xref: /third_party/node/deps/v8/src/objects/objects.cc (revision 1cb0ef41)
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/objects.h"
6
7#include <algorithm>
8#include <cmath>
9#include <memory>
10#include <sstream>
11#include <vector>
12
13#include "src/api/api-arguments-inl.h"
14#include "src/api/api-natives.h"
15#include "src/api/api.h"
16#include "src/ast/ast.h"
17#include "src/ast/scopes.h"
18#include "src/base/bits.h"
19#include "src/base/debug/stack_trace.h"
20#include "src/base/overflowing-math.h"
21#include "src/base/utils/random-number-generator.h"
22#include "src/builtins/accessors.h"
23#include "src/builtins/builtins.h"
24#include "src/codegen/compiler.h"
25#include "src/common/globals.h"
26#include "src/common/message-template.h"
27#include "src/date/date.h"
28#include "src/debug/debug.h"
29#include "src/diagnostics/code-tracer.h"
30#include "src/execution/arguments.h"
31#include "src/execution/execution.h"
32#include "src/execution/frames-inl.h"
33#include "src/execution/isolate-inl.h"
34#include "src/execution/isolate-utils-inl.h"
35#include "src/execution/isolate-utils.h"
36#include "src/execution/microtask-queue.h"
37#include "src/execution/protectors-inl.h"
38#include "src/heap/factory-inl.h"
39#include "src/heap/heap-inl.h"
40#include "src/heap/local-factory-inl.h"
41#include "src/heap/read-only-heap.h"
42#include "src/ic/ic.h"
43#include "src/init/bootstrapper.h"
44#include "src/logging/counters.h"
45#include "src/logging/log.h"
46#include "src/logging/runtime-call-stats-scope.h"
47#include "src/objects/allocation-site-inl.h"
48#include "src/objects/allocation-site-scopes.h"
49#include "src/objects/api-callbacks.h"
50#include "src/objects/arguments-inl.h"
51#include "src/objects/bigint.h"
52#include "src/objects/call-site-info-inl.h"
53#include "src/objects/cell-inl.h"
54#include "src/objects/code-inl.h"
55#include "src/objects/compilation-cache-table-inl.h"
56#include "src/objects/debug-objects-inl.h"
57#include "src/objects/elements.h"
58#include "src/objects/embedder-data-array-inl.h"
59#include "src/objects/field-index-inl.h"
60#include "src/objects/field-index.h"
61#include "src/objects/field-type.h"
62#include "src/objects/foreign.h"
63#include "src/objects/free-space-inl.h"
64#include "src/objects/function-kind.h"
65#include "src/objects/hash-table-inl.h"
66#include "src/objects/instance-type.h"
67#include "src/objects/js-array-buffer-inl.h"
68#include "src/objects/js-array-inl.h"
69#include "src/objects/keys.h"
70#include "src/objects/lookup-inl.h"
71#include "src/objects/map-updater.h"
72#include "src/objects/objects-body-descriptors-inl.h"
73#include "src/objects/objects-inl.h"
74#include "src/objects/property-details.h"
75#include "src/roots/roots.h"
76#include "src/snapshot/deserializer.h"
77#include "src/utils/identity-map.h"
78#ifdef V8_INTL_SUPPORT
79#include "src/objects/js-break-iterator.h"
80#include "src/objects/js-collator.h"
81#endif  // V8_INTL_SUPPORT
82#include "src/objects/js-collection-inl.h"
83#ifdef V8_INTL_SUPPORT
84#include "src/objects/js-date-time-format.h"
85#endif  // V8_INTL_SUPPORT
86#include "src/objects/js-generator-inl.h"
87#ifdef V8_INTL_SUPPORT
88#include "src/objects/js-list-format.h"
89#include "src/objects/js-locale.h"
90#include "src/objects/js-number-format.h"
91#include "src/objects/js-plural-rules.h"
92#endif  // V8_INTL_SUPPORT
93#include "src/objects/js-regexp-inl.h"
94#include "src/objects/js-regexp-string-iterator.h"
95#ifdef V8_INTL_SUPPORT
96#include "src/objects/js-relative-time-format.h"
97#include "src/objects/js-segment-iterator.h"
98#include "src/objects/js-segmenter.h"
99#include "src/objects/js-segments.h"
100#endif  // V8_INTL_SUPPORT
101#include "src/codegen/source-position-table.h"
102#include "src/objects/js-weak-refs-inl.h"
103#include "src/objects/literal-objects-inl.h"
104#include "src/objects/map-inl.h"
105#include "src/objects/map.h"
106#include "src/objects/megadom-handler-inl.h"
107#include "src/objects/microtask-inl.h"
108#include "src/objects/module-inl.h"
109#include "src/objects/promise-inl.h"
110#include "src/objects/property-descriptor-object-inl.h"
111#include "src/objects/property-descriptor.h"
112#include "src/objects/prototype.h"
113#include "src/objects/slots-atomic-inl.h"
114#include "src/objects/string-comparator.h"
115#include "src/objects/string-set-inl.h"
116#include "src/objects/struct-inl.h"
117#include "src/objects/template-objects-inl.h"
118#include "src/objects/transitions-inl.h"
119#include "src/parsing/preparse-data.h"
120#include "src/regexp/regexp.h"
121#include "src/strings/string-builder-inl.h"
122#include "src/strings/string-search.h"
123#include "src/strings/string-stream.h"
124#include "src/strings/unicode-decoder.h"
125#include "src/strings/unicode-inl.h"
126#include "src/utils/ostreams.h"
127#include "src/utils/utils-inl.h"
128#include "src/zone/zone.h"
129
130#if V8_ENABLE_WEBASSEMBLY
131#include "src/wasm/wasm-objects.h"
132#endif  // V8_ENABLE_WEBASSEMBLY
133
134namespace v8 {
135namespace internal {
136
137ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw) {
138  if (should_throw.IsJust()) return should_throw.FromJust();
139
140  LanguageMode mode = isolate->context().scope_info().language_mode();
141  if (mode == LanguageMode::kStrict) return kThrowOnError;
142
143  for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
144    if (!(it.frame()->is_optimized() || it.frame()->is_unoptimized())) {
145      continue;
146    }
147    // Get the language mode from closure.
148    JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(it.frame());
149    std::vector<SharedFunctionInfo> functions;
150    js_frame->GetFunctions(&functions);
151    LanguageMode closure_language_mode = functions.back().language_mode();
152    if (closure_language_mode > mode) {
153      mode = closure_language_mode;
154    }
155    break;
156  }
157
158  return is_sloppy(mode) ? kDontThrow : kThrowOnError;
159}
160
161bool ComparisonResultToBool(Operation op, ComparisonResult result) {
162  switch (op) {
163    case Operation::kLessThan:
164      return result == ComparisonResult::kLessThan;
165    case Operation::kLessThanOrEqual:
166      return result == ComparisonResult::kLessThan ||
167             result == ComparisonResult::kEqual;
168    case Operation::kGreaterThan:
169      return result == ComparisonResult::kGreaterThan;
170    case Operation::kGreaterThanOrEqual:
171      return result == ComparisonResult::kGreaterThan ||
172             result == ComparisonResult::kEqual;
173    default:
174      break;
175  }
176  UNREACHABLE();
177}
178
179std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
180  switch (instance_type) {
181#define WRITE_TYPE(TYPE) \
182  case TYPE:             \
183    return os << #TYPE;
184    INSTANCE_TYPE_LIST(WRITE_TYPE)
185#undef WRITE_TYPE
186  }
187  UNREACHABLE();
188}
189
190std::ostream& operator<<(std::ostream& os, PropertyCellType type) {
191  switch (type) {
192    case PropertyCellType::kUndefined:
193      return os << "Undefined";
194    case PropertyCellType::kConstant:
195      return os << "Constant";
196    case PropertyCellType::kConstantType:
197      return os << "ConstantType";
198    case PropertyCellType::kMutable:
199      return os << "Mutable";
200    case PropertyCellType::kInTransition:
201      return os << "InTransition";
202  }
203  UNREACHABLE();
204}
205
206Handle<FieldType> Object::OptimalType(Isolate* isolate,
207                                      Representation representation) {
208  if (representation.IsNone()) return FieldType::None(isolate);
209  if (FLAG_track_field_types) {
210    if (representation.IsHeapObject() && IsHeapObject()) {
211      // We can track only JavaScript objects with stable maps.
212      Handle<Map> map(HeapObject::cast(*this).map(), isolate);
213      if (map->is_stable() && map->IsJSReceiverMap()) {
214        return FieldType::Class(map, isolate);
215      }
216    }
217  }
218  return FieldType::Any(isolate);
219}
220
221Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
222                                     Representation representation) {
223  if (!representation.IsDouble()) return object;
224  auto result = isolate->factory()->NewHeapNumberWithHoleNaN();
225  if (object->IsUninitialized(isolate)) {
226    result->set_value_as_bits(kHoleNanInt64, kRelaxedStore);
227  } else if (object->IsHeapNumber()) {
228    // Ensure that all bits of the double value are preserved.
229    result->set_value_as_bits(
230        HeapNumber::cast(*object).value_as_bits(kRelaxedLoad), kRelaxedStore);
231  } else {
232    result->set_value(object->Number(), kRelaxedStore);
233  }
234  return result;
235}
236
237template <AllocationType allocation_type, typename IsolateT>
238Handle<Object> Object::WrapForRead(IsolateT* isolate, Handle<Object> object,
239                                   Representation representation) {
240  DCHECK(!object->IsUninitialized(isolate));
241  if (!representation.IsDouble()) {
242    DCHECK(object->FitsRepresentation(representation));
243    return object;
244  }
245  return isolate->factory()->template NewHeapNumberFromBits<allocation_type>(
246      HeapNumber::cast(*object).value_as_bits(kRelaxedLoad));
247}
248
249template Handle<Object> Object::WrapForRead<AllocationType::kYoung>(
250    Isolate* isolate, Handle<Object> object, Representation representation);
251template Handle<Object> Object::WrapForRead<AllocationType::kOld>(
252    LocalIsolate* isolate, Handle<Object> object,
253    Representation representation);
254
255MaybeHandle<JSReceiver> Object::ToObjectImpl(Isolate* isolate,
256                                             Handle<Object> object,
257                                             const char* method_name) {
258  DCHECK(!object->IsJSReceiver());  // Use ToObject() for fast path.
259  Handle<Context> native_context = isolate->native_context();
260  Handle<JSFunction> constructor;
261  if (object->IsSmi()) {
262    constructor = handle(native_context->number_function(), isolate);
263  } else {
264    int constructor_function_index =
265        Handle<HeapObject>::cast(object)->map().GetConstructorFunctionIndex();
266    if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
267      if (method_name != nullptr) {
268        THROW_NEW_ERROR(
269            isolate,
270            NewTypeError(
271                MessageTemplate::kCalledOnNullOrUndefined,
272                isolate->factory()->NewStringFromAsciiChecked(method_name)),
273            JSReceiver);
274      }
275      THROW_NEW_ERROR(isolate,
276                      NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
277                      JSReceiver);
278    }
279    constructor = handle(
280        JSFunction::cast(native_context->get(constructor_function_index)),
281        isolate);
282  }
283  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
284  Handle<JSPrimitiveWrapper>::cast(result)->set_value(*object);
285  return result;
286}
287
288// ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
289// static
290MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
291                                                Handle<Object> object) {
292  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
293  if (object->IsNullOrUndefined(isolate)) {
294    return isolate->global_proxy();
295  }
296  return Object::ToObject(isolate, object);
297}
298
299// static
300MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
301                                                     Handle<Object> input,
302                                                     Conversion mode) {
303  while (true) {
304    if (input->IsNumber()) {
305      return input;
306    }
307    if (input->IsString()) {
308      return String::ToNumber(isolate, Handle<String>::cast(input));
309    }
310    if (input->IsOddball()) {
311      return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
312    }
313    if (input->IsSymbol()) {
314      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
315                      Object);
316    }
317    if (input->IsBigInt()) {
318      if (mode == Conversion::kToNumeric) return input;
319      DCHECK_EQ(mode, Conversion::kToNumber);
320      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
321                      Object);
322    }
323    ASSIGN_RETURN_ON_EXCEPTION(
324        isolate, input,
325        JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(input),
326                                ToPrimitiveHint::kNumber),
327        Object);
328  }
329}
330
331// static
332MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
333                                             Handle<Object> input) {
334  ASSIGN_RETURN_ON_EXCEPTION(
335      isolate, input,
336      ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
337  if (input->IsSmi()) return input;
338  return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
339}
340
341// static
342MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
343                                           Handle<Object> input) {
344  ASSIGN_RETURN_ON_EXCEPTION(
345      isolate, input,
346      ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
347  if (input->IsSmi()) return input;
348  return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
349}
350
351// static
352MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
353                                            Handle<Object> input) {
354  ASSIGN_RETURN_ON_EXCEPTION(
355      isolate, input,
356      ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
357  if (input->IsSmi()) return handle(Smi::cast(*input).ToUint32Smi(), isolate);
358  return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
359}
360
361// static
362MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
363                                        Handle<Object> input) {
364  ASSIGN_RETURN_ON_EXCEPTION(
365      isolate, input,
366      Object::ToPrimitive(isolate, input, ToPrimitiveHint::kString), Name);
367  if (input->IsName()) return Handle<Name>::cast(input);
368  return ToString(isolate, input);
369}
370
371// ES6 7.1.14
372// static
373MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
374                                                 Handle<Object> value) {
375  // 1. Let key be ToPrimitive(argument, hint String).
376  MaybeHandle<Object> maybe_key =
377      Object::ToPrimitive(isolate, value, ToPrimitiveHint::kString);
378  // 2. ReturnIfAbrupt(key).
379  Handle<Object> key;
380  if (!maybe_key.ToHandle(&key)) return key;
381  // 3. If Type(key) is Symbol, then return key.
382  if (key->IsSymbol()) return key;
383  // 4. Return ToString(key).
384  // Extending spec'ed behavior, we'd be happy to return an element index.
385  if (key->IsSmi()) return key;
386  if (key->IsHeapNumber()) {
387    uint32_t uint_value;
388    if (value->ToArrayLength(&uint_value) &&
389        uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
390      return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
391    }
392  }
393  return Object::ToString(isolate, key);
394}
395
396// static
397MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
398                                            Handle<Object> input) {
399  while (true) {
400    if (input->IsOddball()) {
401      return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
402    }
403    if (input->IsNumber()) {
404      return isolate->factory()->NumberToString(input);
405    }
406    if (input->IsSymbol()) {
407      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
408                      String);
409    }
410    if (input->IsBigInt()) {
411      return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
412    }
413    ASSIGN_RETURN_ON_EXCEPTION(
414        isolate, input,
415        JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(input),
416                                ToPrimitiveHint::kString),
417        String);
418    // The previous isString() check happened in Object::ToString and thus we
419    // put it at the end of the loop in this helper.
420    if (input->IsString()) {
421      return Handle<String>::cast(input);
422    }
423  }
424}
425
426namespace {
427
428bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
429  if (!object->IsJSReceiver()) return false;
430  Handle<Symbol> symbol = isolate->factory()->error_stack_symbol();
431  return JSReceiver::HasOwnProperty(isolate, Handle<JSReceiver>::cast(object),
432                                    symbol)
433      .FromMaybe(false);
434}
435
436Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
437  return object->IsString() ? Handle<String>::cast(object)
438                            : isolate->factory()->empty_string();
439}
440
441Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
442                                          Handle<JSReceiver> error) {
443  Handle<Name> name_key = isolate->factory()->name_string();
444  Handle<Object> name = JSReceiver::GetDataProperty(isolate, error, name_key);
445  Handle<String> name_str = AsStringOrEmpty(isolate, name);
446
447  Handle<Name> msg_key = isolate->factory()->message_string();
448  Handle<Object> msg = JSReceiver::GetDataProperty(isolate, error, msg_key);
449  Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
450
451  if (name_str->length() == 0) return msg_str;
452  if (msg_str->length() == 0) return name_str;
453
454  IncrementalStringBuilder builder(isolate);
455  builder.AppendString(name_str);
456  builder.AppendCStringLiteral(": ");
457
458  if (builder.Length() + msg_str->length() <= String::kMaxLength) {
459    builder.AppendString(msg_str);
460  } else {
461    builder.AppendCStringLiteral("<a very large string>");
462  }
463
464  return builder.Finish().ToHandleChecked();
465}
466
467}  // namespace
468
469// static
470MaybeHandle<String> Object::NoSideEffectsToMaybeString(Isolate* isolate,
471                                                       Handle<Object> input) {
472  DisallowJavascriptExecution no_js(isolate);
473
474  if (input->IsString() || input->IsNumber() || input->IsOddball()) {
475    return Object::ToString(isolate, input).ToHandleChecked();
476  } else if (input->IsJSProxy()) {
477    Handle<Object> currInput = input;
478    do {
479      HeapObject target = Handle<JSProxy>::cast(currInput)->target(isolate);
480      currInput = Handle<Object>(target, isolate);
481    } while (currInput->IsJSProxy());
482    return NoSideEffectsToString(isolate, currInput);
483  } else if (input->IsBigInt()) {
484    MaybeHandle<String> maybe_string =
485        BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
486    Handle<String> result;
487    if (maybe_string.ToHandle(&result)) return result;
488    // BigInt-to-String conversion can fail on 32-bit platforms where
489    // String::kMaxLength is too small to fit this BigInt.
490    return isolate->factory()->NewStringFromStaticChars(
491        "<a very large BigInt>");
492  } else if (input->IsFunction()) {
493    // -- F u n c t i o n
494    Handle<String> fun_str;
495    if (input->IsJSBoundFunction()) {
496      fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
497    } else if (input->IsJSWrappedFunction()) {
498      fun_str =
499          JSWrappedFunction::ToString(Handle<JSWrappedFunction>::cast(input));
500    } else {
501      DCHECK(input->IsJSFunction());
502      fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
503    }
504
505    if (fun_str->length() > 128) {
506      IncrementalStringBuilder builder(isolate);
507      builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
508      builder.AppendCStringLiteral("...<omitted>...");
509      builder.AppendString(isolate->factory()->NewSubString(
510          fun_str, fun_str->length() - 2, fun_str->length()));
511
512      return builder.Finish().ToHandleChecked();
513    }
514    return fun_str;
515  } else if (input->IsSymbol()) {
516    // -- S y m b o l
517    Handle<Symbol> symbol = Handle<Symbol>::cast(input);
518
519    if (symbol->is_private_name()) {
520      return Handle<String>(String::cast(symbol->description()), isolate);
521    }
522
523    IncrementalStringBuilder builder(isolate);
524    builder.AppendCStringLiteral("Symbol(");
525    if (symbol->description().IsString()) {
526      builder.AppendString(
527          handle(String::cast(symbol->description()), isolate));
528    }
529    builder.AppendCharacter(')');
530
531    return builder.Finish().ToHandleChecked();
532  } else if (input->IsJSReceiver()) {
533    // -- J S R e c e i v e r
534    Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
535    Handle<Object> to_string = JSReceiver::GetDataProperty(
536        isolate, receiver, isolate->factory()->toString_string());
537
538    if (IsErrorObject(isolate, input) ||
539        *to_string == *isolate->error_to_string()) {
540      // When internally formatting error objects, use a side-effects-free
541      // version of Error.prototype.toString independent of the actually
542      // installed toString method.
543      return NoSideEffectsErrorToString(isolate,
544                                        Handle<JSReceiver>::cast(input));
545    } else if (*to_string == *isolate->object_to_string()) {
546      Handle<Object> ctor = JSReceiver::GetDataProperty(
547          isolate, receiver, isolate->factory()->constructor_string());
548      if (ctor->IsFunction()) {
549        Handle<String> ctor_name;
550        if (ctor->IsJSBoundFunction()) {
551          ctor_name = JSBoundFunction::GetName(
552                          isolate, Handle<JSBoundFunction>::cast(ctor))
553                          .ToHandleChecked();
554        } else if (ctor->IsJSFunction()) {
555          ctor_name =
556              JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
557        }
558
559        if (ctor_name->length() != 0) {
560          IncrementalStringBuilder builder(isolate);
561          builder.AppendCStringLiteral("#<");
562          builder.AppendString(ctor_name);
563          builder.AppendCharacter('>');
564
565          return builder.Finish().ToHandleChecked();
566        }
567      }
568    }
569  }
570  return MaybeHandle<String>(kNullMaybeHandle);
571}
572
573// static
574Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
575                                             Handle<Object> input) {
576  DisallowJavascriptExecution no_js(isolate);
577
578  // Try to convert input to a meaningful string.
579  MaybeHandle<String> maybe_string = NoSideEffectsToMaybeString(isolate, input);
580  Handle<String> string_handle;
581  if (maybe_string.ToHandle(&string_handle)) {
582    return string_handle;
583  }
584
585  // At this point, input is either none of the above or a JSReceiver.
586
587  Handle<JSReceiver> receiver;
588  if (input->IsJSReceiver()) {
589    receiver = Handle<JSReceiver>::cast(input);
590  } else {
591    // This is the only case where Object::ToObject throws.
592    DCHECK(!input->IsSmi());
593    int constructor_function_index =
594        Handle<HeapObject>::cast(input)->map().GetConstructorFunctionIndex();
595    if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
596      return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
597    }
598
599    receiver = Object::ToObjectImpl(isolate, input).ToHandleChecked();
600  }
601
602  Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
603  Handle<Object> tag_obj = JSReceiver::GetDataProperty(
604      isolate, receiver, isolate->factory()->to_string_tag_symbol());
605  Handle<String> tag =
606      tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
607
608  IncrementalStringBuilder builder(isolate);
609  builder.AppendCStringLiteral("[object ");
610  builder.AppendString(tag);
611  builder.AppendCharacter(']');
612
613  return builder.Finish().ToHandleChecked();
614}
615
616// static
617MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
618                                            Handle<Object> input) {
619  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
620  if (input->IsSmi()) {
621    int value = std::max(Smi::ToInt(*input), 0);
622    return handle(Smi::FromInt(value), isolate);
623  }
624  double len = DoubleToInteger(input->Number());
625  if (len <= 0.0) {
626    return handle(Smi::zero(), isolate);
627  } else if (len >= kMaxSafeInteger) {
628    len = kMaxSafeInteger;
629  }
630  return isolate->factory()->NewNumber(len);
631}
632
633// static
634MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
635                                           Handle<Object> input,
636                                           MessageTemplate error_index) {
637  if (input->IsUndefined(isolate)) return handle(Smi::zero(), isolate);
638  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
639  if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
640  double len = DoubleToInteger(input->Number());
641  auto js_len = isolate->factory()->NewNumber(len);
642  if (len < 0.0 || len > kMaxSafeInteger) {
643    THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
644  }
645  return js_len;
646}
647
648bool Object::BooleanValue(Isolate* isolate) {
649  if (IsSmi()) return Smi::ToInt(*this) != 0;
650  DCHECK(IsHeapObject());
651  if (IsBoolean()) return IsTrue(isolate);
652  if (IsNullOrUndefined(isolate)) return false;
653  if (IsUndetectable()) return false;  // Undetectable object is false.
654  if (IsString()) return String::cast(*this).length() != 0;
655  if (IsHeapNumber()) return DoubleToBoolean(HeapNumber::cast(*this).value());
656  if (IsBigInt()) return BigInt::cast(*this).ToBoolean();
657  return true;
658}
659
660Object Object::ToBoolean(Isolate* isolate) {
661  if (IsBoolean()) return *this;
662  return isolate->heap()->ToBoolean(BooleanValue(isolate));
663}
664
665namespace {
666
667// TODO(bmeurer): Maybe we should introduce a marker interface Number,
668// where we put all these methods at some point?
669ComparisonResult StrictNumberCompare(double x, double y) {
670  if (std::isnan(x) || std::isnan(y)) {
671    return ComparisonResult::kUndefined;
672  } else if (x < y) {
673    return ComparisonResult::kLessThan;
674  } else if (x > y) {
675    return ComparisonResult::kGreaterThan;
676  } else {
677    return ComparisonResult::kEqual;
678  }
679}
680
681// See Number case of ES6#sec-strict-equality-comparison
682// Returns false if x or y is NaN, treats -0.0 as equal to 0.0.
683bool StrictNumberEquals(double x, double y) {
684  // Must check explicitly for NaN's on Windows, but -0 works fine.
685  if (std::isnan(x) || std::isnan(y)) return false;
686  return x == y;
687}
688
689bool StrictNumberEquals(const Object x, const Object y) {
690  return StrictNumberEquals(x.Number(), y.Number());
691}
692
693bool StrictNumberEquals(Handle<Object> x, Handle<Object> y) {
694  return StrictNumberEquals(*x, *y);
695}
696
697ComparisonResult Reverse(ComparisonResult result) {
698  if (result == ComparisonResult::kLessThan) {
699    return ComparisonResult::kGreaterThan;
700  }
701  if (result == ComparisonResult::kGreaterThan) {
702    return ComparisonResult::kLessThan;
703  }
704  return result;
705}
706
707}  // anonymous namespace
708
709// static
710Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
711                                        Handle<Object> y) {
712  // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
713  if (!Object::ToPrimitive(isolate, x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
714      !Object::ToPrimitive(isolate, y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
715    return Nothing<ComparisonResult>();
716  }
717  if (x->IsString() && y->IsString()) {
718    // ES6 section 7.2.11 Abstract Relational Comparison step 5.
719    return Just(String::Compare(isolate, Handle<String>::cast(x),
720                                Handle<String>::cast(y)));
721  }
722  if (x->IsBigInt() && y->IsString()) {
723    return BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
724                                   Handle<String>::cast(y));
725  }
726  if (x->IsString() && y->IsBigInt()) {
727    Maybe<ComparisonResult> maybe_result = BigInt::CompareToString(
728        isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x));
729    ComparisonResult result;
730    if (maybe_result.To(&result)) {
731      return Just(Reverse(result));
732    } else {
733      return Nothing<ComparisonResult>();
734    }
735  }
736  // ES6 section 7.2.11 Abstract Relational Comparison step 6.
737  if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
738      !Object::ToNumeric(isolate, y).ToHandle(&y)) {
739    return Nothing<ComparisonResult>();
740  }
741
742  bool x_is_number = x->IsNumber();
743  bool y_is_number = y->IsNumber();
744  if (x_is_number && y_is_number) {
745    return Just(StrictNumberCompare(x->Number(), y->Number()));
746  } else if (!x_is_number && !y_is_number) {
747    return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
748                                        Handle<BigInt>::cast(y)));
749  } else if (x_is_number) {
750    return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
751  } else {
752    return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
753  }
754}
755
756// static
757Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
758                           Handle<Object> y) {
759  // This is the generic version of Abstract Equality Comparison. Must be in
760  // sync with CodeStubAssembler::Equal.
761  while (true) {
762    if (x->IsNumber()) {
763      if (y->IsNumber()) {
764        return Just(StrictNumberEquals(x, y));
765      } else if (y->IsBoolean()) {
766        return Just(
767            StrictNumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
768      } else if (y->IsString()) {
769        return Just(StrictNumberEquals(
770            x, String::ToNumber(isolate, Handle<String>::cast(y))));
771      } else if (y->IsBigInt()) {
772        return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
773      } else if (y->IsJSReceiver()) {
774        if (!JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(y))
775                 .ToHandle(&y)) {
776          return Nothing<bool>();
777        }
778      } else {
779        return Just(false);
780      }
781    } else if (x->IsString()) {
782      if (y->IsString()) {
783        return Just(String::Equals(isolate, Handle<String>::cast(x),
784                                   Handle<String>::cast(y)));
785      } else if (y->IsNumber()) {
786        x = String::ToNumber(isolate, Handle<String>::cast(x));
787        return Just(StrictNumberEquals(x, y));
788      } else if (y->IsBoolean()) {
789        x = String::ToNumber(isolate, Handle<String>::cast(x));
790        return Just(
791            StrictNumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
792      } else if (y->IsBigInt()) {
793        return BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
794                                     Handle<String>::cast(x));
795      } else if (y->IsJSReceiver()) {
796        if (!JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(y))
797                 .ToHandle(&y)) {
798          return Nothing<bool>();
799        }
800      } else {
801        return Just(false);
802      }
803    } else if (x->IsBoolean()) {
804      if (y->IsOddball()) {
805        return Just(x.is_identical_to(y));
806      } else if (y->IsNumber()) {
807        return Just(
808            StrictNumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
809      } else if (y->IsString()) {
810        y = String::ToNumber(isolate, Handle<String>::cast(y));
811        return Just(
812            StrictNumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
813      } else if (y->IsBigInt()) {
814        x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
815        return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
816      } else if (y->IsJSReceiver()) {
817        if (!JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(y))
818                 .ToHandle(&y)) {
819          return Nothing<bool>();
820        }
821        x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
822      } else {
823        return Just(false);
824      }
825    } else if (x->IsSymbol()) {
826      if (y->IsSymbol()) {
827        return Just(x.is_identical_to(y));
828      } else if (y->IsJSReceiver()) {
829        if (!JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(y))
830                 .ToHandle(&y)) {
831          return Nothing<bool>();
832        }
833      } else {
834        return Just(false);
835      }
836    } else if (x->IsBigInt()) {
837      if (y->IsBigInt()) {
838        return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
839      }
840      return Equals(isolate, y, x);
841    } else if (x->IsJSReceiver()) {
842      if (y->IsJSReceiver()) {
843        return Just(x.is_identical_to(y));
844      } else if (y->IsUndetectable()) {
845        return Just(x->IsUndetectable());
846      } else if (y->IsBoolean()) {
847        y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
848      } else if (!JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(x))
849                      .ToHandle(&x)) {
850        return Nothing<bool>();
851      }
852    } else {
853      return Just(x->IsUndetectable() && y->IsUndetectable());
854    }
855  }
856}
857
858bool Object::StrictEquals(Object that) {
859  if (this->IsNumber()) {
860    if (!that.IsNumber()) return false;
861    return StrictNumberEquals(*this, that);
862  } else if (this->IsString()) {
863    if (!that.IsString()) return false;
864    return String::cast(*this).Equals(String::cast(that));
865  } else if (this->IsBigInt()) {
866    if (!that.IsBigInt()) return false;
867    return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(that));
868  }
869  return *this == that;
870}
871
872// static
873Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
874  if (object->IsNumber()) return isolate->factory()->number_string();
875  if (object->IsOddball())
876    return handle(Oddball::cast(*object).type_of(), isolate);
877  if (object->IsUndetectable()) {
878    return isolate->factory()->undefined_string();
879  }
880  if (object->IsString()) return isolate->factory()->string_string();
881  if (object->IsSymbol()) return isolate->factory()->symbol_string();
882  if (object->IsBigInt()) return isolate->factory()->bigint_string();
883  if (object->IsCallable()) return isolate->factory()->function_string();
884  return isolate->factory()->object_string();
885}
886
887// static
888MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
889                                Handle<Object> rhs) {
890  if (lhs->IsNumber() && rhs->IsNumber()) {
891    return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
892  } else if (lhs->IsString() && rhs->IsString()) {
893    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
894                                             Handle<String>::cast(rhs));
895  }
896  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(isolate, lhs),
897                             Object);
898  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(isolate, rhs),
899                             Object);
900  if (lhs->IsString() || rhs->IsString()) {
901    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
902                               Object);
903    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
904                               Object);
905    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
906                                             Handle<String>::cast(rhs));
907  }
908  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
909                             Object);
910  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
911                             Object);
912  return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
913}
914
915// static
916MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
917                                                Handle<Object> callable,
918                                                Handle<Object> object) {
919  // The {callable} must have a [[Call]] internal method.
920  if (!callable->IsCallable()) return isolate->factory()->false_value();
921
922  // Check if {callable} is a bound function, and if so retrieve its
923  // [[BoundTargetFunction]] and use that instead of {callable}.
924  if (callable->IsJSBoundFunction()) {
925    // Since there is a mutual recursion here, we might run out of stack
926    // space for long chains of bound functions.
927    STACK_CHECK(isolate, MaybeHandle<Object>());
928    Handle<Object> bound_callable(
929        Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
930        isolate);
931    return Object::InstanceOf(isolate, object, bound_callable);
932  }
933
934  // If {object} is not a receiver, return false.
935  if (!object->IsJSReceiver()) return isolate->factory()->false_value();
936
937  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
938  Handle<Object> prototype;
939  ASSIGN_RETURN_ON_EXCEPTION(
940      isolate, prototype,
941      Object::GetProperty(isolate, callable,
942                          isolate->factory()->prototype_string()),
943      Object);
944  if (!prototype->IsJSReceiver()) {
945    THROW_NEW_ERROR(
946        isolate,
947        NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
948        Object);
949  }
950
951  // Return whether or not {prototype} is in the prototype chain of {object}.
952  Maybe<bool> result = JSReceiver::HasInPrototypeChain(
953      isolate, Handle<JSReceiver>::cast(object), prototype);
954  if (result.IsNothing()) return MaybeHandle<Object>();
955  return isolate->factory()->ToBoolean(result.FromJust());
956}
957
958// static
959MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
960                                       Handle<Object> callable) {
961  // The {callable} must be a receiver.
962  if (!callable->IsJSReceiver()) {
963    THROW_NEW_ERROR(isolate,
964                    NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
965                    Object);
966  }
967
968  // Lookup the @@hasInstance method on {callable}.
969  Handle<Object> inst_of_handler;
970  ASSIGN_RETURN_ON_EXCEPTION(
971      isolate, inst_of_handler,
972      Object::GetMethod(Handle<JSReceiver>::cast(callable),
973                        isolate->factory()->has_instance_symbol()),
974      Object);
975  if (!inst_of_handler->IsUndefined(isolate)) {
976    // Call the {inst_of_handler} on the {callable}.
977    Handle<Object> result;
978    ASSIGN_RETURN_ON_EXCEPTION(
979        isolate, result,
980        Execution::Call(isolate, inst_of_handler, callable, 1, &object),
981        Object);
982    return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
983  }
984
985  // The {callable} must have a [[Call]] internal method.
986  if (!callable->IsCallable()) {
987    THROW_NEW_ERROR(
988        isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
989        Object);
990  }
991
992  // Fall back to OrdinaryHasInstance with {callable} and {object}.
993  Handle<Object> result;
994  ASSIGN_RETURN_ON_EXCEPTION(
995      isolate, result, Object::OrdinaryHasInstance(isolate, callable, object),
996      Object);
997  return result;
998}
999
1000// static
1001MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
1002                                      Handle<Name> name) {
1003  Handle<Object> func;
1004  Isolate* isolate = receiver->GetIsolate();
1005  ASSIGN_RETURN_ON_EXCEPTION(
1006      isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
1007  if (func->IsNullOrUndefined(isolate)) {
1008    return isolate->factory()->undefined_value();
1009  }
1010  if (!func->IsCallable()) {
1011    THROW_NEW_ERROR(isolate,
1012                    NewTypeError(MessageTemplate::kPropertyNotFunction, func,
1013                                 name, receiver),
1014                    Object);
1015  }
1016  return func;
1017}
1018
1019namespace {
1020
1021MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
1022    Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
1023  if (element_types == ElementTypes::kAll) {
1024    if (object->IsJSArray()) {
1025      Handle<JSArray> array = Handle<JSArray>::cast(object);
1026      uint32_t length;
1027      if (!array->HasArrayPrototype(isolate) ||
1028          !array->length().ToUint32(&length) || !array->HasFastElements() ||
1029          !JSObject::PrototypeHasNoElements(isolate, *array)) {
1030        return MaybeHandle<FixedArray>();
1031      }
1032      return array->GetElementsAccessor()->CreateListFromArrayLike(
1033          isolate, array, length);
1034    } else if (object->IsJSTypedArray()) {
1035      Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
1036      size_t length = array->length();
1037      if (array->WasDetached() ||
1038          length > static_cast<size_t>(FixedArray::kMaxLength)) {
1039        return MaybeHandle<FixedArray>();
1040      }
1041      STATIC_ASSERT(FixedArray::kMaxLength <=
1042                    std::numeric_limits<uint32_t>::max());
1043      return array->GetElementsAccessor()->CreateListFromArrayLike(
1044          isolate, array, static_cast<uint32_t>(length));
1045    }
1046  }
1047  return MaybeHandle<FixedArray>();
1048}
1049
1050}  // namespace
1051
1052// static
1053MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
1054    Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
1055  // Fast-path for JSArray and JSTypedArray.
1056  MaybeHandle<FixedArray> fast_result =
1057      CreateListFromArrayLikeFastPath(isolate, object, element_types);
1058  if (!fast_result.is_null()) return fast_result;
1059  // 1. ReturnIfAbrupt(object).
1060  // 2. (default elementTypes -- not applicable.)
1061  // 3. If Type(obj) is not Object, throw a TypeError exception.
1062  if (!object->IsJSReceiver()) {
1063    THROW_NEW_ERROR(isolate,
1064                    NewTypeError(MessageTemplate::kCalledOnNonObject,
1065                                 isolate->factory()->NewStringFromAsciiChecked(
1066                                     "CreateListFromArrayLike")),
1067                    FixedArray);
1068  }
1069
1070  // 4. Let len be ? ToLength(? Get(obj, "length")).
1071  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
1072  Handle<Object> raw_length_number;
1073  ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
1074                             Object::GetLengthFromArrayLike(isolate, receiver),
1075                             FixedArray);
1076  uint32_t len;
1077  if (!raw_length_number->ToUint32(&len) ||
1078      len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
1079    THROW_NEW_ERROR(isolate,
1080                    NewRangeError(MessageTemplate::kInvalidArrayLength),
1081                    FixedArray);
1082  }
1083  // 5. Let list be an empty List.
1084  Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
1085  // 6. Let index be 0.
1086  // 7. Repeat while index < len:
1087  for (uint32_t index = 0; index < len; ++index) {
1088    // 7a. Let indexName be ToString(index).
1089    // 7b. Let next be ? Get(obj, indexName).
1090    Handle<Object> next;
1091    ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
1092                               JSReceiver::GetElement(isolate, receiver, index),
1093                               FixedArray);
1094    switch (element_types) {
1095      case ElementTypes::kAll:
1096        // Nothing to do.
1097        break;
1098      case ElementTypes::kStringAndSymbol: {
1099        // 7c. If Type(next) is not an element of elementTypes, throw a
1100        //     TypeError exception.
1101        if (!next->IsName()) {
1102          THROW_NEW_ERROR(isolate,
1103                          NewTypeError(MessageTemplate::kNotPropertyName, next),
1104                          FixedArray);
1105        }
1106        // 7d. Append next as the last element of list.
1107        // Internalize on the fly so we can use pointer identity later.
1108        next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
1109        break;
1110      }
1111    }
1112    list->set(index, *next);
1113    // 7e. Set index to index + 1. (See loop header.)
1114  }
1115  // 8. Return list.
1116  return list;
1117}
1118
1119// static
1120MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
1121                                                   Handle<JSReceiver> object) {
1122  Handle<Object> val;
1123  Handle<Name> key = isolate->factory()->length_string();
1124  ASSIGN_RETURN_ON_EXCEPTION(
1125      isolate, val, JSReceiver::GetProperty(isolate, object, key), Object);
1126  return Object::ToLength(isolate, val);
1127}
1128
1129// static
1130MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
1131                                        bool is_global_reference) {
1132  for (; it->IsFound(); it->Next()) {
1133    switch (it->state()) {
1134      case LookupIterator::NOT_FOUND:
1135      case LookupIterator::TRANSITION:
1136        UNREACHABLE();
1137      case LookupIterator::JSPROXY: {
1138        bool was_found;
1139        Handle<Object> receiver = it->GetReceiver();
1140        // In case of global IC, the receiver is the global object. Replace by
1141        // the global proxy.
1142        if (receiver->IsJSGlobalObject()) {
1143          receiver = handle(JSGlobalObject::cast(*receiver).global_proxy(),
1144                            it->isolate());
1145        }
1146        if (is_global_reference) {
1147          Maybe<bool> maybe = JSProxy::HasProperty(
1148              it->isolate(), it->GetHolder<JSProxy>(), it->GetName());
1149          if (maybe.IsNothing()) return MaybeHandle<Object>();
1150          if (!maybe.FromJust()) {
1151            it->NotFound();
1152            return it->isolate()->factory()->undefined_value();
1153          }
1154        }
1155        MaybeHandle<Object> result =
1156            JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
1157                                 it->GetName(), receiver, &was_found);
1158        if (!was_found && !is_global_reference) it->NotFound();
1159        return result;
1160      }
1161      case LookupIterator::INTERCEPTOR: {
1162        bool done;
1163        Handle<Object> result;
1164        ASSIGN_RETURN_ON_EXCEPTION(
1165            it->isolate(), result,
1166            JSObject::GetPropertyWithInterceptor(it, &done), Object);
1167        if (done) return result;
1168        break;
1169      }
1170      case LookupIterator::ACCESS_CHECK:
1171        if (it->HasAccess()) break;
1172        return JSObject::GetPropertyWithFailedAccessCheck(it);
1173      case LookupIterator::ACCESSOR:
1174        return GetPropertyWithAccessor(it);
1175      case LookupIterator::INTEGER_INDEXED_EXOTIC:
1176        return it->isolate()->factory()->undefined_value();
1177      case LookupIterator::DATA:
1178        return it->GetDataValue();
1179    }
1180  }
1181
1182  return it->isolate()->factory()->undefined_value();
1183}
1184
1185// static
1186MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
1187                                         Handle<JSProxy> proxy,
1188                                         Handle<Name> name,
1189                                         Handle<Object> receiver,
1190                                         bool* was_found) {
1191  *was_found = true;
1192
1193  DCHECK(!name->IsPrivate());
1194  STACK_CHECK(isolate, MaybeHandle<Object>());
1195  Handle<Name> trap_name = isolate->factory()->get_string();
1196  // 1. Assert: IsPropertyKey(P) is true.
1197  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1198  Handle<Object> handler(proxy->handler(), isolate);
1199  // 3. If handler is null, throw a TypeError exception.
1200  // 4. Assert: Type(handler) is Object.
1201  if (proxy->IsRevoked()) {
1202    THROW_NEW_ERROR(isolate,
1203                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1204                    Object);
1205  }
1206  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
1207  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1208  // 6. Let trap be ? GetMethod(handler, "get").
1209  Handle<Object> trap;
1210  ASSIGN_RETURN_ON_EXCEPTION(
1211      isolate, trap,
1212      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
1213  // 7. If trap is undefined, then
1214  if (trap->IsUndefined(isolate)) {
1215    // 7.a Return target.[[Get]](P, Receiver).
1216    PropertyKey key(isolate, name);
1217    LookupIterator it(isolate, receiver, key, target);
1218    MaybeHandle<Object> result = Object::GetProperty(&it);
1219    *was_found = it.IsFound();
1220    return result;
1221  }
1222  // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
1223  Handle<Object> trap_result;
1224  Handle<Object> args[] = {target, name, receiver};
1225  ASSIGN_RETURN_ON_EXCEPTION(
1226      isolate, trap_result,
1227      Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
1228
1229  MaybeHandle<Object> result =
1230      JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
1231  if (result.is_null()) {
1232    return result;
1233  }
1234
1235  // 11. Return trap_result
1236  return trap_result;
1237}
1238
1239// static
1240MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
1241                                                   Handle<Name> name,
1242                                                   Handle<JSReceiver> target,
1243                                                   Handle<Object> trap_result,
1244                                                   AccessKind access_kind) {
1245  // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
1246  PropertyDescriptor target_desc;
1247  Maybe<bool> target_found =
1248      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
1249  MAYBE_RETURN_NULL(target_found);
1250  // 10. If targetDesc is not undefined, then
1251  if (target_found.FromJust()) {
1252    // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
1253    //       false and targetDesc.[[Writable]] is false, then
1254    // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
1255    //        throw a TypeError exception.
1256    bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
1257                        !target_desc.configurable() &&
1258                        !target_desc.writable() &&
1259                        !trap_result->SameValue(*target_desc.value());
1260    if (inconsistent) {
1261      if (access_kind == kGet) {
1262        THROW_NEW_ERROR(
1263            isolate,
1264            NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
1265                         target_desc.value(), trap_result),
1266            Object);
1267      } else {
1268        isolate->Throw(*isolate->factory()->NewTypeError(
1269            MessageTemplate::kProxySetFrozenData, name));
1270        return MaybeHandle<Object>();
1271      }
1272    }
1273    // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
1274    //       is false and targetDesc.[[Get]] is undefined, then
1275    // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
1276    if (access_kind == kGet) {
1277      inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1278                     !target_desc.configurable() &&
1279                     target_desc.get()->IsUndefined(isolate) &&
1280                     !trap_result->IsUndefined(isolate);
1281    } else {
1282      inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1283                     !target_desc.configurable() &&
1284                     target_desc.set()->IsUndefined(isolate);
1285    }
1286    if (inconsistent) {
1287      if (access_kind == kGet) {
1288        THROW_NEW_ERROR(
1289            isolate,
1290            NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
1291                         name, trap_result),
1292            Object);
1293      } else {
1294        isolate->Throw(*isolate->factory()->NewTypeError(
1295            MessageTemplate::kProxySetFrozenAccessor, name));
1296        return MaybeHandle<Object>();
1297      }
1298    }
1299  }
1300  return isolate->factory()->undefined_value();
1301}
1302
1303bool Object::ToInt32(int32_t* value) {
1304  if (IsSmi()) {
1305    *value = Smi::ToInt(*this);
1306    return true;
1307  }
1308  if (IsHeapNumber()) {
1309    double num = HeapNumber::cast(*this).value();
1310    // Check range before conversion to avoid undefined behavior.
1311    if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1312      *value = FastD2I(num);
1313      return true;
1314    }
1315  }
1316  return false;
1317}
1318
1319// static
1320Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
1321  Handle<FixedArray> list =
1322      isolate->factory()->NewFixedArray(kLengthIndex + size);
1323  list->set(kLengthIndex, Smi::zero());
1324  return Handle<TemplateList>::cast(list);
1325}
1326
1327// static
1328Handle<TemplateList> TemplateList::Add(Isolate* isolate,
1329                                       Handle<TemplateList> list,
1330                                       Handle<i::Object> value) {
1331  STATIC_ASSERT(kFirstElementIndex == 1);
1332  int index = list->length() + 1;
1333  Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
1334  fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
1335  fixed_array->set(kLengthIndex, Smi::FromInt(index));
1336  return Handle<TemplateList>::cast(fixed_array);
1337}
1338
1339// ES6 9.5.1
1340// static
1341MaybeHandle<HeapObject> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1342  Isolate* isolate = proxy->GetIsolate();
1343  Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1344
1345  STACK_CHECK(isolate, MaybeHandle<HeapObject>());
1346
1347  // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1348  // 2. If handler is null, throw a TypeError exception.
1349  // 3. Assert: Type(handler) is Object.
1350  // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1351  if (proxy->IsRevoked()) {
1352    THROW_NEW_ERROR(isolate,
1353                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1354                    HeapObject);
1355  }
1356  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1357  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1358
1359  // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1360  Handle<Object> trap;
1361  ASSIGN_RETURN_ON_EXCEPTION(isolate, trap,
1362                             Object::GetMethod(handler, trap_name), HeapObject);
1363  // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1364  if (trap->IsUndefined(isolate)) {
1365    return JSReceiver::GetPrototype(isolate, target);
1366  }
1367  // 7. Let handlerProto be ? Call(trap, handler, «target»).
1368  Handle<Object> argv[] = {target};
1369  Handle<Object> handler_proto;
1370  ASSIGN_RETURN_ON_EXCEPTION(
1371      isolate, handler_proto,
1372      Execution::Call(isolate, trap, handler, arraysize(argv), argv),
1373      HeapObject);
1374  // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1375  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1376    THROW_NEW_ERROR(isolate,
1377                    NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1378                    HeapObject);
1379  }
1380  // 9. Let extensibleTarget be ? IsExtensible(target).
1381  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1382  MAYBE_RETURN(is_extensible, MaybeHandle<HeapObject>());
1383  // 10. If extensibleTarget is true, return handlerProto.
1384  if (is_extensible.FromJust()) return Handle<HeapObject>::cast(handler_proto);
1385  // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1386  Handle<HeapObject> target_proto;
1387  ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1388                             JSReceiver::GetPrototype(isolate, target),
1389                             HeapObject);
1390  // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1391  if (!handler_proto->SameValue(*target_proto)) {
1392    THROW_NEW_ERROR(
1393        isolate,
1394        NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1395        HeapObject);
1396  }
1397  // 13. Return handlerProto.
1398  return Handle<HeapObject>::cast(handler_proto);
1399}
1400
1401MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1402  Isolate* isolate = it->isolate();
1403  Handle<Object> structure = it->GetAccessors();
1404  Handle<Object> receiver = it->GetReceiver();
1405  // In case of global IC, the receiver is the global object. Replace by the
1406  // global proxy.
1407  if (receiver->IsJSGlobalObject()) {
1408    receiver = handle(JSGlobalObject::cast(*receiver).global_proxy(), isolate);
1409  }
1410
1411  // We should never get here to initialize a const with the hole value since a
1412  // const declaration would conflict with the getter.
1413  DCHECK(!structure->IsForeign());
1414
1415  // API style callbacks.
1416  Handle<JSObject> holder = it->GetHolder<JSObject>();
1417  if (structure->IsAccessorInfo()) {
1418    Handle<Name> name = it->GetName();
1419    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1420    if (!info->IsCompatibleReceiver(*receiver)) {
1421      THROW_NEW_ERROR(isolate,
1422                      NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1423                                   name, receiver),
1424                      Object);
1425    }
1426
1427    if (!info->has_getter()) return isolate->factory()->undefined_value();
1428
1429    if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1430      ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1431                                 Object::ConvertReceiver(isolate, receiver),
1432                                 Object);
1433    }
1434
1435    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1436                                   Just(kDontThrow));
1437    Handle<Object> result = args.CallAccessorGetter(info, name);
1438    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1439    if (result.is_null()) return isolate->factory()->undefined_value();
1440    Handle<Object> reboxed_result = handle(*result, isolate);
1441    if (info->replace_on_access() && receiver->IsJSReceiver()) {
1442      RETURN_ON_EXCEPTION(isolate,
1443                          Accessors::ReplaceAccessorWithDataProperty(
1444                              isolate, receiver, holder, name, result),
1445                          Object);
1446    }
1447    return reboxed_result;
1448  }
1449
1450  Handle<AccessorPair> accessor_pair = Handle<AccessorPair>::cast(structure);
1451  // AccessorPair with 'cached' private property.
1452  if (it->TryLookupCachedProperty(accessor_pair)) {
1453    return Object::GetProperty(it);
1454  }
1455
1456  // Regular accessor.
1457  Handle<Object> getter(accessor_pair->getter(), isolate);
1458  if (getter->IsFunctionTemplateInfo()) {
1459    SaveAndSwitchContext save(isolate,
1460                              *holder->GetCreationContext().ToHandleChecked());
1461    return Builtins::InvokeApiFunction(
1462        isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1463        nullptr, isolate->factory()->undefined_value());
1464  } else if (getter->IsCallable()) {
1465    // TODO(rossberg): nicer would be to cast to some JSCallable here...
1466    return Object::GetPropertyWithDefinedGetter(
1467        receiver, Handle<JSReceiver>::cast(getter));
1468  }
1469  // Getter is not a function.
1470  return isolate->factory()->undefined_value();
1471}
1472
1473// static
1474Address AccessorInfo::redirect(Address address, AccessorComponent component) {
1475  ApiFunction fun(address);
1476  DCHECK_EQ(ACCESSOR_GETTER, component);
1477  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1478  return ExternalReference::Create(&fun, type).address();
1479}
1480
1481Address AccessorInfo::redirected_getter() const {
1482  Address accessor = v8::ToCData<Address>(getter());
1483  if (accessor == kNullAddress) return kNullAddress;
1484  return redirect(accessor, ACCESSOR_GETTER);
1485}
1486
1487Address CallHandlerInfo::redirected_callback() const {
1488  Address address = v8::ToCData<Address>(callback());
1489  ApiFunction fun(address);
1490  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
1491  return ExternalReference::Create(&fun, type).address();
1492}
1493
1494bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
1495                                           Handle<Map> map) {
1496  if (!info->HasExpectedReceiverType()) return true;
1497  if (!map->IsJSObjectMap()) return false;
1498  return FunctionTemplateInfo::cast(info->expected_receiver_type())
1499      .IsTemplateFor(*map);
1500}
1501
1502Maybe<bool> Object::SetPropertyWithAccessor(
1503    LookupIterator* it, Handle<Object> value,
1504    Maybe<ShouldThrow> maybe_should_throw) {
1505  Isolate* isolate = it->isolate();
1506  Handle<Object> structure = it->GetAccessors();
1507  Handle<Object> receiver = it->GetReceiver();
1508  // In case of global IC, the receiver is the global object. Replace by the
1509  // global proxy.
1510  if (receiver->IsJSGlobalObject()) {
1511    receiver = handle(JSGlobalObject::cast(*receiver).global_proxy(), isolate);
1512  }
1513
1514  // We should never get here to initialize a const with the hole value since a
1515  // const declaration would conflict with the setter.
1516  DCHECK(!structure->IsForeign());
1517
1518  // API style callbacks.
1519  Handle<JSObject> holder = it->GetHolder<JSObject>();
1520  if (structure->IsAccessorInfo()) {
1521    Handle<Name> name = it->GetName();
1522    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1523    if (!info->IsCompatibleReceiver(*receiver)) {
1524      isolate->Throw(*isolate->factory()->NewTypeError(
1525          MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1526      return Nothing<bool>();
1527    }
1528
1529    if (!info->has_setter()) {
1530      // TODO(verwaest): We should not get here anymore once all AccessorInfos
1531      // are marked as special_data_property. They cannot both be writable and
1532      // not have a setter.
1533      return Just(true);
1534    }
1535
1536    if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1537      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1538          isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1539          Nothing<bool>());
1540    }
1541
1542    // The actual type of setter callback is either
1543    // v8::AccessorNameSetterCallback or
1544    // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
1545    // AccessorInfo was created by the API or internally (see accessors.cc).
1546    // Here we handle both cases using GenericNamedPropertySetterCallback and
1547    // its Call method.
1548    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1549                                   maybe_should_throw);
1550    Handle<Object> result = args.CallAccessorSetter(info, name, value);
1551    // In the case of AccessorNameSetterCallback, we know that the result value
1552    // cannot have been set, so the result of Call will be null.  In the case of
1553    // AccessorNameBooleanSetterCallback, the result will either be null
1554    // (signalling an exception) or a boolean Oddball.
1555    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1556    if (result.is_null()) return Just(true);
1557    DCHECK(result->BooleanValue(isolate) ||
1558           GetShouldThrow(isolate, maybe_should_throw) == kDontThrow);
1559    return Just(result->BooleanValue(isolate));
1560  }
1561
1562  // Regular accessor.
1563  Handle<Object> setter(AccessorPair::cast(*structure).setter(), isolate);
1564  if (setter->IsFunctionTemplateInfo()) {
1565    SaveAndSwitchContext save(isolate,
1566                              *holder->GetCreationContext().ToHandleChecked());
1567    Handle<Object> argv[] = {value};
1568    RETURN_ON_EXCEPTION_VALUE(
1569        isolate,
1570        Builtins::InvokeApiFunction(isolate, false,
1571                                    Handle<FunctionTemplateInfo>::cast(setter),
1572                                    receiver, arraysize(argv), argv,
1573                                    isolate->factory()->undefined_value()),
1574        Nothing<bool>());
1575    return Just(true);
1576  } else if (setter->IsCallable()) {
1577    // TODO(rossberg): nicer would be to cast to some JSCallable here...
1578    return SetPropertyWithDefinedSetter(
1579        receiver, Handle<JSReceiver>::cast(setter), value, maybe_should_throw);
1580  }
1581
1582  RETURN_FAILURE(isolate, GetShouldThrow(isolate, maybe_should_throw),
1583                 NewTypeError(MessageTemplate::kNoSetterInCallback,
1584                              it->GetName(), it->GetHolder<JSObject>()));
1585}
1586
1587MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1588    Handle<Object> receiver, Handle<JSReceiver> getter) {
1589  Isolate* isolate = getter->GetIsolate();
1590
1591  // Platforms with simulators like arm/arm64 expose a funny issue. If the
1592  // simulator has a separate JS stack pointer from the C++ stack pointer, it
1593  // can miss C++ stack overflows in the stack guard at the start of JavaScript
1594  // functions. It would be very expensive to check the C++ stack pointer at
1595  // that location. The best solution seems to be to break the impasse by
1596  // adding checks at possible recursion points. What's more, we don't put
1597  // this stack check behind the USE_SIMULATOR define in order to keep
1598  // behavior the same between hardware and simulators.
1599  StackLimitCheck check(isolate);
1600  if (check.JsHasOverflowed()) {
1601    isolate->StackOverflow();
1602    return MaybeHandle<Object>();
1603  }
1604
1605  return Execution::Call(isolate, getter, receiver, 0, nullptr);
1606}
1607
1608Maybe<bool> Object::SetPropertyWithDefinedSetter(
1609    Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value,
1610    Maybe<ShouldThrow> should_throw) {
1611  Isolate* isolate = setter->GetIsolate();
1612
1613  Handle<Object> argv[] = {value};
1614  RETURN_ON_EXCEPTION_VALUE(
1615      isolate,
1616      Execution::Call(isolate, setter, receiver, arraysize(argv), argv),
1617      Nothing<bool>());
1618  return Just(true);
1619}
1620
1621Map Object::GetPrototypeChainRootMap(Isolate* isolate) const {
1622  DisallowGarbageCollection no_alloc;
1623  if (IsSmi()) {
1624    Context native_context = isolate->context().native_context();
1625    return native_context.number_function().initial_map();
1626  }
1627
1628  const HeapObject heap_object = HeapObject::cast(*this);
1629  return heap_object.map().GetPrototypeChainRootMap(isolate);
1630}
1631
1632Smi Object::GetOrCreateHash(Isolate* isolate) {
1633  DisallowGarbageCollection no_gc;
1634  Object hash = Object::GetSimpleHash(*this);
1635  if (hash.IsSmi()) return Smi::cast(hash);
1636
1637  DCHECK(IsJSReceiver());
1638  return JSReceiver::cast(*this).GetOrCreateIdentityHash(isolate);
1639}
1640
1641bool Object::SameValue(Object other) {
1642  if (other == *this) return true;
1643
1644  if (IsNumber() && other.IsNumber()) {
1645    return SameNumberValue(Number(), other.Number());
1646  }
1647  if (IsString() && other.IsString()) {
1648    return String::cast(*this).Equals(String::cast(other));
1649  }
1650  if (IsBigInt() && other.IsBigInt()) {
1651    return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1652  }
1653  return false;
1654}
1655
1656bool Object::SameValueZero(Object other) {
1657  if (other == *this) return true;
1658
1659  if (IsNumber() && other.IsNumber()) {
1660    double this_value = Number();
1661    double other_value = other.Number();
1662    // +0 == -0 is true
1663    return this_value == other_value ||
1664           (std::isnan(this_value) && std::isnan(other_value));
1665  }
1666  if (IsString() && other.IsString()) {
1667    return String::cast(*this).Equals(String::cast(other));
1668  }
1669  if (IsBigInt() && other.IsBigInt()) {
1670    return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1671  }
1672  return false;
1673}
1674
1675MaybeHandle<Object> Object::ArraySpeciesConstructor(
1676    Isolate* isolate, Handle<Object> original_array) {
1677  Handle<Object> default_species = isolate->array_function();
1678  if (!FLAG_builtin_subclassing) return default_species;
1679  if (original_array->IsJSArray() &&
1680      Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
1681      Protectors::IsArraySpeciesLookupChainIntact(isolate)) {
1682    return default_species;
1683  }
1684  Handle<Object> constructor = isolate->factory()->undefined_value();
1685  Maybe<bool> is_array = Object::IsArray(original_array);
1686  MAYBE_RETURN_NULL(is_array);
1687  if (is_array.FromJust()) {
1688    ASSIGN_RETURN_ON_EXCEPTION(
1689        isolate, constructor,
1690        Object::GetProperty(isolate, original_array,
1691                            isolate->factory()->constructor_string()),
1692        Object);
1693    if (constructor->IsConstructor()) {
1694      Handle<Context> constructor_context;
1695      ASSIGN_RETURN_ON_EXCEPTION(
1696          isolate, constructor_context,
1697          JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
1698          Object);
1699      if (*constructor_context != *isolate->native_context() &&
1700          *constructor == constructor_context->array_function()) {
1701        constructor = isolate->factory()->undefined_value();
1702      }
1703    }
1704    if (constructor->IsJSReceiver()) {
1705      ASSIGN_RETURN_ON_EXCEPTION(
1706          isolate, constructor,
1707          JSReceiver::GetProperty(isolate,
1708                                  Handle<JSReceiver>::cast(constructor),
1709                                  isolate->factory()->species_symbol()),
1710          Object);
1711      if (constructor->IsNull(isolate)) {
1712        constructor = isolate->factory()->undefined_value();
1713      }
1714    }
1715  }
1716  if (constructor->IsUndefined(isolate)) {
1717    return default_species;
1718  } else {
1719    if (!constructor->IsConstructor()) {
1720      THROW_NEW_ERROR(isolate,
1721                      NewTypeError(MessageTemplate::kSpeciesNotConstructor),
1722                      Object);
1723    }
1724    return constructor;
1725  }
1726}
1727
1728// ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
1729V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
1730    Isolate* isolate, Handle<JSReceiver> recv,
1731    Handle<JSFunction> default_ctor) {
1732  Handle<Object> ctor_obj;
1733  ASSIGN_RETURN_ON_EXCEPTION(
1734      isolate, ctor_obj,
1735      JSObject::GetProperty(isolate, recv,
1736                            isolate->factory()->constructor_string()),
1737      Object);
1738
1739  if (ctor_obj->IsUndefined(isolate)) return default_ctor;
1740
1741  if (!ctor_obj->IsJSReceiver()) {
1742    THROW_NEW_ERROR(isolate,
1743                    NewTypeError(MessageTemplate::kConstructorNotReceiver),
1744                    Object);
1745  }
1746
1747  Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
1748
1749  Handle<Object> species;
1750  ASSIGN_RETURN_ON_EXCEPTION(
1751      isolate, species,
1752      JSObject::GetProperty(isolate, ctor,
1753                            isolate->factory()->species_symbol()),
1754      Object);
1755
1756  if (species->IsNullOrUndefined(isolate)) {
1757    return default_ctor;
1758  }
1759
1760  if (species->IsConstructor()) return species;
1761
1762  THROW_NEW_ERROR(
1763      isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
1764}
1765
1766bool Object::IterationHasObservableEffects() {
1767  // Check that this object is an array.
1768  if (!IsJSArray()) return true;
1769  JSArray array = JSArray::cast(*this);
1770  Isolate* isolate = array.GetIsolate();
1771
1772  // Check that we have the original ArrayPrototype.
1773  i::HandleScope handle_scope(isolate);
1774  i::Handle<i::Context> context;
1775  if (!array.GetCreationContext().ToHandle(&context)) return false;
1776  if (!array.map().prototype().IsJSObject()) return true;
1777  JSObject array_proto = JSObject::cast(array.map().prototype());
1778  auto initial_array_prototype =
1779      context->native_context().initial_array_prototype();
1780  if (initial_array_prototype != array_proto) return true;
1781
1782  // Check that the ArrayPrototype hasn't been modified in a way that would
1783  // affect iteration.
1784  if (!Protectors::IsArrayIteratorLookupChainIntact(isolate)) return true;
1785
1786  // For FastPacked kinds, iteration will have the same effect as simply
1787  // accessing each property in order.
1788  ElementsKind array_kind = array.GetElementsKind();
1789  if (IsFastPackedElementsKind(array_kind)) return false;
1790
1791  // For FastHoley kinds, an element access on a hole would cause a lookup on
1792  // the prototype. This could have different results if the prototype has been
1793  // changed.
1794  if (IsHoleyElementsKind(array_kind) &&
1795      Protectors::IsNoElementsIntact(isolate)) {
1796    return false;
1797  }
1798  return true;
1799}
1800
1801bool Object::IsCodeLike(Isolate* isolate) const {
1802  DisallowGarbageCollection no_gc;
1803  return IsJSReceiver() && JSReceiver::cast(*this).IsCodeLike(isolate);
1804}
1805
1806void Object::ShortPrint(FILE* out) const {
1807  OFStream os(out);
1808  os << Brief(*this);
1809}
1810
1811void Object::ShortPrint(StringStream* accumulator) const {
1812  std::ostringstream os;
1813  os << Brief(*this);
1814  accumulator->Add(os.str().c_str());
1815}
1816
1817void Object::ShortPrint(std::ostream& os) const { os << Brief(*this); }
1818
1819std::ostream& operator<<(std::ostream& os, const Object& obj) {
1820  obj.ShortPrint(os);
1821  return os;
1822}
1823
1824std::ostream& operator<<(std::ostream& os, const Brief& v) {
1825  MaybeObject maybe_object(v.value);
1826  Smi smi;
1827  HeapObject heap_object;
1828  if (maybe_object->ToSmi(&smi)) {
1829    smi.SmiPrint(os);
1830  } else if (maybe_object->IsCleared()) {
1831    os << "[cleared]";
1832  } else if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
1833    os << "[weak] ";
1834    heap_object.HeapObjectShortPrint(os);
1835  } else if (maybe_object->GetHeapObjectIfStrong(&heap_object)) {
1836    heap_object.HeapObjectShortPrint(os);
1837  } else {
1838    UNREACHABLE();
1839  }
1840  return os;
1841}
1842
1843void Smi::SmiPrint(std::ostream& os) const { os << value(); }
1844
1845void HeapObject::HeapObjectShortPrint(std::ostream& os) {
1846  PtrComprCageBase cage_base = GetPtrComprCageBaseSlow(*this);
1847  os << AsHex::Address(this->ptr()) << " ";
1848
1849  if (IsString(cage_base)) {
1850    HeapStringAllocator allocator;
1851    StringStream accumulator(&allocator);
1852    String::cast(*this).StringShortPrint(&accumulator);
1853    os << accumulator.ToCString().get();
1854    return;
1855  }
1856  if (IsJSObject(cage_base)) {
1857    HeapStringAllocator allocator;
1858    StringStream accumulator(&allocator);
1859    JSObject::cast(*this).JSObjectShortPrint(&accumulator);
1860    os << accumulator.ToCString().get();
1861    return;
1862  }
1863  switch (map(cage_base).instance_type()) {
1864    case MAP_TYPE: {
1865      os << "<Map";
1866      Map mapInstance = Map::cast(*this);
1867      if (mapInstance.IsJSObjectMap()) {
1868        os << "(" << ElementsKindToString(mapInstance.elements_kind()) << ")";
1869      } else if (mapInstance.instance_size() != kVariableSizeSentinel) {
1870        os << "[" << mapInstance.instance_size() << "]";
1871      }
1872      os << ">";
1873    } break;
1874    case AWAIT_CONTEXT_TYPE: {
1875      os << "<AwaitContext generator= ";
1876      HeapStringAllocator allocator;
1877      StringStream accumulator(&allocator);
1878      Context::cast(*this).extension().ShortPrint(&accumulator);
1879      os << accumulator.ToCString().get();
1880      os << '>';
1881      break;
1882    }
1883    case BLOCK_CONTEXT_TYPE:
1884      os << "<BlockContext[" << Context::cast(*this).length() << "]>";
1885      break;
1886    case CATCH_CONTEXT_TYPE:
1887      os << "<CatchContext[" << Context::cast(*this).length() << "]>";
1888      break;
1889    case DEBUG_EVALUATE_CONTEXT_TYPE:
1890      os << "<DebugEvaluateContext[" << Context::cast(*this).length() << "]>";
1891      break;
1892    case EVAL_CONTEXT_TYPE:
1893      os << "<EvalContext[" << Context::cast(*this).length() << "]>";
1894      break;
1895    case FUNCTION_CONTEXT_TYPE:
1896      os << "<FunctionContext[" << Context::cast(*this).length() << "]>";
1897      break;
1898    case MODULE_CONTEXT_TYPE:
1899      os << "<ModuleContext[" << Context::cast(*this).length() << "]>";
1900      break;
1901    case NATIVE_CONTEXT_TYPE:
1902      os << "<NativeContext[" << Context::cast(*this).length() << "]>";
1903      break;
1904    case SCRIPT_CONTEXT_TYPE:
1905      os << "<ScriptContext[" << Context::cast(*this).length() << "]>";
1906      break;
1907    case WITH_CONTEXT_TYPE:
1908      os << "<WithContext[" << Context::cast(*this).length() << "]>";
1909      break;
1910    case SCRIPT_CONTEXT_TABLE_TYPE:
1911      os << "<ScriptContextTable[" << FixedArray::cast(*this).length() << "]>";
1912      break;
1913    case HASH_TABLE_TYPE:
1914      os << "<HashTable[" << FixedArray::cast(*this).length() << "]>";
1915      break;
1916    case ORDERED_HASH_MAP_TYPE:
1917      os << "<OrderedHashMap[" << FixedArray::cast(*this).length() << "]>";
1918      break;
1919    case ORDERED_HASH_SET_TYPE:
1920      os << "<OrderedHashSet[" << FixedArray::cast(*this).length() << "]>";
1921      break;
1922    case ORDERED_NAME_DICTIONARY_TYPE:
1923      os << "<OrderedNameDictionary[" << FixedArray::cast(*this).length()
1924         << "]>";
1925      break;
1926    case NAME_DICTIONARY_TYPE:
1927      os << "<NameDictionary[" << FixedArray::cast(*this).length() << "]>";
1928      break;
1929    case SWISS_NAME_DICTIONARY_TYPE:
1930      os << "<SwissNameDictionary["
1931         << SwissNameDictionary::cast(*this).Capacity() << "]>";
1932      break;
1933    case GLOBAL_DICTIONARY_TYPE:
1934      os << "<GlobalDictionary[" << FixedArray::cast(*this).length() << "]>";
1935      break;
1936    case NUMBER_DICTIONARY_TYPE:
1937      os << "<NumberDictionary[" << FixedArray::cast(*this).length() << "]>";
1938      break;
1939    case SIMPLE_NUMBER_DICTIONARY_TYPE:
1940      os << "<SimpleNumberDictionary[" << FixedArray::cast(*this).length()
1941         << "]>";
1942      break;
1943    case FIXED_ARRAY_TYPE:
1944      os << "<FixedArray[" << FixedArray::cast(*this).length() << "]>";
1945      break;
1946    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
1947      os << "<ObjectBoilerplateDescription[" << FixedArray::cast(*this).length()
1948         << "]>";
1949      break;
1950    case FIXED_DOUBLE_ARRAY_TYPE:
1951      os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this).length()
1952         << "]>";
1953      break;
1954    case BYTE_ARRAY_TYPE:
1955      os << "<ByteArray[" << ByteArray::cast(*this).length() << "]>";
1956      break;
1957    case BYTECODE_ARRAY_TYPE:
1958      os << "<BytecodeArray[" << BytecodeArray::cast(*this).length() << "]>";
1959      break;
1960    case DESCRIPTOR_ARRAY_TYPE:
1961      os << "<DescriptorArray["
1962         << DescriptorArray::cast(*this).number_of_descriptors() << "]>";
1963      break;
1964    case TRANSITION_ARRAY_TYPE:
1965      os << "<TransitionArray[" << TransitionArray::cast(*this).length()
1966         << "]>";
1967      break;
1968    case PROPERTY_ARRAY_TYPE:
1969      os << "<PropertyArray[" << PropertyArray::cast(*this).length() << "]>";
1970      break;
1971    case FEEDBACK_CELL_TYPE: {
1972      {
1973        ReadOnlyRoots roots = GetReadOnlyRoots();
1974        os << "<FeedbackCell[";
1975        if (map() == roots.no_closures_cell_map()) {
1976          os << "no feedback";
1977        } else if (map() == roots.one_closure_cell_map()) {
1978          os << "one closure";
1979        } else if (map() == roots.many_closures_cell_map()) {
1980          os << "many closures";
1981        } else {
1982          os << "!!!INVALID MAP!!!";
1983        }
1984        os << "]>";
1985      }
1986      break;
1987    }
1988    case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
1989      os << "<ClosureFeedbackCellArray["
1990         << ClosureFeedbackCellArray::cast(*this).length() << "]>";
1991      break;
1992    case FEEDBACK_VECTOR_TYPE:
1993      os << "<FeedbackVector[" << FeedbackVector::cast(*this).length() << "]>";
1994      break;
1995    case FREE_SPACE_TYPE:
1996      os << "<FreeSpace[" << FreeSpace::cast(*this).size(kRelaxedLoad) << "]>";
1997      break;
1998
1999    case PREPARSE_DATA_TYPE: {
2000      PreparseData data = PreparseData::cast(*this);
2001      os << "<PreparseData[data=" << data.data_length()
2002         << " children=" << data.children_length() << "]>";
2003      break;
2004    }
2005
2006    case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE: {
2007      UncompiledDataWithoutPreparseData data =
2008          UncompiledDataWithoutPreparseData::cast(*this);
2009      os << "<UncompiledDataWithoutPreparseData (" << data.start_position()
2010         << ", " << data.end_position() << ")]>";
2011      break;
2012    }
2013
2014    case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE: {
2015      UncompiledDataWithPreparseData data =
2016          UncompiledDataWithPreparseData::cast(*this);
2017      os << "<UncompiledDataWithPreparseData (" << data.start_position() << ", "
2018         << data.end_position() << ") preparsed=" << Brief(data.preparse_data())
2019         << ">";
2020      break;
2021    }
2022
2023    case SHARED_FUNCTION_INFO_TYPE: {
2024      SharedFunctionInfo shared = SharedFunctionInfo::cast(*this);
2025      std::unique_ptr<char[]> debug_name = shared.DebugNameCStr();
2026      if (debug_name[0] != '\0') {
2027        os << "<SharedFunctionInfo " << debug_name.get() << ">";
2028      } else {
2029        os << "<SharedFunctionInfo>";
2030      }
2031      break;
2032    }
2033    case JS_MESSAGE_OBJECT_TYPE:
2034      os << "<JSMessageObject>";
2035      break;
2036#define MAKE_STRUCT_CASE(TYPE, Name, name)   \
2037  case TYPE:                                 \
2038    os << "<" #Name;                         \
2039    Name::cast(*this).BriefPrintDetails(os); \
2040    os << ">";                               \
2041    break;
2042      STRUCT_LIST(MAKE_STRUCT_CASE)
2043#undef MAKE_STRUCT_CASE
2044    case ALLOCATION_SITE_TYPE: {
2045      os << "<AllocationSite";
2046      AllocationSite::cast(*this).BriefPrintDetails(os);
2047      os << ">";
2048      break;
2049    }
2050    case SCOPE_INFO_TYPE: {
2051      ScopeInfo scope = ScopeInfo::cast(*this);
2052      os << "<ScopeInfo";
2053      if (!scope.IsEmpty()) os << " " << scope.scope_type();
2054      os << ">";
2055      break;
2056    }
2057    case CODE_TYPE: {
2058      Code code = Code::cast(*this);
2059      os << "<Code " << CodeKindToString(code.kind());
2060      if (code.is_builtin()) {
2061        os << " " << Builtins::name(code.builtin_id());
2062      }
2063      os << ">";
2064      break;
2065    }
2066    case ODDBALL_TYPE: {
2067      if (IsUndefined()) {
2068        os << "<undefined>";
2069      } else if (IsTheHole()) {
2070        os << "<the_hole>";
2071      } else if (IsNull()) {
2072        os << "<null>";
2073      } else if (IsTrue()) {
2074        os << "<true>";
2075      } else if (IsFalse()) {
2076        os << "<false>";
2077      } else {
2078        os << "<Odd Oddball: ";
2079        os << Oddball::cast(*this).to_string().ToCString().get();
2080        os << ">";
2081      }
2082      break;
2083    }
2084    case SYMBOL_TYPE: {
2085      Symbol symbol = Symbol::cast(*this);
2086      symbol.SymbolShortPrint(os);
2087      break;
2088    }
2089    case HEAP_NUMBER_TYPE: {
2090      os << "<HeapNumber ";
2091      HeapNumber::cast(*this).HeapNumberShortPrint(os);
2092      os << ">";
2093      break;
2094    }
2095    case BIGINT_TYPE: {
2096      os << "<BigInt ";
2097      BigInt::cast(*this).BigIntShortPrint(os);
2098      os << ">";
2099      break;
2100    }
2101    case JS_PROXY_TYPE:
2102      os << "<JSProxy>";
2103      break;
2104    case FOREIGN_TYPE:
2105      os << "<Foreign>";
2106      break;
2107    case CELL_TYPE: {
2108      os << "<Cell value= ";
2109      HeapStringAllocator allocator;
2110      StringStream accumulator(&allocator);
2111      Cell::cast(*this).value().ShortPrint(&accumulator);
2112      os << accumulator.ToCString().get();
2113      os << '>';
2114      break;
2115    }
2116    case PROPERTY_CELL_TYPE: {
2117      PropertyCell cell = PropertyCell::cast(*this);
2118      os << "<PropertyCell name=";
2119      cell.name().ShortPrint(os);
2120      os << " value=";
2121      HeapStringAllocator allocator;
2122      StringStream accumulator(&allocator);
2123      cell.value(kAcquireLoad).ShortPrint(&accumulator);
2124      os << accumulator.ToCString().get();
2125      os << '>';
2126      break;
2127    }
2128    case CALL_HANDLER_INFO_TYPE: {
2129      CallHandlerInfo info = CallHandlerInfo::cast(*this);
2130      os << "<CallHandlerInfo ";
2131      os << "callback= " << Brief(info.callback());
2132      os << ", js_callback= " << Brief(info.js_callback());
2133      os << ", data= " << Brief(info.data());
2134      if (info.IsSideEffectFreeCallHandlerInfo()) {
2135        os << ", side_effect_free= true>";
2136      } else {
2137        os << ", side_effect_free= false>";
2138      }
2139      break;
2140    }
2141    default:
2142      os << "<Other heap object (" << map().instance_type() << ")>";
2143      break;
2144  }
2145}
2146
2147void Struct::BriefPrintDetails(std::ostream& os) {}
2148
2149void Tuple2::BriefPrintDetails(std::ostream& os) {
2150  os << " " << Brief(value1()) << ", " << Brief(value2());
2151}
2152
2153void MegaDomHandler::BriefPrintDetails(std::ostream& os) {
2154  os << " " << Brief(accessor()) << ", " << Brief(context());
2155}
2156
2157void ClassPositions::BriefPrintDetails(std::ostream& os) {
2158  os << " " << start() << ", " << end();
2159}
2160
2161void CallableTask::BriefPrintDetails(std::ostream& os) {
2162  os << " callable=" << Brief(callable());
2163}
2164
2165void HeapObject::Iterate(PtrComprCageBase cage_base, ObjectVisitor* v) {
2166  IterateFast<ObjectVisitor>(cage_base, v);
2167}
2168
2169void HeapObject::IterateBody(PtrComprCageBase cage_base, ObjectVisitor* v) {
2170  Map m = map(cage_base);
2171  IterateBodyFast<ObjectVisitor>(m, SizeFromMap(m), v);
2172}
2173
2174void HeapObject::IterateBody(Map map, int object_size, ObjectVisitor* v) {
2175  IterateBodyFast<ObjectVisitor>(map, object_size, v);
2176}
2177
2178struct CallIsValidSlot {
2179  template <typename BodyDescriptor>
2180  static bool apply(Map map, HeapObject obj, int offset) {
2181    return BodyDescriptor::IsValidSlot(map, obj, offset);
2182  }
2183};
2184
2185bool HeapObject::IsValidSlot(Map map, int offset) {
2186  DCHECK_NE(0, offset);
2187  return BodyDescriptorApply<CallIsValidSlot>(map.instance_type(), map, *this,
2188                                              offset);
2189}
2190
2191int HeapObject::SizeFromMap(Map map) const {
2192  int instance_size = map.instance_size();
2193  if (instance_size != kVariableSizeSentinel) return instance_size;
2194  // Only inline the most frequent cases.
2195  InstanceType instance_type = map.instance_type();
2196  if (base::IsInRange(instance_type, FIRST_FIXED_ARRAY_TYPE,
2197                      LAST_FIXED_ARRAY_TYPE)) {
2198    return FixedArray::SizeFor(
2199        FixedArray::unchecked_cast(*this).length(kAcquireLoad));
2200  }
2201  if (base::IsInRange(instance_type, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE)) {
2202    if (instance_type == NATIVE_CONTEXT_TYPE) return NativeContext::kSize;
2203    return Context::SizeFor(Context::unchecked_cast(*this).length());
2204  }
2205  if (instance_type == ONE_BYTE_STRING_TYPE ||
2206      instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE ||
2207      instance_type == SHARED_ONE_BYTE_STRING_TYPE) {
2208    // Strings may get concurrently truncated, hence we have to access its
2209    // length synchronized.
2210    return SeqOneByteString::SizeFor(
2211        SeqOneByteString::unchecked_cast(*this).length(kAcquireLoad));
2212  }
2213  if (instance_type == BYTE_ARRAY_TYPE) {
2214    return ByteArray::SizeFor(
2215        ByteArray::unchecked_cast(*this).length(kAcquireLoad));
2216  }
2217  if (instance_type == BYTECODE_ARRAY_TYPE) {
2218    return BytecodeArray::SizeFor(
2219        BytecodeArray::unchecked_cast(*this).length(kAcquireLoad));
2220  }
2221  if (instance_type == FREE_SPACE_TYPE) {
2222    return FreeSpace::unchecked_cast(*this).size(kRelaxedLoad);
2223  }
2224  if (instance_type == STRING_TYPE ||
2225      instance_type == INTERNALIZED_STRING_TYPE ||
2226      instance_type == SHARED_STRING_TYPE) {
2227    // Strings may get concurrently truncated, hence we have to access its
2228    // length synchronized.
2229    return SeqTwoByteString::SizeFor(
2230        SeqTwoByteString::unchecked_cast(*this).length(kAcquireLoad));
2231  }
2232  if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2233    return FixedDoubleArray::SizeFor(
2234        FixedDoubleArray::unchecked_cast(*this).length(kAcquireLoad));
2235  }
2236  if (instance_type == FEEDBACK_METADATA_TYPE) {
2237    return FeedbackMetadata::SizeFor(
2238        FeedbackMetadata::unchecked_cast(*this).slot_count(kAcquireLoad));
2239  }
2240  if (base::IsInRange(instance_type, FIRST_DESCRIPTOR_ARRAY_TYPE,
2241                      LAST_DESCRIPTOR_ARRAY_TYPE)) {
2242    return DescriptorArray::SizeFor(
2243        DescriptorArray::unchecked_cast(*this).number_of_all_descriptors());
2244  }
2245  if (base::IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
2246                      LAST_WEAK_FIXED_ARRAY_TYPE)) {
2247    return WeakFixedArray::SizeFor(
2248        WeakFixedArray::unchecked_cast(*this).length(kAcquireLoad));
2249  }
2250  if (instance_type == WEAK_ARRAY_LIST_TYPE) {
2251    return WeakArrayList::SizeForCapacity(
2252        WeakArrayList::unchecked_cast(*this).capacity());
2253  }
2254  if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
2255    return SmallOrderedHashSet::SizeFor(
2256        SmallOrderedHashSet::unchecked_cast(*this).Capacity());
2257  }
2258  if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) {
2259    return SmallOrderedHashMap::SizeFor(
2260        SmallOrderedHashMap::unchecked_cast(*this).Capacity());
2261  }
2262  if (instance_type == SMALL_ORDERED_NAME_DICTIONARY_TYPE) {
2263    return SmallOrderedNameDictionary::SizeFor(
2264        SmallOrderedNameDictionary::unchecked_cast(*this).Capacity());
2265  }
2266  if (instance_type == SWISS_NAME_DICTIONARY_TYPE) {
2267    return SwissNameDictionary::SizeFor(
2268        SwissNameDictionary::unchecked_cast(*this).Capacity());
2269  }
2270  if (instance_type == PROPERTY_ARRAY_TYPE) {
2271    return PropertyArray::SizeFor(
2272        PropertyArray::cast(*this).length(kAcquireLoad));
2273  }
2274  if (instance_type == FEEDBACK_VECTOR_TYPE) {
2275    return FeedbackVector::SizeFor(
2276        FeedbackVector::unchecked_cast(*this).length());
2277  }
2278  if (instance_type == BIGINT_TYPE) {
2279    return BigInt::SizeFor(BigInt::unchecked_cast(*this).length());
2280  }
2281  if (instance_type == PREPARSE_DATA_TYPE) {
2282    PreparseData data = PreparseData::unchecked_cast(*this);
2283    return PreparseData::SizeFor(data.data_length(), data.children_length());
2284  }
2285#define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName)                \
2286  if (instance_type == TYPE) {                              \
2287    return TypeName::unchecked_cast(*this).AllocatedSize(); \
2288  }
2289  TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR)
2290#undef MAKE_TORQUE_SIZE_FOR
2291
2292  if (instance_type == CODE_TYPE) {
2293    return Code::unchecked_cast(*this).CodeSize();
2294  }
2295  if (instance_type == COVERAGE_INFO_TYPE) {
2296    return CoverageInfo::SizeFor(
2297        CoverageInfo::unchecked_cast(*this).slot_count());
2298  }
2299#if V8_ENABLE_WEBASSEMBLY
2300  if (instance_type == WASM_STRUCT_TYPE) {
2301    return WasmStruct::GcSafeSize(map);
2302  }
2303  if (instance_type == WASM_ARRAY_TYPE) {
2304    return WasmArray::SizeFor(map, WasmArray::cast(*this).length());
2305  }
2306#endif  // V8_ENABLE_WEBASSEMBLY
2307  DCHECK_EQ(instance_type, EMBEDDER_DATA_ARRAY_TYPE);
2308  return EmbedderDataArray::SizeFor(
2309      EmbedderDataArray::unchecked_cast(*this).length());
2310}
2311
2312bool HeapObject::NeedsRehashing(PtrComprCageBase cage_base) const {
2313  return NeedsRehashing(map(cage_base).instance_type());
2314}
2315
2316bool HeapObject::NeedsRehashing(InstanceType instance_type) const {
2317  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
2318    // Use map() only when it's guaranteed that it's not a Code object.
2319    DCHECK_IMPLIES(instance_type != CODE_TYPE,
2320                   instance_type == map().instance_type());
2321  } else {
2322    DCHECK_EQ(instance_type, map().instance_type());
2323  }
2324  switch (instance_type) {
2325    case DESCRIPTOR_ARRAY_TYPE:
2326    case STRONG_DESCRIPTOR_ARRAY_TYPE:
2327      return DescriptorArray::cast(*this).number_of_descriptors() > 1;
2328    case TRANSITION_ARRAY_TYPE:
2329      return TransitionArray::cast(*this).number_of_entries() > 1;
2330    case ORDERED_HASH_MAP_TYPE:
2331    case ORDERED_HASH_SET_TYPE:
2332      return false;  // We'll rehash from the JSMap or JSSet referencing them.
2333    case NAME_DICTIONARY_TYPE:
2334    case NAME_TO_INDEX_HASH_TABLE_TYPE:
2335    case REGISTERED_SYMBOL_TABLE_TYPE:
2336    case GLOBAL_DICTIONARY_TYPE:
2337    case NUMBER_DICTIONARY_TYPE:
2338    case SIMPLE_NUMBER_DICTIONARY_TYPE:
2339    case HASH_TABLE_TYPE:
2340    case SMALL_ORDERED_HASH_MAP_TYPE:
2341    case SMALL_ORDERED_HASH_SET_TYPE:
2342    case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2343    case SWISS_NAME_DICTIONARY_TYPE:
2344    case JS_MAP_TYPE:
2345    case JS_SET_TYPE:
2346      return true;
2347    default:
2348      return false;
2349  }
2350}
2351
2352bool HeapObject::CanBeRehashed(PtrComprCageBase cage_base) const {
2353  DCHECK(NeedsRehashing(cage_base));
2354  switch (map(cage_base).instance_type()) {
2355    case JS_MAP_TYPE:
2356    case JS_SET_TYPE:
2357      return true;
2358    case ORDERED_HASH_MAP_TYPE:
2359    case ORDERED_HASH_SET_TYPE:
2360      UNREACHABLE();  // We'll rehash from the JSMap or JSSet referencing them.
2361    case ORDERED_NAME_DICTIONARY_TYPE:
2362      return false;
2363    case NAME_DICTIONARY_TYPE:
2364    case NAME_TO_INDEX_HASH_TABLE_TYPE:
2365    case REGISTERED_SYMBOL_TABLE_TYPE:
2366    case GLOBAL_DICTIONARY_TYPE:
2367    case NUMBER_DICTIONARY_TYPE:
2368    case SIMPLE_NUMBER_DICTIONARY_TYPE:
2369    case SWISS_NAME_DICTIONARY_TYPE:
2370      return true;
2371    case DESCRIPTOR_ARRAY_TYPE:
2372    case STRONG_DESCRIPTOR_ARRAY_TYPE:
2373      return true;
2374    case TRANSITION_ARRAY_TYPE:
2375      return true;
2376    case SMALL_ORDERED_HASH_MAP_TYPE:
2377      return SmallOrderedHashMap::cast(*this).NumberOfElements() == 0;
2378    case SMALL_ORDERED_HASH_SET_TYPE:
2379      return SmallOrderedHashMap::cast(*this).NumberOfElements() == 0;
2380    case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2381      return SmallOrderedNameDictionary::cast(*this).NumberOfElements() == 0;
2382    default:
2383      return false;
2384  }
2385}
2386
2387template <typename IsolateT>
2388void HeapObject::RehashBasedOnMap(IsolateT* isolate) {
2389  switch (map(isolate).instance_type()) {
2390    case HASH_TABLE_TYPE:
2391      UNREACHABLE();
2392    case NAME_DICTIONARY_TYPE:
2393      NameDictionary::cast(*this).Rehash(isolate);
2394      break;
2395    case NAME_TO_INDEX_HASH_TABLE_TYPE:
2396      NameToIndexHashTable::cast(*this).Rehash(isolate);
2397      break;
2398    case REGISTERED_SYMBOL_TABLE_TYPE:
2399      RegisteredSymbolTable::cast(*this).Rehash(isolate);
2400      break;
2401    case SWISS_NAME_DICTIONARY_TYPE:
2402      SwissNameDictionary::cast(*this).Rehash(isolate);
2403      break;
2404    case GLOBAL_DICTIONARY_TYPE:
2405      GlobalDictionary::cast(*this).Rehash(isolate);
2406      break;
2407    case NUMBER_DICTIONARY_TYPE:
2408      NumberDictionary::cast(*this).Rehash(isolate);
2409      break;
2410    case SIMPLE_NUMBER_DICTIONARY_TYPE:
2411      SimpleNumberDictionary::cast(*this).Rehash(isolate);
2412      break;
2413    case DESCRIPTOR_ARRAY_TYPE:
2414      DCHECK_LE(1, DescriptorArray::cast(*this).number_of_descriptors());
2415      DescriptorArray::cast(*this).Sort();
2416      break;
2417    case TRANSITION_ARRAY_TYPE:
2418      TransitionArray::cast(*this).Sort();
2419      break;
2420    case SMALL_ORDERED_HASH_MAP_TYPE:
2421      DCHECK_EQ(0, SmallOrderedHashMap::cast(*this).NumberOfElements());
2422      break;
2423    case SMALL_ORDERED_HASH_SET_TYPE:
2424      DCHECK_EQ(0, SmallOrderedHashSet::cast(*this).NumberOfElements());
2425      break;
2426    case ORDERED_HASH_MAP_TYPE:
2427    case ORDERED_HASH_SET_TYPE:
2428      UNREACHABLE();  // We'll rehash from the JSMap or JSSet referencing them.
2429    case JS_MAP_TYPE: {
2430      JSMap::cast(*this).Rehash(isolate->AsIsolate());
2431      break;
2432    }
2433    case JS_SET_TYPE: {
2434      JSSet::cast(*this).Rehash(isolate->AsIsolate());
2435      break;
2436    }
2437    case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2438      DCHECK_EQ(0, SmallOrderedNameDictionary::cast(*this).NumberOfElements());
2439      break;
2440    case ONE_BYTE_INTERNALIZED_STRING_TYPE:
2441    case INTERNALIZED_STRING_TYPE:
2442      // Rare case, rehash read-only space strings before they are sealed.
2443      DCHECK(ReadOnlyHeap::Contains(*this));
2444      String::cast(*this).EnsureHash();
2445      break;
2446    default:
2447      UNREACHABLE();
2448  }
2449}
2450template void HeapObject::RehashBasedOnMap(Isolate* isolate);
2451template void HeapObject::RehashBasedOnMap(LocalIsolate* isolate);
2452
2453void DescriptorArray::GeneralizeAllFields() {
2454  int length = number_of_descriptors();
2455  for (InternalIndex i : InternalIndex::Range(length)) {
2456    PropertyDetails details = GetDetails(i);
2457    details = details.CopyWithRepresentation(Representation::Tagged());
2458    if (details.location() == PropertyLocation::kField) {
2459      DCHECK_EQ(PropertyKind::kData, details.kind());
2460      details = details.CopyWithConstness(PropertyConstness::kMutable);
2461      SetValue(i, MaybeObject::FromObject(FieldType::Any()));
2462    }
2463    SetDetails(i, details);
2464  }
2465}
2466
2467MaybeHandle<Object> Object::SetProperty(Isolate* isolate, Handle<Object> object,
2468                                        Handle<Name> name, Handle<Object> value,
2469                                        StoreOrigin store_origin,
2470                                        Maybe<ShouldThrow> should_throw) {
2471  LookupIterator it(isolate, object, name);
2472  MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
2473  return value;
2474}
2475
2476Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
2477                                        Handle<Object> value,
2478                                        Maybe<ShouldThrow> should_throw,
2479                                        StoreOrigin store_origin, bool* found) {
2480  it->UpdateProtector();
2481  DCHECK(it->IsFound());
2482
2483  // Make sure that the top context does not change when doing callbacks or
2484  // interceptor calls.
2485  AssertNoContextChange ncc(it->isolate());
2486
2487  do {
2488    switch (it->state()) {
2489      case LookupIterator::NOT_FOUND:
2490        UNREACHABLE();
2491
2492      case LookupIterator::ACCESS_CHECK:
2493        if (it->HasAccess()) break;
2494        // Check whether it makes sense to reuse the lookup iterator. Here it
2495        // might still call into setters up the prototype chain.
2496        return JSObject::SetPropertyWithFailedAccessCheck(it, value,
2497                                                          should_throw);
2498
2499      case LookupIterator::JSPROXY: {
2500        Handle<Object> receiver = it->GetReceiver();
2501        // In case of global IC, the receiver is the global object. Replace by
2502        // the global proxy.
2503        if (receiver->IsJSGlobalObject()) {
2504          receiver = handle(JSGlobalObject::cast(*receiver).global_proxy(),
2505                            it->isolate());
2506        }
2507        return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
2508                                    value, receiver, should_throw);
2509      }
2510
2511      case LookupIterator::INTERCEPTOR: {
2512        if (it->HolderIsReceiverOrHiddenPrototype()) {
2513          Maybe<bool> result =
2514              JSObject::SetPropertyWithInterceptor(it, should_throw, value);
2515          if (result.IsNothing() || result.FromJust()) return result;
2516          // Assuming that the callback have side effects, we use
2517          // Object::SetSuperProperty() which works properly regardless on
2518          // whether the property was present on the receiver or not when
2519          // storing to the receiver.
2520          // Proceed lookup from the next state.
2521          it->Next();
2522        } else {
2523          Maybe<PropertyAttributes> maybe_attributes =
2524              JSObject::GetPropertyAttributesWithInterceptor(it);
2525          if (maybe_attributes.IsNothing()) return Nothing<bool>();
2526          if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
2527            return WriteToReadOnlyProperty(it, value, should_throw);
2528          }
2529          // At this point we might have called interceptor's query or getter
2530          // callback. Assuming that the callbacks have side effects, we use
2531          // Object::SetSuperProperty() which works properly regardless on
2532          // whether the property was present on the receiver or not when
2533          // storing to the receiver.
2534          if (maybe_attributes.FromJust() == ABSENT) {
2535            // Proceed lookup from the next state.
2536            it->Next();
2537          } else {
2538            // Finish lookup in order to make Object::SetSuperProperty() store
2539            // property to the receiver.
2540            it->NotFound();
2541          }
2542        }
2543        return Object::SetSuperProperty(it, value, store_origin, should_throw);
2544      }
2545
2546      case LookupIterator::ACCESSOR: {
2547        if (it->IsReadOnly()) {
2548          return WriteToReadOnlyProperty(it, value, should_throw);
2549        }
2550        Handle<Object> accessors = it->GetAccessors();
2551        if (accessors->IsAccessorInfo() &&
2552            !it->HolderIsReceiverOrHiddenPrototype() &&
2553            AccessorInfo::cast(*accessors).is_special_data_property()) {
2554          *found = false;
2555          return Nothing<bool>();
2556        }
2557        return SetPropertyWithAccessor(it, value, should_throw);
2558      }
2559      case LookupIterator::INTEGER_INDEXED_EXOTIC: {
2560        // IntegerIndexedElementSet converts value to a Number/BigInt prior to
2561        // the bounds check. The bounds check has already happened here, but
2562        // perform the possibly effectful ToNumber (or ToBigInt) operation
2563        // anyways.
2564        auto holder = it->GetHolder<JSTypedArray>();
2565        Handle<Object> throwaway_value;
2566        if (holder->type() == kExternalBigInt64Array ||
2567            holder->type() == kExternalBigUint64Array) {
2568          ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2569              it->isolate(), throwaway_value,
2570              BigInt::FromObject(it->isolate(), value), Nothing<bool>());
2571        } else {
2572          ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2573              it->isolate(), throwaway_value,
2574              Object::ToNumber(it->isolate(), value), Nothing<bool>());
2575        }
2576
2577        // FIXME: Throw a TypeError if the holder is detached here
2578        // (IntegerIndexedElementSpec step 5).
2579
2580        // TODO(verwaest): Per spec, we should return false here (steps 6-9
2581        // in IntegerIndexedElementSpec), resulting in an exception being thrown
2582        // on OOB accesses in strict code. Historically, v8 has not done made
2583        // this change due to uncertainty about web compat. (v8:4901)
2584        return Just(true);
2585      }
2586
2587      case LookupIterator::DATA:
2588        if (it->IsReadOnly()) {
2589          return WriteToReadOnlyProperty(it, value, should_throw);
2590        }
2591        if (it->HolderIsReceiverOrHiddenPrototype()) {
2592          return SetDataProperty(it, value);
2593        }
2594        V8_FALLTHROUGH;
2595      case LookupIterator::TRANSITION:
2596        *found = false;
2597        return Nothing<bool>();
2598    }
2599    it->Next();
2600  } while (it->IsFound());
2601
2602  *found = false;
2603  return Nothing<bool>();
2604}
2605
2606bool Object::CheckContextualStoreToJSGlobalObject(
2607    LookupIterator* it, Maybe<ShouldThrow> should_throw) {
2608  Isolate* isolate = it->isolate();
2609
2610  if (it->GetReceiver()->IsJSGlobalObject(isolate) &&
2611      (GetShouldThrow(isolate, should_throw) == ShouldThrow::kThrowOnError)) {
2612    if (it->state() == LookupIterator::TRANSITION) {
2613      // The property cell that we have created is garbage because we are going
2614      // to throw now instead of putting it into the global dictionary. However,
2615      // the cell might already have been stored into the feedback vector, so
2616      // we must invalidate it nevertheless.
2617      it->transition_cell()->ClearAndInvalidate(ReadOnlyRoots(isolate));
2618    }
2619    isolate->Throw(*isolate->factory()->NewReferenceError(
2620        MessageTemplate::kNotDefined, it->GetName()));
2621    return false;
2622  }
2623  return true;
2624}
2625
2626Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
2627                                StoreOrigin store_origin,
2628                                Maybe<ShouldThrow> should_throw) {
2629  if (it->IsFound()) {
2630    bool found = true;
2631    Maybe<bool> result =
2632        SetPropertyInternal(it, value, should_throw, store_origin, &found);
2633    if (found) return result;
2634  }
2635
2636  if (!CheckContextualStoreToJSGlobalObject(it, should_throw)) {
2637    return Nothing<bool>();
2638  }
2639  return AddDataProperty(it, value, NONE, should_throw, store_origin);
2640}
2641
2642Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
2643                                     StoreOrigin store_origin,
2644                                     Maybe<ShouldThrow> should_throw) {
2645  Isolate* isolate = it->isolate();
2646
2647  if (it->IsFound()) {
2648    bool found = true;
2649    Maybe<bool> result =
2650        SetPropertyInternal(it, value, should_throw, store_origin, &found);
2651    if (found) return result;
2652  }
2653
2654  it->UpdateProtector();
2655
2656  // The property either doesn't exist on the holder or exists there as a data
2657  // property.
2658
2659  if (!it->GetReceiver()->IsJSReceiver()) {
2660    return WriteToReadOnlyProperty(it, value, should_throw);
2661  }
2662  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
2663
2664  // Note, the callers rely on the fact that this code is redoing the full own
2665  // lookup from scratch.
2666  LookupIterator::Configuration c = LookupIterator::OWN;
2667  LookupIterator own_lookup =
2668      it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
2669                      : LookupIterator(isolate, receiver, it->name(), c);
2670
2671  for (; own_lookup.IsFound(); own_lookup.Next()) {
2672    switch (own_lookup.state()) {
2673      case LookupIterator::ACCESS_CHECK:
2674        if (!own_lookup.HasAccess()) {
2675          return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
2676                                                            should_throw);
2677        }
2678        break;
2679
2680      case LookupIterator::ACCESSOR:
2681        if (own_lookup.GetAccessors()->IsAccessorInfo()) {
2682          if (own_lookup.IsReadOnly()) {
2683            return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
2684          }
2685          return Object::SetPropertyWithAccessor(&own_lookup, value,
2686                                                 should_throw);
2687        }
2688        V8_FALLTHROUGH;
2689      case LookupIterator::INTEGER_INDEXED_EXOTIC:
2690        return RedefineIncompatibleProperty(isolate, it->GetName(), value,
2691                                            should_throw);
2692
2693      case LookupIterator::DATA: {
2694        if (own_lookup.IsReadOnly()) {
2695          return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
2696        }
2697        return SetDataProperty(&own_lookup, value);
2698      }
2699
2700      case LookupIterator::INTERCEPTOR:
2701      case LookupIterator::JSPROXY: {
2702        PropertyDescriptor desc;
2703        Maybe<bool> owned =
2704            JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
2705        MAYBE_RETURN(owned, Nothing<bool>());
2706        if (!owned.FromJust()) {
2707          if (!CheckContextualStoreToJSGlobalObject(&own_lookup,
2708                                                    should_throw)) {
2709            return Nothing<bool>();
2710          }
2711          return JSReceiver::CreateDataProperty(&own_lookup, value,
2712                                                should_throw);
2713        }
2714        if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
2715            !desc.writable()) {
2716          return RedefineIncompatibleProperty(isolate, it->GetName(), value,
2717                                              should_throw);
2718        }
2719
2720        PropertyDescriptor value_desc;
2721        value_desc.set_value(value);
2722        return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
2723                                             &value_desc, should_throw);
2724      }
2725
2726      case LookupIterator::NOT_FOUND:
2727      case LookupIterator::TRANSITION:
2728        UNREACHABLE();
2729    }
2730  }
2731
2732  if (!CheckContextualStoreToJSGlobalObject(&own_lookup, should_throw)) {
2733    return Nothing<bool>();
2734  }
2735  return AddDataProperty(&own_lookup, value, NONE, should_throw, store_origin);
2736}
2737
2738Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
2739                                         Handle<Object> receiver,
2740                                         Handle<Object> name,
2741                                         Handle<Object> value,
2742                                         Maybe<ShouldThrow> should_throw) {
2743  RETURN_FAILURE(
2744      isolate, GetShouldThrow(isolate, should_throw),
2745      NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
2746                   Object::TypeOf(isolate, receiver), receiver));
2747}
2748
2749Maybe<bool> Object::WriteToReadOnlyProperty(
2750    LookupIterator* it, Handle<Object> value,
2751    Maybe<ShouldThrow> maybe_should_throw) {
2752  ShouldThrow should_throw = GetShouldThrow(it->isolate(), maybe_should_throw);
2753  if (it->IsFound() && !it->HolderIsReceiver()) {
2754    // "Override mistake" attempted, record a use count to track this per
2755    // v8:8175
2756    v8::Isolate::UseCounterFeature feature =
2757        should_throw == kThrowOnError
2758            ? v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeStrict
2759            : v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeSloppy;
2760    it->isolate()->CountUsage(feature);
2761  }
2762  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
2763                                 it->GetName(), value, should_throw);
2764}
2765
2766Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
2767                                            Handle<Object> receiver,
2768                                            Handle<Object> name,
2769                                            Handle<Object> value,
2770                                            ShouldThrow should_throw) {
2771  RETURN_FAILURE(isolate, should_throw,
2772                 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
2773                              Object::TypeOf(isolate, receiver), receiver));
2774}
2775
2776Maybe<bool> Object::RedefineIncompatibleProperty(
2777    Isolate* isolate, Handle<Object> name, Handle<Object> value,
2778    Maybe<ShouldThrow> should_throw) {
2779  RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
2780                 NewTypeError(MessageTemplate::kRedefineDisallowed, name));
2781}
2782
2783Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
2784  Isolate* isolate = it->isolate();
2785  DCHECK_IMPLIES(it->GetReceiver()->IsJSProxy(isolate),
2786                 it->GetName()->IsPrivateName(isolate));
2787  DCHECK_IMPLIES(!it->IsElement() && it->GetName()->IsPrivateName(isolate),
2788                 it->state() == LookupIterator::DATA);
2789  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
2790
2791  // Store on the holder which may be hidden behind the receiver.
2792  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
2793
2794  Handle<Object> to_assign = value;
2795  // Convert the incoming value to a number for storing into typed arrays.
2796  if (it->IsElement() && receiver->IsJSObject(isolate) &&
2797      JSObject::cast(*receiver).HasTypedArrayOrRabGsabTypedArrayElements(
2798          isolate)) {
2799    ElementsKind elements_kind = JSObject::cast(*receiver).GetElementsKind();
2800    if (IsBigIntTypedArrayElementsKind(elements_kind)) {
2801      ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, to_assign,
2802                                       BigInt::FromObject(isolate, value),
2803                                       Nothing<bool>());
2804      // We have to recheck the length. However, it can only change if the
2805      // underlying buffer was detached, so just check that.
2806      if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
2807        return Just(true);
2808        // TODO(neis): According to the spec, this should throw a TypeError.
2809      }
2810    } else if (!value->IsNumber() && !value->IsUndefined(isolate)) {
2811      ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, to_assign,
2812                                       Object::ToNumber(isolate, value),
2813                                       Nothing<bool>());
2814      // We have to recheck the length. However, it can only change if the
2815      // underlying buffer was detached, so just check that.
2816      if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
2817        return Just(true);
2818        // TODO(neis): According to the spec, this should throw a TypeError.
2819      }
2820    }
2821  }
2822
2823#if V8_ENABLE_WEBASSEMBLY
2824  if (receiver->IsWasmObject(isolate)) {
2825    // Prepares given value for being stored into a field of given Wasm type
2826    // or throw if the value can't be stored into the field.
2827    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2828        isolate, to_assign,
2829        WasmObject::ToWasmValue(isolate, it->wasm_value_type(), to_assign),
2830        Nothing<bool>());
2831
2832    // Store prepared value.
2833    it->WriteDataValueToWasmObject(to_assign);
2834
2835  } else  // NOLINT(readability/braces)
2836#endif    // V8_ENABLE_WEBASSEMBLY
2837          // clang-format off
2838  if (V8_UNLIKELY(receiver->IsJSSharedStruct(isolate))) {
2839    // clang-format on
2840
2841    // Shared structs can only point to primitives or shared values.
2842    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2843        isolate, to_assign, Object::Share(isolate, to_assign, kThrowOnError),
2844        Nothing<bool>());
2845    it->WriteDataValue(to_assign, false);
2846  } else {
2847    // Possibly migrate to the most up-to-date map that will be able to store
2848    // |value| under it->name().
2849    it->PrepareForDataProperty(to_assign);
2850
2851    // Write the property value.
2852    it->WriteDataValue(to_assign, false);
2853  }
2854
2855#if VERIFY_HEAP
2856  if (FLAG_verify_heap) {
2857    receiver->HeapObjectVerify(isolate);
2858  }
2859#endif
2860  return Just(true);
2861}
2862
2863Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
2864                                    PropertyAttributes attributes,
2865                                    Maybe<ShouldThrow> should_throw,
2866                                    StoreOrigin store_origin,
2867                                    EnforceDefineSemantics semantics) {
2868  if (!it->GetReceiver()->IsJSReceiver()) {
2869    return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
2870                                value, should_throw);
2871  }
2872
2873  // Private symbols should be installed on JSProxy using
2874  // JSProxy::SetPrivateSymbol.
2875  if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate() &&
2876      !it->GetName()->IsPrivateName()) {
2877    RETURN_FAILURE(it->isolate(), GetShouldThrow(it->isolate(), should_throw),
2878                   NewTypeError(MessageTemplate::kProxyPrivate));
2879  }
2880
2881  DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
2882
2883  Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
2884  DCHECK_IMPLIES(receiver->IsJSProxy(), it->GetName()->IsPrivateName());
2885  DCHECK_IMPLIES(receiver->IsJSProxy(),
2886                 it->state() == LookupIterator::NOT_FOUND);
2887
2888  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
2889  // instead. If the prototype is Null, the proxy is detached.
2890  if (receiver->IsJSGlobalProxy()) return Just(true);
2891
2892  Isolate* isolate = it->isolate();
2893
2894  if (it->ExtendingNonExtensible(receiver)) {
2895    RETURN_FAILURE(isolate, GetShouldThrow(it->isolate(), should_throw),
2896                   NewTypeError(semantics == EnforceDefineSemantics::kDefine
2897                                    ? MessageTemplate::kDefineDisallowed
2898                                    : MessageTemplate::kObjectNotExtensible,
2899                                it->GetName()));
2900  }
2901
2902  if (it->IsElement(*receiver)) {
2903    if (receiver->IsJSArray()) {
2904      Handle<JSArray> array = Handle<JSArray>::cast(receiver);
2905      if (JSArray::WouldChangeReadOnlyLength(array, it->array_index())) {
2906        RETURN_FAILURE(isolate, GetShouldThrow(it->isolate(), should_throw),
2907                       NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
2908                                    isolate->factory()->length_string(),
2909                                    Object::TypeOf(isolate, array), array));
2910      }
2911    }
2912
2913    Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
2914    MAYBE_RETURN(JSObject::AddDataElement(receiver_obj, it->array_index(),
2915                                          value, attributes),
2916                 Nothing<bool>());
2917    JSObject::ValidateElements(*receiver_obj);
2918    return Just(true);
2919  }
2920
2921  return Object::TransitionAndWriteDataProperty(it, value, attributes,
2922                                                should_throw, store_origin);
2923}
2924
2925// static
2926Maybe<bool> Object::TransitionAndWriteDataProperty(
2927    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
2928    Maybe<ShouldThrow> should_throw, StoreOrigin store_origin) {
2929  Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
2930  it->UpdateProtector();
2931  // Migrate to the most up-to-date map that will be able to store |value|
2932  // under it->name() with |attributes|.
2933  it->PrepareTransitionToDataProperty(receiver, value, attributes,
2934                                      store_origin);
2935  DCHECK_EQ(LookupIterator::TRANSITION, it->state());
2936  it->ApplyTransitionToDataProperty(receiver);
2937
2938  // Write the property value.
2939  it->WriteDataValue(value, true);
2940
2941#if VERIFY_HEAP
2942    if (FLAG_verify_heap) {
2943      receiver->HeapObjectVerify(it->isolate());
2944    }
2945#endif
2946
2947    return Just(true);
2948}
2949// static
2950MaybeHandle<Object> Object::ShareSlow(Isolate* isolate,
2951                                      Handle<HeapObject> value,
2952                                      ShouldThrow throw_if_cannot_be_shared) {
2953  // Use Object::Share() if value might already be shared.
2954  DCHECK(!value->IsShared());
2955
2956  if (value->IsString()) {
2957    return String::Share(isolate, Handle<String>::cast(value));
2958  }
2959
2960  if (value->IsHeapNumber()) {
2961    uint64_t bits = HeapNumber::cast(*value).value_as_bits(kRelaxedLoad);
2962    return isolate->factory()
2963        ->NewHeapNumberFromBits<AllocationType::kSharedOld>(bits);
2964  }
2965
2966  if (throw_if_cannot_be_shared == kThrowOnError) {
2967    THROW_NEW_ERROR(
2968        isolate, NewTypeError(MessageTemplate::kCannotBeShared, value), Object);
2969  }
2970  return MaybeHandle<Object>();
2971}
2972
2973template <class T>
2974static int AppendUniqueCallbacks(Isolate* isolate,
2975                                 Handle<TemplateList> callbacks,
2976                                 Handle<typename T::Array> array,
2977                                 int valid_descriptors) {
2978  int nof_callbacks = callbacks->length();
2979
2980  // Fill in new callback descriptors.  Process the callbacks from
2981  // back to front so that the last callback with a given name takes
2982  // precedence over previously added callbacks with that name.
2983  for (int i = nof_callbacks - 1; i >= 0; i--) {
2984    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)), isolate);
2985    Handle<Name> key(Name::cast(entry->name()), isolate);
2986    DCHECK(key->IsUniqueName());
2987    // Check if a descriptor with this name already exists before writing.
2988    if (!T::Contains(key, entry, valid_descriptors, array)) {
2989      T::Insert(key, entry, valid_descriptors, array);
2990      valid_descriptors++;
2991    }
2992  }
2993
2994  return valid_descriptors;
2995}
2996
2997struct FixedArrayAppender {
2998  using Array = FixedArray;
2999  static bool Contains(Handle<Name> key, Handle<AccessorInfo> entry,
3000                       int valid_descriptors, Handle<FixedArray> array) {
3001    for (int i = 0; i < valid_descriptors; i++) {
3002      if (*key == AccessorInfo::cast(array->get(i)).name()) return true;
3003    }
3004    return false;
3005  }
3006  static void Insert(Handle<Name> key, Handle<AccessorInfo> entry,
3007                     int valid_descriptors, Handle<FixedArray> array) {
3008    DisallowGarbageCollection no_gc;
3009    array->set(valid_descriptors, *entry);
3010  }
3011};
3012
3013int AccessorInfo::AppendUnique(Isolate* isolate, Handle<Object> descriptors,
3014                               Handle<FixedArray> array,
3015                               int valid_descriptors) {
3016  Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
3017  DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
3018  return AppendUniqueCallbacks<FixedArrayAppender>(isolate, callbacks, array,
3019                                                   valid_descriptors);
3020}
3021
3022void JSProxy::Revoke(Handle<JSProxy> proxy) {
3023  Isolate* isolate = proxy->GetIsolate();
3024  // ES#sec-proxy-revocation-functions
3025  if (!proxy->IsRevoked()) {
3026    // 5. Set p.[[ProxyTarget]] to null.
3027    proxy->set_target(ReadOnlyRoots(isolate).null_value());
3028    // 6. Set p.[[ProxyHandler]] to null.
3029    proxy->set_handler(ReadOnlyRoots(isolate).null_value());
3030  }
3031  DCHECK(proxy->IsRevoked());
3032}
3033
3034// static
3035Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) {
3036  Isolate* isolate = proxy->GetIsolate();
3037  Handle<JSReceiver> object = Handle<JSReceiver>::cast(proxy);
3038  for (int i = 0; i < JSProxy::kMaxIterationLimit; i++) {
3039    proxy = Handle<JSProxy>::cast(object);
3040    if (proxy->IsRevoked()) {
3041      isolate->Throw(*isolate->factory()->NewTypeError(
3042          MessageTemplate::kProxyRevoked,
3043          isolate->factory()->NewStringFromAsciiChecked("IsArray")));
3044      return Nothing<bool>();
3045    }
3046    object = handle(JSReceiver::cast(proxy->target()), isolate);
3047    if (object->IsJSArray()) return Just(true);
3048    if (!object->IsJSProxy()) return Just(false);
3049  }
3050
3051  // Too deep recursion, throw a RangeError.
3052  isolate->StackOverflow();
3053  return Nothing<bool>();
3054}
3055
3056Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
3057                                 Handle<Name> name) {
3058  DCHECK(!name->IsPrivate());
3059  STACK_CHECK(isolate, Nothing<bool>());
3060  // 1. (Assert)
3061  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
3062  Handle<Object> handler(proxy->handler(), isolate);
3063  // 3. If handler is null, throw a TypeError exception.
3064  // 4. Assert: Type(handler) is Object.
3065  if (proxy->IsRevoked()) {
3066    isolate->Throw(*isolate->factory()->NewTypeError(
3067        MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
3068    return Nothing<bool>();
3069  }
3070  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
3071  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3072  // 6. Let trap be ? GetMethod(handler, "has").
3073  Handle<Object> trap;
3074  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3075      isolate, trap,
3076      Object::GetMethod(Handle<JSReceiver>::cast(handler),
3077                        isolate->factory()->has_string()),
3078      Nothing<bool>());
3079  // 7. If trap is undefined, then
3080  if (trap->IsUndefined(isolate)) {
3081    // 7a. Return target.[[HasProperty]](P).
3082    return JSReceiver::HasProperty(isolate, target, name);
3083  }
3084  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)).
3085  Handle<Object> trap_result_obj;
3086  Handle<Object> args[] = {target, name};
3087  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3088      isolate, trap_result_obj,
3089      Execution::Call(isolate, trap, handler, arraysize(args), args),
3090      Nothing<bool>());
3091  bool boolean_trap_result = trap_result_obj->BooleanValue(isolate);
3092  // 9. If booleanTrapResult is false, then:
3093  if (!boolean_trap_result) {
3094    MAYBE_RETURN(JSProxy::CheckHasTrap(isolate, name, target), Nothing<bool>());
3095  }
3096  // 10. Return booleanTrapResult.
3097  return Just(boolean_trap_result);
3098}
3099
3100Maybe<bool> JSProxy::CheckHasTrap(Isolate* isolate, Handle<Name> name,
3101                                  Handle<JSReceiver> target) {
3102  // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
3103  PropertyDescriptor target_desc;
3104  Maybe<bool> target_found =
3105      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
3106  MAYBE_RETURN(target_found, Nothing<bool>());
3107  // 9b. If targetDesc is not undefined, then:
3108  if (target_found.FromJust()) {
3109    // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
3110    //       exception.
3111    if (!target_desc.configurable()) {
3112      isolate->Throw(*isolate->factory()->NewTypeError(
3113          MessageTemplate::kProxyHasNonConfigurable, name));
3114      return Nothing<bool>();
3115    }
3116    // 9b ii. Let extensibleTarget be ? IsExtensible(target).
3117    Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3118    MAYBE_RETURN(extensible_target, Nothing<bool>());
3119    // 9b iii. If extensibleTarget is false, throw a TypeError exception.
3120    if (!extensible_target.FromJust()) {
3121      isolate->Throw(*isolate->factory()->NewTypeError(
3122          MessageTemplate::kProxyHasNonExtensible, name));
3123      return Nothing<bool>();
3124    }
3125  }
3126  return Just(true);
3127}
3128
3129Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
3130                                 Handle<Object> value, Handle<Object> receiver,
3131                                 Maybe<ShouldThrow> should_throw) {
3132  DCHECK(!name->IsPrivate());
3133  Isolate* isolate = proxy->GetIsolate();
3134  STACK_CHECK(isolate, Nothing<bool>());
3135  Factory* factory = isolate->factory();
3136  Handle<String> trap_name = factory->set_string();
3137
3138  if (proxy->IsRevoked()) {
3139    isolate->Throw(
3140        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3141    return Nothing<bool>();
3142  }
3143  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3144  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3145
3146  Handle<Object> trap;
3147  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3148      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3149  if (trap->IsUndefined(isolate)) {
3150    PropertyKey key(isolate, name);
3151    LookupIterator it(isolate, receiver, key, target);
3152
3153    return Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed,
3154                                    should_throw);
3155  }
3156
3157  Handle<Object> trap_result;
3158  Handle<Object> args[] = {target, name, value, receiver};
3159  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3160      isolate, trap_result,
3161      Execution::Call(isolate, trap, handler, arraysize(args), args),
3162      Nothing<bool>());
3163  if (!trap_result->BooleanValue(isolate)) {
3164    RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3165                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3166                                trap_name, name));
3167  }
3168
3169  MaybeHandle<Object> result =
3170      JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet);
3171
3172  if (result.is_null()) {
3173    return Nothing<bool>();
3174  }
3175  return Just(true);
3176}
3177
3178Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
3179                                             Handle<Name> name,
3180                                             LanguageMode language_mode) {
3181  DCHECK(!name->IsPrivate());
3182  ShouldThrow should_throw =
3183      is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
3184  Isolate* isolate = proxy->GetIsolate();
3185  STACK_CHECK(isolate, Nothing<bool>());
3186  Factory* factory = isolate->factory();
3187  Handle<String> trap_name = factory->deleteProperty_string();
3188
3189  if (proxy->IsRevoked()) {
3190    isolate->Throw(
3191        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3192    return Nothing<bool>();
3193  }
3194  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3195  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3196
3197  Handle<Object> trap;
3198  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3199      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3200  if (trap->IsUndefined(isolate)) {
3201    return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
3202  }
3203
3204  Handle<Object> trap_result;
3205  Handle<Object> args[] = {target, name};
3206  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3207      isolate, trap_result,
3208      Execution::Call(isolate, trap, handler, arraysize(args), args),
3209      Nothing<bool>());
3210  if (!trap_result->BooleanValue(isolate)) {
3211    RETURN_FAILURE(isolate, should_throw,
3212                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3213                                trap_name, name));
3214  }
3215
3216  // Enforce the invariant.
3217  return JSProxy::CheckDeleteTrap(isolate, name, target);
3218}
3219
3220Maybe<bool> JSProxy::CheckDeleteTrap(Isolate* isolate, Handle<Name> name,
3221                                     Handle<JSReceiver> target) {
3222  // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
3223  PropertyDescriptor target_desc;
3224  Maybe<bool> target_found =
3225      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
3226  MAYBE_RETURN(target_found, Nothing<bool>());
3227  // 11. If targetDesc is undefined, return true.
3228  if (target_found.FromJust()) {
3229    // 12. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
3230    if (!target_desc.configurable()) {
3231      isolate->Throw(*isolate->factory()->NewTypeError(
3232          MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
3233      return Nothing<bool>();
3234    }
3235    // 13. Let extensibleTarget be ? IsExtensible(target).
3236    Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3237    MAYBE_RETURN(extensible_target, Nothing<bool>());
3238    // 14. If extensibleTarget is false, throw a TypeError exception.
3239    if (!extensible_target.FromJust()) {
3240      isolate->Throw(*isolate->factory()->NewTypeError(
3241          MessageTemplate::kProxyDeletePropertyNonExtensible, name));
3242      return Nothing<bool>();
3243    }
3244  }
3245  return Just(true);
3246}
3247
3248// static
3249MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
3250                                  Handle<Object> handler) {
3251  if (!target->IsJSReceiver()) {
3252    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
3253                    JSProxy);
3254  }
3255  if (!handler->IsJSReceiver()) {
3256    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
3257                    JSProxy);
3258  }
3259  return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
3260                                        Handle<JSReceiver>::cast(handler));
3261}
3262
3263Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
3264  PropertyDescriptor desc;
3265  Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
3266      it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
3267  MAYBE_RETURN(found, Nothing<PropertyAttributes>());
3268  if (!found.FromJust()) return Just(ABSENT);
3269  return Just(desc.ToAttributes());
3270}
3271
3272// TODO(jkummerow): Consider unification with FastAsArrayLength() in
3273// accessors.cc.
3274bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
3275  DCHECK(value->IsNumber() || value->IsName());
3276  if (value->ToArrayLength(length)) return true;
3277  if (value->IsString()) return String::cast(*value).AsArrayIndex(length);
3278  return false;
3279}
3280
3281bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
3282  return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
3283}
3284
3285// ES6 9.4.2.1
3286// static
3287Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
3288                                       Handle<Object> name,
3289                                       PropertyDescriptor* desc,
3290                                       Maybe<ShouldThrow> should_throw) {
3291  // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
3292  // 2. If P is "length", then:
3293  // TODO(jkummerow): Check if we need slow string comparison.
3294  if (*name == ReadOnlyRoots(isolate).length_string()) {
3295    // 2a. Return ArraySetLength(A, Desc).
3296    return ArraySetLength(isolate, o, desc, should_throw);
3297  }
3298  // 3. Else if P is an array index, then:
3299  uint32_t index = 0;
3300  if (PropertyKeyToArrayIndex(name, &index)) {
3301    // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
3302    PropertyDescriptor old_len_desc;
3303    Maybe<bool> success = GetOwnPropertyDescriptor(
3304        isolate, o, isolate->factory()->length_string(), &old_len_desc);
3305    // 3b. (Assert)
3306    DCHECK(success.FromJust());
3307    USE(success);
3308    // 3c. Let oldLen be oldLenDesc.[[Value]].
3309    uint32_t old_len = 0;
3310    CHECK(old_len_desc.value()->ToArrayLength(&old_len));
3311    // 3d. Let index be ToUint32(P).
3312    // (Already done above.)
3313    // 3e. (Assert)
3314    // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
3315    //     return false.
3316    if (index >= old_len && old_len_desc.has_writable() &&
3317        !old_len_desc.writable()) {
3318      RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3319                     NewTypeError(MessageTemplate::kDefineDisallowed, name));
3320    }
3321    // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
3322    Maybe<bool> succeeded =
3323        OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
3324    // 3h. Assert: succeeded is not an abrupt completion.
3325    //     In our case, if should_throw == kThrowOnError, it can be!
3326    // 3i. If succeeded is false, return false.
3327    if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
3328    // 3j. If index >= oldLen, then:
3329    if (index >= old_len) {
3330      // 3j i. Set oldLenDesc.[[Value]] to index + 1.
3331      old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
3332      // 3j ii. Let succeeded be
3333      //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
3334      succeeded = OrdinaryDefineOwnProperty(isolate, o,
3335                                            isolate->factory()->length_string(),
3336                                            &old_len_desc, should_throw);
3337      // 3j iii. Assert: succeeded is true.
3338      DCHECK(succeeded.FromJust());
3339      USE(succeeded);
3340    }
3341    // 3k. Return true.
3342    return Just(true);
3343  }
3344
3345  // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
3346  return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
3347}
3348
3349// Part of ES6 9.4.2.4 ArraySetLength.
3350// static
3351bool JSArray::AnythingToArrayLength(Isolate* isolate,
3352                                    Handle<Object> length_object,
3353                                    uint32_t* output) {
3354  // Fast path: check numbers and strings that can be converted directly
3355  // and unobservably.
3356  if (length_object->ToArrayLength(output)) return true;
3357  if (length_object->IsString() &&
3358      Handle<String>::cast(length_object)->AsArrayIndex(output)) {
3359    return true;
3360  }
3361  // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
3362  // 3. Let newLen be ToUint32(Desc.[[Value]]).
3363  Handle<Object> uint32_v;
3364  if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
3365    // 4. ReturnIfAbrupt(newLen).
3366    return false;
3367  }
3368  // 5. Let numberLen be ToNumber(Desc.[[Value]]).
3369  Handle<Object> number_v;
3370  if (!Object::ToNumber(isolate, length_object).ToHandle(&number_v)) {
3371    // 6. ReturnIfAbrupt(newLen).
3372    return false;
3373  }
3374  // 7. If newLen != numberLen, throw a RangeError exception.
3375  if (uint32_v->Number() != number_v->Number()) {
3376    Handle<Object> exception =
3377        isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
3378    isolate->Throw(*exception);
3379    return false;
3380  }
3381  CHECK(uint32_v->ToArrayLength(output));
3382  return true;
3383}
3384
3385// ES6 9.4.2.4
3386// static
3387Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
3388                                    PropertyDescriptor* desc,
3389                                    Maybe<ShouldThrow> should_throw) {
3390  // 1. If the [[Value]] field of Desc is absent, then
3391  if (!desc->has_value()) {
3392    // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
3393    return OrdinaryDefineOwnProperty(
3394        isolate, a, isolate->factory()->length_string(), desc, should_throw);
3395  }
3396  // 2. Let newLenDesc be a copy of Desc.
3397  // (Actual copying is not necessary.)
3398  PropertyDescriptor* new_len_desc = desc;
3399  // 3. - 7. Convert Desc.[[Value]] to newLen.
3400  uint32_t new_len = 0;
3401  if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
3402    DCHECK(isolate->has_pending_exception());
3403    return Nothing<bool>();
3404  }
3405  // 8. Set newLenDesc.[[Value]] to newLen.
3406  // (Done below, if needed.)
3407  // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
3408  PropertyDescriptor old_len_desc;
3409  Maybe<bool> success = GetOwnPropertyDescriptor(
3410      isolate, a, isolate->factory()->length_string(), &old_len_desc);
3411  // 10. (Assert)
3412  DCHECK(success.FromJust());
3413  USE(success);
3414  // 11. Let oldLen be oldLenDesc.[[Value]].
3415  uint32_t old_len = 0;
3416  CHECK(old_len_desc.value()->ToArrayLength(&old_len));
3417  // 12. If newLen >= oldLen, then
3418  if (new_len >= old_len) {
3419    // 8. Set newLenDesc.[[Value]] to newLen.
3420    // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
3421    new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
3422    return OrdinaryDefineOwnProperty(isolate, a,
3423                                     isolate->factory()->length_string(),
3424                                     new_len_desc, should_throw);
3425  }
3426  // 13. If oldLenDesc.[[Writable]] is false, return false.
3427  if (!old_len_desc.writable() ||
3428      // Also handle the {configurable: true} and enumerable changes
3429      // since we later use JSArray::SetLength instead of
3430      // OrdinaryDefineOwnProperty to change the length,
3431      // and it doesn't have access to the descriptor anymore.
3432      new_len_desc->configurable() ||
3433      (new_len_desc->has_enumerable() &&
3434       (old_len_desc.enumerable() != new_len_desc->enumerable()))) {
3435    RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3436                   NewTypeError(MessageTemplate::kRedefineDisallowed,
3437                                isolate->factory()->length_string()));
3438  }
3439  // 14. If newLenDesc.[[Writable]] is absent or has the value true,
3440  // let newWritable be true.
3441  bool new_writable = false;
3442  if (!new_len_desc->has_writable() || new_len_desc->writable()) {
3443    new_writable = true;
3444  } else {
3445    // 15. Else,
3446    // 15a. Need to defer setting the [[Writable]] attribute to false in case
3447    //      any elements cannot be deleted.
3448    // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
3449    // 15c. Set newLenDesc.[[Writable]] to true.
3450    // (Not needed.)
3451  }
3452  // Most of steps 16 through 19 is implemented by JSArray::SetLength.
3453  MAYBE_RETURN(JSArray::SetLength(a, new_len), Nothing<bool>());
3454  // Steps 19d-ii, 20.
3455  if (!new_writable) {
3456    PropertyDescriptor readonly;
3457    readonly.set_writable(false);
3458    success = OrdinaryDefineOwnProperty(isolate, a,
3459                                        isolate->factory()->length_string(),
3460                                        &readonly, should_throw);
3461    DCHECK(success.FromJust());
3462    USE(success);
3463  }
3464  uint32_t actual_new_len = 0;
3465  CHECK(a->length().ToArrayLength(&actual_new_len));
3466  // Steps 19d-v, 21. Return false if there were non-deletable elements.
3467  bool result = actual_new_len == new_len;
3468  if (!result) {
3469    RETURN_FAILURE(
3470        isolate, GetShouldThrow(isolate, should_throw),
3471        NewTypeError(MessageTemplate::kStrictDeleteProperty,
3472                     isolate->factory()->NewNumberFromUint(actual_new_len - 1),
3473                     a));
3474  }
3475  return Just(result);
3476}
3477
3478// ES6 9.5.6
3479// static
3480Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
3481                                       Handle<Object> key,
3482                                       PropertyDescriptor* desc,
3483                                       Maybe<ShouldThrow> should_throw) {
3484  STACK_CHECK(isolate, Nothing<bool>());
3485  if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
3486    DCHECK(!Handle<Symbol>::cast(key)->IsPrivateName());
3487    return JSProxy::SetPrivateSymbol(isolate, proxy, Handle<Symbol>::cast(key),
3488                                     desc, should_throw);
3489  }
3490  Handle<String> trap_name = isolate->factory()->defineProperty_string();
3491  // 1. Assert: IsPropertyKey(P) is true.
3492  DCHECK(key->IsName() || key->IsNumber());
3493  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
3494  Handle<Object> handler(proxy->handler(), isolate);
3495  // 3. If handler is null, throw a TypeError exception.
3496  // 4. Assert: Type(handler) is Object.
3497  if (proxy->IsRevoked()) {
3498    isolate->Throw(*isolate->factory()->NewTypeError(
3499        MessageTemplate::kProxyRevoked, trap_name));
3500    return Nothing<bool>();
3501  }
3502  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
3503  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3504  // 6. Let trap be ? GetMethod(handler, "defineProperty").
3505  Handle<Object> trap;
3506  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3507      isolate, trap,
3508      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
3509      Nothing<bool>());
3510  // 7. If trap is undefined, then:
3511  if (trap->IsUndefined(isolate)) {
3512    // 7a. Return target.[[DefineOwnProperty]](P, Desc).
3513    return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
3514                                         should_throw);
3515  }
3516  // 8. Let descObj be FromPropertyDescriptor(Desc).
3517  Handle<Object> desc_obj = desc->ToObject(isolate);
3518  // 9. Let booleanTrapResult be
3519  //    ToBoolean(? Call(trap, handler, «target, P, descObj»)).
3520  Handle<Name> property_name =
3521      key->IsName()
3522          ? Handle<Name>::cast(key)
3523          : Handle<Name>::cast(isolate->factory()->NumberToString(key));
3524  // Do not leak private property names.
3525  DCHECK(!property_name->IsPrivate());
3526  Handle<Object> trap_result_obj;
3527  Handle<Object> args[] = {target, property_name, desc_obj};
3528  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3529      isolate, trap_result_obj,
3530      Execution::Call(isolate, trap, handler, arraysize(args), args),
3531      Nothing<bool>());
3532  // 10. If booleanTrapResult is false, return false.
3533  if (!trap_result_obj->BooleanValue(isolate)) {
3534    RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3535                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3536                                trap_name, property_name));
3537  }
3538  // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
3539  PropertyDescriptor target_desc;
3540  Maybe<bool> target_found =
3541      JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
3542  MAYBE_RETURN(target_found, Nothing<bool>());
3543  // 12. Let extensibleTarget be ? IsExtensible(target).
3544  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
3545  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
3546  bool extensible_target = maybe_extensible.FromJust();
3547  // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
3548  //     is false, then:
3549  // 13a. Let settingConfigFalse be true.
3550  // 14. Else let settingConfigFalse be false.
3551  bool setting_config_false = desc->has_configurable() && !desc->configurable();
3552  // 15. If targetDesc is undefined, then
3553  if (!target_found.FromJust()) {
3554    // 15a. If extensibleTarget is false, throw a TypeError exception.
3555    if (!extensible_target) {
3556      isolate->Throw(*isolate->factory()->NewTypeError(
3557          MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
3558      return Nothing<bool>();
3559    }
3560    // 15b. If settingConfigFalse is true, throw a TypeError exception.
3561    if (setting_config_false) {
3562      isolate->Throw(*isolate->factory()->NewTypeError(
3563          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
3564      return Nothing<bool>();
3565    }
3566  } else {
3567    // 16. Else targetDesc is not undefined,
3568    // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
3569    //      targetDesc) is false, throw a TypeError exception.
3570    Maybe<bool> valid = IsCompatiblePropertyDescriptor(
3571        isolate, extensible_target, desc, &target_desc, property_name,
3572        Just(kDontThrow));
3573    MAYBE_RETURN(valid, Nothing<bool>());
3574    if (!valid.FromJust()) {
3575      isolate->Throw(*isolate->factory()->NewTypeError(
3576          MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
3577      return Nothing<bool>();
3578    }
3579    // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
3580    //      true, throw a TypeError exception.
3581    if (setting_config_false && target_desc.configurable()) {
3582      isolate->Throw(*isolate->factory()->NewTypeError(
3583          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
3584      return Nothing<bool>();
3585    }
3586    // 16c. If IsDataDescriptor(targetDesc) is true,
3587    // targetDesc.[[Configurable]] is
3588    //       false, and targetDesc.[[Writable]] is true, then
3589    if (PropertyDescriptor::IsDataDescriptor(&target_desc) &&
3590        !target_desc.configurable() && target_desc.writable()) {
3591      // 16c i. If Desc has a [[Writable]] field and Desc.[[Writable]] is false,
3592      // throw a TypeError exception.
3593      if (desc->has_writable() && !desc->writable()) {
3594        isolate->Throw(*isolate->factory()->NewTypeError(
3595            MessageTemplate::kProxyDefinePropertyNonConfigurableWritable,
3596            property_name));
3597        return Nothing<bool>();
3598      }
3599    }
3600  }
3601  // 17. Return true.
3602  return Just(true);
3603}
3604
3605// static
3606Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
3607                                      Handle<Symbol> private_name,
3608                                      PropertyDescriptor* desc,
3609                                      Maybe<ShouldThrow> should_throw) {
3610  // Despite the generic name, this can only add private data properties.
3611  if (!PropertyDescriptor::IsDataDescriptor(desc) ||
3612      desc->ToAttributes() != DONT_ENUM) {
3613    RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3614                   NewTypeError(MessageTemplate::kProxyPrivate));
3615  }
3616  DCHECK(proxy->map().is_dictionary_map());
3617  Handle<Object> value =
3618      desc->has_value()
3619          ? desc->value()
3620          : Handle<Object>::cast(isolate->factory()->undefined_value());
3621
3622  LookupIterator it(isolate, proxy, private_name, proxy);
3623
3624  if (it.IsFound()) {
3625    DCHECK_EQ(LookupIterator::DATA, it.state());
3626    DCHECK_EQ(DONT_ENUM, it.property_attributes());
3627    // We are not tracking constness for private symbols added to JSProxy
3628    // objects.
3629    DCHECK_EQ(PropertyConstness::kMutable, it.property_details().constness());
3630    it.WriteDataValue(value, false);
3631    return Just(true);
3632  }
3633
3634  PropertyDetails details(PropertyKind::kData, DONT_ENUM,
3635                          PropertyConstness::kMutable);
3636  if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
3637    Handle<SwissNameDictionary> dict(proxy->property_dictionary_swiss(),
3638                                     isolate);
3639    Handle<SwissNameDictionary> result =
3640        SwissNameDictionary::Add(isolate, dict, private_name, value, details);
3641    if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
3642  } else {
3643    Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
3644    Handle<NameDictionary> result =
3645        NameDictionary::Add(isolate, dict, private_name, value, details);
3646    if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
3647  }
3648  return Just(true);
3649}
3650
3651// ES6 9.5.5
3652// static
3653Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
3654                                              Handle<JSProxy> proxy,
3655                                              Handle<Name> name,
3656                                              PropertyDescriptor* desc) {
3657  DCHECK(!name->IsPrivate());
3658  STACK_CHECK(isolate, Nothing<bool>());
3659
3660  Handle<String> trap_name =
3661      isolate->factory()->getOwnPropertyDescriptor_string();
3662  // 1. (Assert)
3663  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
3664  Handle<Object> handler(proxy->handler(), isolate);
3665  // 3. If handler is null, throw a TypeError exception.
3666  // 4. Assert: Type(handler) is Object.
3667  if (proxy->IsRevoked()) {
3668    isolate->Throw(*isolate->factory()->NewTypeError(
3669        MessageTemplate::kProxyRevoked, trap_name));
3670    return Nothing<bool>();
3671  }
3672  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
3673  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3674  // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
3675  Handle<Object> trap;
3676  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3677      isolate, trap,
3678      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
3679      Nothing<bool>());
3680  // 7. If trap is undefined, then
3681  if (trap->IsUndefined(isolate)) {
3682    // 7a. Return target.[[GetOwnProperty]](P).
3683    return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
3684  }
3685  // 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
3686  Handle<Object> trap_result_obj;
3687  Handle<Object> args[] = {target, name};
3688  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3689      isolate, trap_result_obj,
3690      Execution::Call(isolate, trap, handler, arraysize(args), args),
3691      Nothing<bool>());
3692  // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
3693  //    TypeError exception.
3694  if (!trap_result_obj->IsJSReceiver() &&
3695      !trap_result_obj->IsUndefined(isolate)) {
3696    isolate->Throw(*isolate->factory()->NewTypeError(
3697        MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
3698    return Nothing<bool>();
3699  }
3700  // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
3701  PropertyDescriptor target_desc;
3702  Maybe<bool> found =
3703      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
3704  MAYBE_RETURN(found, Nothing<bool>());
3705  // 11. If trapResultObj is undefined, then
3706  if (trap_result_obj->IsUndefined(isolate)) {
3707    // 11a. If targetDesc is undefined, return undefined.
3708    if (!found.FromJust()) return Just(false);
3709    // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
3710    //      exception.
3711    if (!target_desc.configurable()) {
3712      isolate->Throw(*isolate->factory()->NewTypeError(
3713          MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
3714      return Nothing<bool>();
3715    }
3716    // 11c. Let extensibleTarget be ? IsExtensible(target).
3717    Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3718    MAYBE_RETURN(extensible_target, Nothing<bool>());
3719    // 11d. (Assert)
3720    // 11e. If extensibleTarget is false, throw a TypeError exception.
3721    if (!extensible_target.FromJust()) {
3722      isolate->Throw(*isolate->factory()->NewTypeError(
3723          MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
3724      return Nothing<bool>();
3725    }
3726    // 11f. Return undefined.
3727    return Just(false);
3728  }
3729  // 12. Let extensibleTarget be ? IsExtensible(target).
3730  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3731  MAYBE_RETURN(extensible_target, Nothing<bool>());
3732  // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
3733  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
3734                                                desc)) {
3735    DCHECK(isolate->has_pending_exception());
3736    return Nothing<bool>();
3737  }
3738  // 14. Call CompletePropertyDescriptor(resultDesc).
3739  PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
3740  // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
3741  //     resultDesc, targetDesc).
3742  Maybe<bool> valid = IsCompatiblePropertyDescriptor(
3743      isolate, extensible_target.FromJust(), desc, &target_desc, name,
3744      Just(kDontThrow));
3745  MAYBE_RETURN(valid, Nothing<bool>());
3746  // 16. If valid is false, throw a TypeError exception.
3747  if (!valid.FromJust()) {
3748    isolate->Throw(*isolate->factory()->NewTypeError(
3749        MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
3750    return Nothing<bool>();
3751  }
3752  // 17. If resultDesc.[[Configurable]] is false, then
3753  if (!desc->configurable()) {
3754    // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
3755    if (target_desc.is_empty() || target_desc.configurable()) {
3756      // 17a i. Throw a TypeError exception.
3757      isolate->Throw(*isolate->factory()->NewTypeError(
3758          MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
3759          name));
3760      return Nothing<bool>();
3761    }
3762    // 17b. If resultDesc has a [[Writable]] field and resultDesc.[[Writable]]
3763    // is false, then
3764    if (desc->has_writable() && !desc->writable()) {
3765      // 17b i. If targetDesc.[[Writable]] is true, throw a TypeError exception.
3766      if (target_desc.writable()) {
3767        isolate->Throw(*isolate->factory()->NewTypeError(
3768            MessageTemplate::
3769                kProxyGetOwnPropertyDescriptorNonConfigurableWritable,
3770            name));
3771        return Nothing<bool>();
3772      }
3773    }
3774  }
3775  // 18. Return resultDesc.
3776  return Just(true);
3777}
3778
3779Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
3780                                       ShouldThrow should_throw) {
3781  Isolate* isolate = proxy->GetIsolate();
3782  STACK_CHECK(isolate, Nothing<bool>());
3783  Factory* factory = isolate->factory();
3784  Handle<String> trap_name = factory->preventExtensions_string();
3785
3786  if (proxy->IsRevoked()) {
3787    isolate->Throw(
3788        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3789    return Nothing<bool>();
3790  }
3791  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3792  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3793
3794  Handle<Object> trap;
3795  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3796      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3797  if (trap->IsUndefined(isolate)) {
3798    return JSReceiver::PreventExtensions(target, should_throw);
3799  }
3800
3801  Handle<Object> trap_result;
3802  Handle<Object> args[] = {target};
3803  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3804      isolate, trap_result,
3805      Execution::Call(isolate, trap, handler, arraysize(args), args),
3806      Nothing<bool>());
3807  if (!trap_result->BooleanValue(isolate)) {
3808    RETURN_FAILURE(
3809        isolate, should_throw,
3810        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
3811  }
3812
3813  // Enforce the invariant.
3814  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
3815  MAYBE_RETURN(target_result, Nothing<bool>());
3816  if (target_result.FromJust()) {
3817    isolate->Throw(*factory->NewTypeError(
3818        MessageTemplate::kProxyPreventExtensionsExtensible));
3819    return Nothing<bool>();
3820  }
3821  return Just(true);
3822}
3823
3824Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
3825  Isolate* isolate = proxy->GetIsolate();
3826  STACK_CHECK(isolate, Nothing<bool>());
3827  Factory* factory = isolate->factory();
3828  Handle<String> trap_name = factory->isExtensible_string();
3829
3830  if (proxy->IsRevoked()) {
3831    isolate->Throw(
3832        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3833    return Nothing<bool>();
3834  }
3835  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3836  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3837
3838  Handle<Object> trap;
3839  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3840      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3841  if (trap->IsUndefined(isolate)) {
3842    return JSReceiver::IsExtensible(target);
3843  }
3844
3845  Handle<Object> trap_result;
3846  Handle<Object> args[] = {target};
3847  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3848      isolate, trap_result,
3849      Execution::Call(isolate, trap, handler, arraysize(args), args),
3850      Nothing<bool>());
3851
3852  // Enforce the invariant.
3853  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
3854  MAYBE_RETURN(target_result, Nothing<bool>());
3855  if (target_result.FromJust() != trap_result->BooleanValue(isolate)) {
3856    isolate->Throw(
3857        *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
3858                               factory->ToBoolean(target_result.FromJust())));
3859    return Nothing<bool>();
3860  }
3861  return target_result;
3862}
3863
3864Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
3865                                                  Handle<DescriptorArray> desc,
3866                                                  int enumeration_index,
3867                                                  int slack) {
3868  return DescriptorArray::CopyUpToAddAttributes(isolate, desc,
3869                                                enumeration_index, NONE, slack);
3870}
3871
3872Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
3873    Isolate* isolate, Handle<DescriptorArray> source_handle,
3874    int enumeration_index, PropertyAttributes attributes, int slack) {
3875  if (enumeration_index + slack == 0) {
3876    return isolate->factory()->empty_descriptor_array();
3877  }
3878
3879  int size = enumeration_index;
3880  Handle<DescriptorArray> copy_handle =
3881      DescriptorArray::Allocate(isolate, size, slack);
3882
3883  DisallowGarbageCollection no_gc;
3884  auto source = *source_handle;
3885  auto copy = *copy_handle;
3886
3887  if (attributes != NONE) {
3888    for (InternalIndex i : InternalIndex::Range(size)) {
3889      MaybeObject value_or_field_type = source.GetValue(i);
3890      Name key = source.GetKey(i);
3891      PropertyDetails details = source.GetDetails(i);
3892      // Bulk attribute changes never affect private properties.
3893      if (!key.IsPrivate()) {
3894        int mask = DONT_DELETE | DONT_ENUM;
3895        // READ_ONLY is an invalid attribute for JS setters/getters.
3896        HeapObject heap_object;
3897        if (details.kind() != PropertyKind::kAccessor ||
3898            !(value_or_field_type->GetHeapObjectIfStrong(&heap_object) &&
3899              heap_object.IsAccessorPair())) {
3900          mask |= READ_ONLY;
3901        }
3902        details = details.CopyAddAttributes(
3903            static_cast<PropertyAttributes>(attributes & mask));
3904      }
3905      copy.Set(i, key, value_or_field_type, details);
3906    }
3907  } else {
3908    for (InternalIndex i : InternalIndex::Range(size)) {
3909      copy.CopyFrom(i, source);
3910    }
3911  }
3912
3913  if (source.number_of_descriptors() != enumeration_index) copy.Sort();
3914
3915  return copy_handle;
3916}
3917
3918// Create a new descriptor array with only enumerable, configurable, writeable
3919// data properties, but identical field locations.
3920Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
3921    Isolate* isolate, Handle<DescriptorArray> src_handle, int enumeration_index,
3922    int slack) {
3923  if (enumeration_index + slack == 0) {
3924    return isolate->factory()->empty_descriptor_array();
3925  }
3926
3927  int size = enumeration_index;
3928  Handle<DescriptorArray> descriptors_handle =
3929      DescriptorArray::Allocate(isolate, size, slack);
3930
3931  DisallowGarbageCollection no_gc;
3932  auto src = *src_handle;
3933  auto descriptors = *descriptors_handle;
3934
3935  for (InternalIndex i : InternalIndex::Range(size)) {
3936    Name key = src.GetKey(i);
3937    PropertyDetails details = src.GetDetails(i);
3938    Representation new_representation = details.representation();
3939
3940    DCHECK(!key.IsPrivateName());
3941    DCHECK(details.IsEnumerable());
3942    DCHECK_EQ(details.kind(), PropertyKind::kData);
3943    // If the new representation is an in-place changeable field, make it
3944    // generic as possible (under in-place changes) to avoid type confusion if
3945    // the source representation changes after this feedback has been collected.
3946    MaybeObject type = src.GetValue(i);
3947    if (details.location() == PropertyLocation::kField) {
3948      type = MaybeObject::FromObject(FieldType::Any());
3949      // TODO(bmeurer,ishell): Igor suggested to use some kind of dynamic
3950      // checks in the fast-path for CloneObjectIC instead to avoid the
3951      // need to generalize the descriptors here. That will also enable
3952      // us to skip the defensive copying of the target map whenever a
3953      // CloneObjectIC misses.
3954      new_representation = new_representation.MostGenericInPlaceChange();
3955    }
3956
3957    // Ensure the ObjectClone property details are NONE, and that all source
3958    // details did not contain DONT_ENUM.
3959    PropertyDetails new_details(PropertyKind::kData, NONE, details.location(),
3960                                details.constness(), new_representation,
3961                                details.field_index());
3962
3963    descriptors.Set(i, key, type, new_details);
3964  }
3965
3966  descriptors.Sort();
3967
3968  return descriptors_handle;
3969}
3970
3971bool DescriptorArray::IsEqualUpTo(DescriptorArray desc, int nof_descriptors) {
3972  for (InternalIndex i : InternalIndex::Range(nof_descriptors)) {
3973    if (GetKey(i) != desc.GetKey(i) || GetValue(i) != desc.GetValue(i)) {
3974      return false;
3975    }
3976    PropertyDetails details = GetDetails(i);
3977    PropertyDetails other_details = desc.GetDetails(i);
3978    if (details.kind() != other_details.kind() ||
3979        details.location() != other_details.location() ||
3980        !details.representation().Equals(other_details.representation())) {
3981      return false;
3982    }
3983  }
3984  return true;
3985}
3986
3987Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
3988                                          Handle<FixedArray> array, int index,
3989                                          Handle<Object> value) {
3990  if (index < array->length()) {
3991    array->set(index, *value);
3992    return array;
3993  }
3994  int capacity = array->length();
3995  do {
3996    capacity = JSObject::NewElementsCapacity(capacity);
3997  } while (capacity <= index);
3998  Handle<FixedArray> new_array = isolate->factory()->NewFixedArray(capacity);
3999  array->CopyTo(0, *new_array, 0, array->length());
4000  new_array->FillWithHoles(array->length(), new_array->length());
4001  new_array->set(index, *value);
4002  return new_array;
4003}
4004
4005Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
4006                                             Handle<FixedArray> array,
4007                                             int new_length) {
4008  if (new_length == 0) {
4009    return array->GetReadOnlyRoots().empty_fixed_array_handle();
4010  } else {
4011    array->Shrink(isolate, new_length);
4012    return array;
4013  }
4014}
4015
4016void FixedArray::Shrink(Isolate* isolate, int new_length) {
4017  DCHECK(0 < new_length && new_length <= length());
4018  if (new_length < length()) {
4019    isolate->heap()->RightTrimFixedArray(*this, length() - new_length);
4020  }
4021}
4022
4023void FixedArray::CopyTo(int pos, FixedArray dest, int dest_pos, int len) const {
4024  DisallowGarbageCollection no_gc;
4025  // Return early if len == 0 so that we don't try to read the write barrier off
4026  // a canonical read-only empty fixed array.
4027  if (len == 0) return;
4028  WriteBarrierMode mode = dest.GetWriteBarrierMode(no_gc);
4029  for (int index = 0; index < len; index++) {
4030    dest.set(dest_pos + index, get(pos + index), mode);
4031  }
4032}
4033
4034// static
4035Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
4036                                 Handle<Object> obj) {
4037  int length = array->Length();
4038  array = EnsureSpace(isolate, array, length + 1);
4039  // Check that GC didn't remove elements from the array.
4040  DCHECK_EQ(array->Length(), length);
4041  {
4042    DisallowGarbageCollection no_gc;
4043    ArrayList raw_array = *array;
4044    raw_array.Set(length, *obj);
4045    raw_array.SetLength(length + 1);
4046  }
4047  return array;
4048}
4049
4050// static
4051Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
4052                                 Handle<Object> obj1, Handle<Object> obj2) {
4053  int length = array->Length();
4054  array = EnsureSpace(isolate, array, length + 2);
4055  // Check that GC didn't remove elements from the array.
4056  DCHECK_EQ(array->Length(), length);
4057  {
4058    DisallowGarbageCollection no_gc;
4059    ArrayList raw_array = *array;
4060    raw_array.Set(length, *obj1);
4061    raw_array.Set(length + 1, *obj2);
4062    raw_array.SetLength(length + 2);
4063  }
4064  return array;
4065}
4066
4067Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
4068                                 Handle<Object> obj1, Smi obj2, Smi obj3,
4069                                 Smi obj4) {
4070  int length = array->Length();
4071  array = EnsureSpace(isolate, array, length + 4);
4072  // Check that GC didn't remove elements from the array.
4073  DCHECK_EQ(array->Length(), length);
4074  {
4075    DisallowGarbageCollection no_gc;
4076    ArrayList raw_array = *array;
4077    raw_array.Set(length, *obj1);
4078    raw_array.Set(length + 1, obj2);
4079    raw_array.Set(length + 2, obj3);
4080    raw_array.Set(length + 3, obj4);
4081    raw_array.SetLength(length + 4);
4082  }
4083  return array;
4084}
4085
4086// static
4087Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) {
4088  return isolate->factory()->NewArrayList(size);
4089}
4090
4091Handle<FixedArray> ArrayList::Elements(Isolate* isolate,
4092                                       Handle<ArrayList> array) {
4093  int length = array->Length();
4094  Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
4095  // Do not copy the first entry, i.e., the length.
4096  array->CopyTo(kFirstIndex, *result, 0, length);
4097  return result;
4098}
4099
4100namespace {
4101
4102Handle<FixedArray> EnsureSpaceInFixedArray(Isolate* isolate,
4103                                           Handle<FixedArray> array,
4104                                           int length) {
4105  int capacity = array->length();
4106  if (capacity < length) {
4107    int new_capacity = length;
4108    new_capacity = new_capacity + std::max(new_capacity / 2, 2);
4109    int grow_by = new_capacity - capacity;
4110    array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
4111  }
4112  return array;
4113}
4114
4115}  // namespace
4116
4117// static
4118Handle<ArrayList> ArrayList::EnsureSpace(Isolate* isolate,
4119                                         Handle<ArrayList> array, int length) {
4120  DCHECK_LT(0, length);
4121  auto new_array = Handle<ArrayList>::cast(
4122      EnsureSpaceInFixedArray(isolate, array, kFirstIndex + length));
4123  DCHECK_EQ(array->Length(), new_array->Length());
4124  return new_array;
4125}
4126
4127// static
4128Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
4129                                              Handle<WeakArrayList> array,
4130                                              const MaybeObjectHandle& value) {
4131  int length = array->length();
4132  array = EnsureSpace(isolate, array, length + 1);
4133  {
4134    DisallowGarbageCollection no_gc;
4135    WeakArrayList raw = *array;
4136    // Reload length; GC might have removed elements from the array.
4137    length = raw.length();
4138    raw.Set(length, *value);
4139    raw.set_length(length + 1);
4140  }
4141  return array;
4142}
4143
4144Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
4145                                              Handle<WeakArrayList> array,
4146                                              const MaybeObjectHandle& value1,
4147                                              const MaybeObjectHandle& value2) {
4148  int length = array->length();
4149  array = EnsureSpace(isolate, array, length + 2);
4150  {
4151    DisallowGarbageCollection no_gc;
4152    WeakArrayList raw = *array;
4153    // Reload length; GC might have removed elements from the array.
4154    length = array->length();
4155    raw.Set(length, *value1);
4156    raw.Set(length + 1, *value2);
4157    raw.set_length(length + 2);
4158  }
4159  return array;
4160}
4161
4162// static
4163Handle<WeakArrayList> WeakArrayList::Append(Isolate* isolate,
4164                                            Handle<WeakArrayList> array,
4165                                            const MaybeObjectHandle& value,
4166                                            AllocationType allocation) {
4167  int length = 0;
4168  int new_length = 0;
4169  {
4170    DisallowGarbageCollection no_gc;
4171    WeakArrayList raw = *array;
4172    length = raw.length();
4173
4174    if (length < raw.capacity()) {
4175      raw.Set(length, *value);
4176      raw.set_length(length + 1);
4177      return array;
4178    }
4179
4180    // Not enough space in the array left, either grow, shrink or
4181    // compact the array.
4182    new_length = raw.CountLiveElements() + 1;
4183  }
4184
4185  bool shrink = new_length < length / 4;
4186  bool grow = 3 * (length / 4) < new_length;
4187
4188  if (shrink || grow) {
4189    // Grow or shrink array and compact out-of-place.
4190    int new_capacity = CapacityForLength(new_length);
4191    array = isolate->factory()->CompactWeakArrayList(array, new_capacity,
4192                                                     allocation);
4193
4194  } else {
4195    // Perform compaction in the current array.
4196    array->Compact(isolate);
4197  }
4198
4199  // Now append value to the array, there should always be enough space now.
4200  DCHECK_LT(array->length(), array->capacity());
4201
4202  {
4203    DisallowGarbageCollection no_gc;
4204    WeakArrayList raw = *array;
4205    // Reload length, allocation might have killed some weak refs.
4206    int index = raw.length();
4207    raw.Set(index, *value);
4208    raw.set_length(index + 1);
4209  }
4210  return array;
4211}
4212
4213void WeakArrayList::Compact(Isolate* isolate) {
4214  DisallowGarbageCollection no_gc;
4215  int length = this->length();
4216  int new_length = 0;
4217
4218  for (int i = 0; i < length; i++) {
4219    MaybeObject value = Get(isolate, i);
4220
4221    if (!value->IsCleared()) {
4222      if (new_length != i) {
4223        Set(new_length, value);
4224      }
4225      ++new_length;
4226    }
4227  }
4228
4229  set_length(new_length);
4230}
4231
4232bool WeakArrayList::IsFull() const { return length() == capacity(); }
4233
4234// static
4235Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
4236                                                 Handle<WeakArrayList> array,
4237                                                 int length,
4238                                                 AllocationType allocation) {
4239  int capacity = array->capacity();
4240  if (capacity < length) {
4241    int grow_by = CapacityForLength(length) - capacity;
4242    array = isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by,
4243                                                         allocation);
4244  }
4245  return array;
4246}
4247
4248int WeakArrayList::CountLiveWeakReferences() const {
4249  int live_weak_references = 0;
4250  for (int i = 0; i < length(); i++) {
4251    if (Get(i)->IsWeak()) {
4252      ++live_weak_references;
4253    }
4254  }
4255  return live_weak_references;
4256}
4257
4258int WeakArrayList::CountLiveElements() const {
4259  int non_cleared_objects = 0;
4260  for (int i = 0; i < length(); i++) {
4261    if (!Get(i)->IsCleared()) {
4262      ++non_cleared_objects;
4263    }
4264  }
4265  return non_cleared_objects;
4266}
4267
4268bool WeakArrayList::RemoveOne(const MaybeObjectHandle& value) {
4269  if (length() == 0) return false;
4270  // Optimize for the most recently added element to be removed again.
4271  MaybeObject cleared_weak_ref =
4272      HeapObjectReference::ClearedValue(GetIsolate());
4273  int last_index = length() - 1;
4274  for (int i = last_index; i >= 0; --i) {
4275    if (Get(i) == *value) {
4276      // Move the last element into the this slot (or no-op, if this is the
4277      // last slot).
4278      Set(i, Get(last_index));
4279      Set(last_index, cleared_weak_ref);
4280      set_length(last_index);
4281      return true;
4282    }
4283  }
4284  return false;
4285}
4286
4287// static
4288Handle<WeakArrayList> PrototypeUsers::Add(Isolate* isolate,
4289                                          Handle<WeakArrayList> array,
4290                                          Handle<Map> value,
4291                                          int* assigned_index) {
4292  int length = array->length();
4293  if (length == 0) {
4294    // Uninitialized WeakArrayList; need to initialize empty_slot_index.
4295    array = WeakArrayList::EnsureSpace(isolate, array, kFirstIndex + 1);
4296    set_empty_slot_index(*array, kNoEmptySlotsMarker);
4297    array->Set(kFirstIndex, HeapObjectReference::Weak(*value));
4298    array->set_length(kFirstIndex + 1);
4299    if (assigned_index != nullptr) *assigned_index = kFirstIndex;
4300    return array;
4301  }
4302
4303  // If the array has unfilled space at the end, use it.
4304  if (!array->IsFull()) {
4305    array->Set(length, HeapObjectReference::Weak(*value));
4306    array->set_length(length + 1);
4307    if (assigned_index != nullptr) *assigned_index = length;
4308    return array;
4309  }
4310
4311  // If there are empty slots, use one of them.
4312  int empty_slot = Smi::ToInt(empty_slot_index(*array));
4313
4314  if (empty_slot == kNoEmptySlotsMarker) {
4315    // GCs might have cleared some references, rescan the array for empty slots.
4316    PrototypeUsers::ScanForEmptySlots(*array);
4317    empty_slot = Smi::ToInt(empty_slot_index(*array));
4318  }
4319
4320  if (empty_slot != kNoEmptySlotsMarker) {
4321    DCHECK_GE(empty_slot, kFirstIndex);
4322    CHECK_LT(empty_slot, array->length());
4323    int next_empty_slot = array->Get(empty_slot).ToSmi().value();
4324
4325    array->Set(empty_slot, HeapObjectReference::Weak(*value));
4326    if (assigned_index != nullptr) *assigned_index = empty_slot;
4327
4328    set_empty_slot_index(*array, next_empty_slot);
4329    return array;
4330  } else {
4331    DCHECK_EQ(empty_slot, kNoEmptySlotsMarker);
4332  }
4333
4334  // Array full and no empty slots. Grow the array.
4335  array = WeakArrayList::EnsureSpace(isolate, array, length + 1);
4336  array->Set(length, HeapObjectReference::Weak(*value));
4337  array->set_length(length + 1);
4338  if (assigned_index != nullptr) *assigned_index = length;
4339  return array;
4340}
4341
4342// static
4343void PrototypeUsers::ScanForEmptySlots(WeakArrayList array) {
4344  for (int i = kFirstIndex; i < array.length(); i++) {
4345    if (array.Get(i)->IsCleared()) {
4346      PrototypeUsers::MarkSlotEmpty(array, i);
4347    }
4348  }
4349}
4350
4351WeakArrayList PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
4352                                      CompactionCallback callback,
4353                                      AllocationType allocation) {
4354  if (array->length() == 0) {
4355    return *array;
4356  }
4357  int new_length = kFirstIndex + array->CountLiveWeakReferences();
4358  if (new_length == array->length()) {
4359    return *array;
4360  }
4361
4362  Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
4363      heap->isolate(),
4364      handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
4365      new_length, allocation);
4366  // Allocation might have caused GC and turned some of the elements into
4367  // cleared weak heap objects. Count the number of live objects again.
4368  int copy_to = kFirstIndex;
4369  for (int i = kFirstIndex; i < array->length(); i++) {
4370    MaybeObject element = array->Get(i);
4371    HeapObject value;
4372    if (element->GetHeapObjectIfWeak(&value)) {
4373      callback(value, i, copy_to);
4374      new_array->Set(copy_to++, element);
4375    } else {
4376      DCHECK(element->IsCleared() || element->IsSmi());
4377    }
4378  }
4379  new_array->set_length(copy_to);
4380  set_empty_slot_index(*new_array, kNoEmptySlotsMarker);
4381  return *new_array;
4382}
4383
4384Handle<RegExpMatchInfo> RegExpMatchInfo::New(Isolate* isolate,
4385                                             int capture_count) {
4386  Handle<RegExpMatchInfo> match_info = isolate->factory()->NewRegExpMatchInfo();
4387  return ReserveCaptures(isolate, match_info, capture_count);
4388}
4389
4390Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
4391    Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture_count) {
4392  DCHECK_GE(match_info->length(), kLastMatchOverhead);
4393
4394  int capture_register_count =
4395      JSRegExp::RegistersForCaptureCount(capture_count);
4396  const int required_length = kFirstCaptureIndex + capture_register_count;
4397  Handle<RegExpMatchInfo> result = Handle<RegExpMatchInfo>::cast(
4398      EnsureSpaceInFixedArray(isolate, match_info, required_length));
4399  result->SetNumberOfCaptureRegisters(capture_register_count);
4400  return result;
4401}
4402
4403template <typename IsolateT>
4404Handle<DescriptorArray> DescriptorArray::Allocate(IsolateT* isolate,
4405                                                  int nof_descriptors,
4406                                                  int slack,
4407                                                  AllocationType allocation) {
4408  return nof_descriptors + slack == 0
4409             ? isolate->factory()->empty_descriptor_array()
4410             : isolate->factory()->NewDescriptorArray(nof_descriptors, slack,
4411                                                      allocation);
4412}
4413template Handle<DescriptorArray> DescriptorArray::Allocate(
4414    Isolate* isolate, int nof_descriptors, int slack,
4415    AllocationType allocation);
4416template Handle<DescriptorArray> DescriptorArray::Allocate(
4417    LocalIsolate* isolate, int nof_descriptors, int slack,
4418    AllocationType allocation);
4419
4420void DescriptorArray::Initialize(EnumCache empty_enum_cache,
4421                                 HeapObject undefined_value,
4422                                 int nof_descriptors, int slack) {
4423  DCHECK_GE(nof_descriptors, 0);
4424  DCHECK_GE(slack, 0);
4425  DCHECK_LE(nof_descriptors + slack, kMaxNumberOfDescriptors);
4426  set_number_of_all_descriptors(nof_descriptors + slack);
4427  set_number_of_descriptors(nof_descriptors);
4428  set_raw_number_of_marked_descriptors(0);
4429  set_filler16bits(0);
4430  set_enum_cache(empty_enum_cache, SKIP_WRITE_BARRIER);
4431  MemsetTagged(GetDescriptorSlot(0), undefined_value,
4432               number_of_all_descriptors() * kEntrySize);
4433}
4434
4435void DescriptorArray::ClearEnumCache() {
4436  set_enum_cache(GetReadOnlyRoots().empty_enum_cache(), SKIP_WRITE_BARRIER);
4437}
4438
4439void DescriptorArray::Replace(InternalIndex index, Descriptor* descriptor) {
4440  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index.as_int()));
4441  Set(index, descriptor);
4442}
4443
4444// static
4445void DescriptorArray::InitializeOrChangeEnumCache(
4446    Handle<DescriptorArray> descriptors, Isolate* isolate,
4447    Handle<FixedArray> keys, Handle<FixedArray> indices) {
4448  EnumCache enum_cache = descriptors->enum_cache();
4449  if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
4450    enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
4451    descriptors->set_enum_cache(enum_cache);
4452  } else {
4453    enum_cache.set_keys(*keys);
4454    enum_cache.set_indices(*indices);
4455  }
4456}
4457
4458void DescriptorArray::CopyFrom(InternalIndex index, DescriptorArray src) {
4459  PropertyDetails details = src.GetDetails(index);
4460  Set(index, src.GetKey(index), src.GetValue(index), details);
4461}
4462
4463void DescriptorArray::Sort() {
4464  // In-place heap sort.
4465  const int len = number_of_descriptors();
4466  // Reset sorting since the descriptor array might contain invalid pointers.
4467  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
4468  // Bottom-up max-heap construction.
4469  // Index of the last node with children.
4470  int max_parent_index = (len / 2) - 1;
4471  for (int i = max_parent_index; i >= 0; --i) {
4472    int parent_index = i;
4473    const uint32_t parent_hash = GetSortedKey(i).hash();
4474    while (parent_index <= max_parent_index) {
4475      int child_index = 2 * parent_index + 1;
4476      uint32_t child_hash = GetSortedKey(child_index).hash();
4477      if (child_index + 1 < len) {
4478        uint32_t right_child_hash = GetSortedKey(child_index + 1).hash();
4479        if (right_child_hash > child_hash) {
4480          child_index++;
4481          child_hash = right_child_hash;
4482        }
4483      }
4484      if (child_hash <= parent_hash) break;
4485      SwapSortedKeys(parent_index, child_index);
4486      // Now element at child_index could be < its children.
4487      parent_index = child_index;  // parent_hash remains correct.
4488    }
4489  }
4490
4491  // Extract elements and create sorted array.
4492  for (int i = len - 1; i > 0; --i) {
4493    // Put max element at the back of the array.
4494    SwapSortedKeys(0, i);
4495    // Shift down the new top element.
4496    int parent_index = 0;
4497    const uint32_t parent_hash = GetSortedKey(parent_index).hash();
4498    max_parent_index = (i / 2) - 1;
4499    while (parent_index <= max_parent_index) {
4500      int child_index = parent_index * 2 + 1;
4501      uint32_t child_hash = GetSortedKey(child_index).hash();
4502      if (child_index + 1 < i) {
4503        uint32_t right_child_hash = GetSortedKey(child_index + 1).hash();
4504        if (right_child_hash > child_hash) {
4505          child_index++;
4506          child_hash = right_child_hash;
4507        }
4508      }
4509      if (child_hash <= parent_hash) break;
4510      SwapSortedKeys(parent_index, child_index);
4511      parent_index = child_index;
4512    }
4513  }
4514  DCHECK(IsSortedNoDuplicates());
4515}
4516
4517int16_t DescriptorArray::UpdateNumberOfMarkedDescriptors(
4518    unsigned mark_compact_epoch, int16_t new_marked) {
4519  STATIC_ASSERT(kMaxNumberOfDescriptors <=
4520                NumberOfMarkedDescriptors::kMaxNumberOfMarkedDescriptors);
4521  int16_t old_raw_marked = raw_number_of_marked_descriptors();
4522  int16_t old_marked =
4523      NumberOfMarkedDescriptors::decode(mark_compact_epoch, old_raw_marked);
4524  int16_t new_raw_marked =
4525      NumberOfMarkedDescriptors::encode(mark_compact_epoch, new_marked);
4526  while (old_marked < new_marked) {
4527    int16_t actual_raw_marked = CompareAndSwapRawNumberOfMarkedDescriptors(
4528        old_raw_marked, new_raw_marked);
4529    if (actual_raw_marked == old_raw_marked) {
4530      break;
4531    }
4532    old_raw_marked = actual_raw_marked;
4533    old_marked =
4534        NumberOfMarkedDescriptors::decode(mark_compact_epoch, old_raw_marked);
4535  }
4536  return old_marked;
4537}
4538
4539Handle<AccessorPair> AccessorPair::Copy(Isolate* isolate,
4540                                        Handle<AccessorPair> pair) {
4541  Handle<AccessorPair> copy = isolate->factory()->NewAccessorPair();
4542  copy->set_getter(pair->getter());
4543  copy->set_setter(pair->setter());
4544  return copy;
4545}
4546
4547Handle<Object> AccessorPair::GetComponent(Isolate* isolate,
4548                                          Handle<NativeContext> native_context,
4549                                          Handle<AccessorPair> accessor_pair,
4550                                          AccessorComponent component) {
4551  Handle<Object> accessor(accessor_pair->get(component), isolate);
4552  if (accessor->IsFunctionTemplateInfo()) {
4553    auto function = ApiNatives::InstantiateFunction(
4554                        isolate, native_context,
4555                        Handle<FunctionTemplateInfo>::cast(accessor))
4556                        .ToHandleChecked();
4557    accessor_pair->set(component, *function, kReleaseStore);
4558    return function;
4559  }
4560  if (accessor->IsNull(isolate)) {
4561    return isolate->factory()->undefined_value();
4562  }
4563  return accessor;
4564}
4565
4566#ifdef DEBUG
4567bool DescriptorArray::IsEqualTo(DescriptorArray other) {
4568  if (number_of_all_descriptors() != other.number_of_all_descriptors()) {
4569    return false;
4570  }
4571  for (InternalIndex i : InternalIndex::Range(number_of_descriptors())) {
4572    if (GetKey(i) != other.GetKey(i)) return false;
4573    if (GetDetails(i).AsSmi() != other.GetDetails(i).AsSmi()) return false;
4574    if (GetValue(i) != other.GetValue(i)) return false;
4575  }
4576  return true;
4577}
4578#endif
4579
4580// static
4581MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
4582  if (name->IsString()) return Handle<String>::cast(name);
4583  // ES6 section 9.2.11 SetFunctionName, step 4.
4584  Handle<Object> description(Handle<Symbol>::cast(name)->description(),
4585                             isolate);
4586  if (description->IsUndefined(isolate)) {
4587    return isolate->factory()->empty_string();
4588  }
4589  IncrementalStringBuilder builder(isolate);
4590  builder.AppendCharacter('[');
4591  builder.AppendString(Handle<String>::cast(description));
4592  builder.AppendCharacter(']');
4593  return builder.Finish();
4594}
4595
4596// static
4597MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name,
4598                                         Handle<String> prefix) {
4599  Handle<String> name_string;
4600  ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string,
4601                             ToFunctionName(isolate, name), String);
4602  IncrementalStringBuilder builder(isolate);
4603  builder.AppendString(prefix);
4604  builder.AppendCharacter(' ');
4605  builder.AppendString(name_string);
4606  return builder.Finish();
4607}
4608
4609void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
4610  Relocatable* current = isolate->relocatable_top();
4611  while (current != nullptr) {
4612    current->PostGarbageCollection();
4613    current = current->prev_;
4614  }
4615}
4616
4617// Reserve space for statics needing saving and restoring.
4618int Relocatable::ArchiveSpacePerThread() { return sizeof(Relocatable*); }
4619
4620// Archive statics that are thread-local.
4621char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
4622  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
4623  isolate->set_relocatable_top(nullptr);
4624  return to + ArchiveSpacePerThread();
4625}
4626
4627// Restore statics that are thread-local.
4628char* Relocatable::RestoreState(Isolate* isolate, char* from) {
4629  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
4630  return from + ArchiveSpacePerThread();
4631}
4632
4633char* Relocatable::Iterate(RootVisitor* v, char* thread_storage) {
4634  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
4635  Iterate(v, top);
4636  return thread_storage + ArchiveSpacePerThread();
4637}
4638
4639void Relocatable::Iterate(Isolate* isolate, RootVisitor* v) {
4640  Iterate(v, isolate->relocatable_top());
4641}
4642
4643void Relocatable::Iterate(RootVisitor* v, Relocatable* top) {
4644  Relocatable* current = top;
4645  while (current != nullptr) {
4646    current->IterateInstance(v);
4647    current = current->prev_;
4648  }
4649}
4650
4651namespace {
4652
4653template <typename sinkchar>
4654void WriteFixedArrayToFlat(FixedArray fixed_array, int length, String separator,
4655                           sinkchar* sink, int sink_length) {
4656  DisallowGarbageCollection no_gc;
4657  CHECK_GT(length, 0);
4658  CHECK_LE(length, fixed_array.length());
4659#ifdef DEBUG
4660  sinkchar* sink_end = sink + sink_length;
4661#endif
4662
4663  const int separator_length = separator.length();
4664  const bool use_one_byte_separator_fast_path =
4665      separator_length == 1 && sizeof(sinkchar) == 1 &&
4666      StringShape(separator).IsSequentialOneByte();
4667  uint8_t separator_one_char;
4668  if (use_one_byte_separator_fast_path) {
4669    CHECK(StringShape(separator).IsSequentialOneByte());
4670    CHECK_EQ(separator.length(), 1);
4671    separator_one_char = SeqOneByteString::cast(separator).GetChars(no_gc)[0];
4672  }
4673
4674  uint32_t num_separators = 0;
4675  for (int i = 0; i < length; i++) {
4676    Object element = fixed_array.get(i);
4677    const bool element_is_separator_sequence = element.IsSmi();
4678
4679    // If element is a Smi, it represents the number of separators to write.
4680    if (V8_UNLIKELY(element_is_separator_sequence)) {
4681      CHECK(element.ToUint32(&num_separators));
4682      // Verify that Smis (number of separators) only occur when necessary:
4683      //   1) at the beginning
4684      //   2) at the end
4685      //   3) when the number of separators > 1
4686      //     - It is assumed that consecutive Strings will have one separator,
4687      //       so there is no need for a Smi.
4688      DCHECK(i == 0 || i == length - 1 || num_separators > 1);
4689    }
4690
4691    // Write separator(s) if necessary.
4692    if (num_separators > 0 && separator_length > 0) {
4693      // TODO(pwong): Consider doubling strategy employed by runtime-strings.cc
4694      //              WriteRepeatToFlat().
4695      // Fast path for single character, single byte separators.
4696      if (use_one_byte_separator_fast_path) {
4697        DCHECK_LE(sink + num_separators, sink_end);
4698        memset(sink, separator_one_char, num_separators);
4699        DCHECK_EQ(separator_length, 1);
4700        sink += num_separators;
4701      } else {
4702        for (uint32_t j = 0; j < num_separators; j++) {
4703          DCHECK_LE(sink + separator_length, sink_end);
4704          String::WriteToFlat(separator, sink, 0, separator_length);
4705          sink += separator_length;
4706        }
4707      }
4708    }
4709
4710    if (V8_UNLIKELY(element_is_separator_sequence)) {
4711      num_separators = 0;
4712    } else {
4713      DCHECK(element.IsString());
4714      String string = String::cast(element);
4715      const int string_length = string.length();
4716
4717      DCHECK(string_length == 0 || sink < sink_end);
4718      String::WriteToFlat(string, sink, 0, string_length);
4719      sink += string_length;
4720
4721      // Next string element, needs at least one separator preceding it.
4722      num_separators = 1;
4723    }
4724  }
4725
4726  // Verify we have written to the end of the sink.
4727  DCHECK_EQ(sink, sink_end);
4728}
4729
4730}  // namespace
4731
4732// static
4733Address JSArray::ArrayJoinConcatToSequentialString(Isolate* isolate,
4734                                                   Address raw_fixed_array,
4735                                                   intptr_t length,
4736                                                   Address raw_separator,
4737                                                   Address raw_dest) {
4738  DisallowGarbageCollection no_gc;
4739  DisallowJavascriptExecution no_js(isolate);
4740  FixedArray fixed_array = FixedArray::cast(Object(raw_fixed_array));
4741  String separator = String::cast(Object(raw_separator));
4742  String dest = String::cast(Object(raw_dest));
4743  DCHECK(fixed_array.IsFixedArray());
4744  DCHECK(StringShape(dest).IsSequentialOneByte() ||
4745         StringShape(dest).IsSequentialTwoByte());
4746
4747  if (StringShape(dest).IsSequentialOneByte()) {
4748    WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
4749                          SeqOneByteString::cast(dest).GetChars(no_gc),
4750                          dest.length());
4751  } else {
4752    DCHECK(StringShape(dest).IsSequentialTwoByte());
4753    WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
4754                          SeqTwoByteString::cast(dest).GetChars(no_gc),
4755                          dest.length());
4756  }
4757  return dest.ptr();
4758}
4759
4760uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
4761  // For array indexes mix the length into the hash as an array index could
4762  // be zero.
4763  DCHECK_GT(length, 0);
4764  DCHECK_LE(length, String::kMaxArrayIndexSize);
4765  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
4766         (1 << String::kArrayIndexValueBits));
4767
4768  value <<= String::ArrayIndexValueBits::kShift;
4769  value |= length << String::ArrayIndexLengthBits::kShift;
4770
4771  DCHECK(String::IsIntegerIndex(value));
4772  DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
4773            Name::ContainsCachedArrayIndex(value));
4774  return value;
4775}
4776
4777STATIC_ASSERT_FIELD_OFFSETS_EQUAL(HeapNumber::kValueOffset,
4778                                  Oddball::kToNumberRawOffset);
4779
4780void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
4781                         const char* to_string, Handle<Object> to_number,
4782                         const char* type_of, byte kind) {
4783  Handle<String> internalized_to_string =
4784      isolate->factory()->InternalizeUtf8String(to_string);
4785  Handle<String> internalized_type_of =
4786      isolate->factory()->InternalizeUtf8String(type_of);
4787  if (to_number->IsHeapNumber()) {
4788    oddball->set_to_number_raw_as_bits(
4789        Handle<HeapNumber>::cast(to_number)->value_as_bits(kRelaxedLoad));
4790  } else {
4791    oddball->set_to_number_raw(to_number->Number());
4792  }
4793  oddball->set_to_number(*to_number);
4794  oddball->set_to_string(*internalized_to_string);
4795  oddball->set_type_of(*internalized_type_of);
4796  oddball->set_kind(kind);
4797}
4798
4799// static
4800int Script::GetEvalPosition(Isolate* isolate, Handle<Script> script) {
4801  DCHECK(script->compilation_type() == Script::COMPILATION_TYPE_EVAL);
4802  int position = script->eval_from_position();
4803  if (position < 0) {
4804    // Due to laziness, the position may not have been translated from code
4805    // offset yet, which would be encoded as negative integer. In that case,
4806    // translate and set the position.
4807    if (!script->has_eval_from_shared()) {
4808      position = 0;
4809    } else {
4810      Handle<SharedFunctionInfo> shared =
4811          handle(script->eval_from_shared(), isolate);
4812      SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, shared);
4813      position = shared->abstract_code(isolate).SourcePosition(-position);
4814    }
4815    DCHECK_GE(position, 0);
4816    script->set_eval_from_position(position);
4817  }
4818  return position;
4819}
4820
4821template <typename IsolateT>
4822// static
4823void Script::InitLineEnds(IsolateT* isolate, Handle<Script> script) {
4824  if (!script->line_ends().IsUndefined(isolate)) return;
4825#if V8_ENABLE_WEBASSEMBLY
4826  DCHECK(script->type() != Script::TYPE_WASM ||
4827         script->source_mapping_url().IsString());
4828#endif  // V8_ENABLE_WEBASSEMBLY
4829
4830  Object src_obj = script->source();
4831  if (!src_obj.IsString()) {
4832    DCHECK(src_obj.IsUndefined(isolate));
4833    script->set_line_ends(ReadOnlyRoots(isolate).empty_fixed_array());
4834  } else {
4835    DCHECK(src_obj.IsString());
4836    Handle<String> src(String::cast(src_obj), isolate);
4837    Handle<FixedArray> array = String::CalculateLineEnds(isolate, src, true);
4838    script->set_line_ends(*array);
4839  }
4840
4841  DCHECK(script->line_ends().IsFixedArray());
4842}
4843
4844template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Script::InitLineEnds(
4845    Isolate* isolate, Handle<Script> script);
4846template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Script::InitLineEnds(
4847    LocalIsolate* isolate, Handle<Script> script);
4848
4849bool Script::GetPositionInfo(Handle<Script> script, int position,
4850                             PositionInfo* info, OffsetFlag offset_flag) {
4851  bool init_line_ends = true;
4852#if V8_ENABLE_WEBASSEMBLY
4853  // For wasm, we do not create an artificial line_ends array, but do the
4854  // translation directly.
4855  init_line_ends = script->type() != Script::TYPE_WASM;
4856#endif  // V8_ENABLE_WEBASSEMBLY
4857  if (init_line_ends) InitLineEnds(script->GetIsolate(), script);
4858  return script->GetPositionInfo(position, info, offset_flag);
4859}
4860
4861bool Script::IsSubjectToDebugging() const {
4862  switch (type()) {
4863    case TYPE_NORMAL:
4864#if V8_ENABLE_WEBASSEMBLY
4865    case TYPE_WASM:
4866#endif  // V8_ENABLE_WEBASSEMBLY
4867      return true;
4868  }
4869  return false;
4870}
4871
4872bool Script::IsUserJavaScript() const { return type() == Script::TYPE_NORMAL; }
4873
4874#if V8_ENABLE_WEBASSEMBLY
4875bool Script::ContainsAsmModule() {
4876  DisallowGarbageCollection no_gc;
4877  SharedFunctionInfo::ScriptIterator iter(this->GetIsolate(), *this);
4878  for (SharedFunctionInfo info = iter.Next(); !info.is_null();
4879       info = iter.Next()) {
4880    if (info.HasAsmWasmData()) return true;
4881  }
4882  return false;
4883}
4884#endif  // V8_ENABLE_WEBASSEMBLY
4885
4886namespace {
4887
4888template <typename Char>
4889bool GetPositionInfoSlowImpl(const base::Vector<Char>& source, int position,
4890                             Script::PositionInfo* info) {
4891  if (position < 0) {
4892    position = 0;
4893  }
4894  int line = 0;
4895  const auto begin = std::cbegin(source);
4896  const auto end = std::cend(source);
4897  for (auto line_begin = begin; line_begin < end;) {
4898    const auto line_end = std::find(line_begin, end, '\n');
4899    if (position <= (line_end - begin)) {
4900      info->line = line;
4901      info->column = static_cast<int>((begin + position) - line_begin);
4902      info->line_start = static_cast<int>(line_begin - begin);
4903      info->line_end = static_cast<int>(line_end - begin);
4904      return true;
4905    }
4906    ++line;
4907    line_begin = line_end + 1;
4908  }
4909  return false;
4910}
4911bool GetPositionInfoSlow(const Script script, int position,
4912                         const DisallowGarbageCollection& no_gc,
4913                         Script::PositionInfo* info) {
4914  if (!script.source().IsString()) {
4915    return false;
4916  }
4917  auto source = String::cast(script.source());
4918  const auto flat = source.GetFlatContent(no_gc);
4919  return flat.IsOneByte()
4920             ? GetPositionInfoSlowImpl(flat.ToOneByteVector(), position, info)
4921             : GetPositionInfoSlowImpl(flat.ToUC16Vector(), position, info);
4922}
4923
4924}  // namespace
4925
4926bool Script::GetPositionInfo(int position, PositionInfo* info,
4927                             OffsetFlag offset_flag) const {
4928  DisallowGarbageCollection no_gc;
4929
4930#if V8_ENABLE_WEBASSEMBLY
4931  // For wasm, we use the byte offset as the column.
4932  if (type() == Script::TYPE_WASM) {
4933    DCHECK_LE(0, position);
4934    wasm::NativeModule* native_module = wasm_native_module();
4935    const wasm::WasmModule* module = native_module->module();
4936    if (module->functions.size() == 0) return false;
4937    info->line = 0;
4938    info->column = position;
4939    info->line_start = module->functions[0].code.offset();
4940    info->line_end = module->functions.back().code.end_offset();
4941    return true;
4942  }
4943#endif  // V8_ENABLE_WEBASSEMBLY
4944
4945  if (line_ends().IsUndefined()) {
4946    // Slow mode: we do not have line_ends. We have to iterate through source.
4947    if (!GetPositionInfoSlow(*this, position, no_gc, info)) {
4948      return false;
4949    }
4950  } else {
4951    DCHECK(line_ends().IsFixedArray());
4952    FixedArray ends = FixedArray::cast(line_ends());
4953
4954    const int ends_len = ends.length();
4955    if (ends_len == 0) return false;
4956
4957    // Return early on invalid positions. Negative positions behave as if 0 was
4958    // passed, and positions beyond the end of the script return as failure.
4959    if (position < 0) {
4960      position = 0;
4961    } else if (position > Smi::ToInt(ends.get(ends_len - 1))) {
4962      return false;
4963    }
4964
4965    // Determine line number by doing a binary search on the line ends array.
4966    if (Smi::ToInt(ends.get(0)) >= position) {
4967      info->line = 0;
4968      info->line_start = 0;
4969      info->column = position;
4970    } else {
4971      int left = 0;
4972      int right = ends_len - 1;
4973
4974      while (right > 0) {
4975        DCHECK_LE(left, right);
4976        const int mid = (left + right) / 2;
4977        if (position > Smi::ToInt(ends.get(mid))) {
4978          left = mid + 1;
4979        } else if (position <= Smi::ToInt(ends.get(mid - 1))) {
4980          right = mid - 1;
4981        } else {
4982          info->line = mid;
4983          break;
4984        }
4985      }
4986      DCHECK(Smi::ToInt(ends.get(info->line)) >= position &&
4987             Smi::ToInt(ends.get(info->line - 1)) < position);
4988      info->line_start = Smi::ToInt(ends.get(info->line - 1)) + 1;
4989      info->column = position - info->line_start;
4990    }
4991
4992    // Line end is position of the linebreak character.
4993    info->line_end = Smi::ToInt(ends.get(info->line));
4994    if (info->line_end > 0) {
4995      DCHECK(source().IsString());
4996      String src = String::cast(source());
4997      if (src.length() >= info->line_end &&
4998          src.Get(info->line_end - 1) == '\r') {
4999        info->line_end--;
5000      }
5001    }
5002  }
5003
5004  // Add offsets if requested.
5005  if (offset_flag == WITH_OFFSET) {
5006    if (info->line == 0) {
5007      info->column += column_offset();
5008    }
5009    info->line += line_offset();
5010  }
5011
5012  return true;
5013}
5014
5015int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
5016  PositionInfo info;
5017  GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
5018  return info.column;
5019}
5020
5021int Script::GetColumnNumber(int code_pos) const {
5022  PositionInfo info;
5023  GetPositionInfo(code_pos, &info, WITH_OFFSET);
5024  return info.column;
5025}
5026
5027int Script::GetLineNumber(Handle<Script> script, int code_pos) {
5028  PositionInfo info;
5029  GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
5030  return info.line;
5031}
5032
5033int Script::GetLineNumber(int code_pos) const {
5034  PositionInfo info;
5035  GetPositionInfo(code_pos, &info, WITH_OFFSET);
5036  return info.line;
5037}
5038
5039Object Script::GetNameOrSourceURL() {
5040  // Keep in sync with ScriptNameOrSourceURL in messages.js.
5041  if (!source_url().IsUndefined()) return source_url();
5042  return name();
5043}
5044
5045template <typename IsolateT>
5046MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
5047    Handle<Script> script, IsolateT* isolate,
5048    FunctionLiteral* function_literal) {
5049  int function_literal_id = function_literal->function_literal_id();
5050  if V8_UNLIKELY (script->type() == Script::TYPE_WEB_SNAPSHOT &&
5051                  function_literal_id >= script->shared_function_info_count()) {
5052    return FindWebSnapshotSharedFunctionInfo(script, isolate, function_literal);
5053  }
5054
5055  CHECK_NE(function_literal_id, kFunctionLiteralIdInvalid);
5056  // If this check fails, the problem is most probably the function id
5057  // renumbering done by AstFunctionLiteralIdReindexer; in particular, that
5058  // AstTraversalVisitor doesn't recurse properly in the construct which
5059  // triggers the mismatch.
5060  CHECK_LT(function_literal_id, script->shared_function_info_count());
5061  MaybeObject shared = script->shared_function_infos().Get(function_literal_id);
5062  HeapObject heap_object;
5063  if (!shared->GetHeapObject(&heap_object) ||
5064      heap_object.IsUndefined(isolate)) {
5065    return MaybeHandle<SharedFunctionInfo>();
5066  }
5067  return handle(SharedFunctionInfo::cast(heap_object), isolate);
5068}
5069template MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
5070    Handle<Script> script, Isolate* isolate, FunctionLiteral* function_literal);
5071template MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
5072    Handle<Script> script, LocalIsolate* isolate,
5073    FunctionLiteral* function_literal);
5074
5075MaybeHandle<SharedFunctionInfo> Script::FindWebSnapshotSharedFunctionInfo(
5076    Handle<Script> script, Isolate* isolate,
5077    FunctionLiteral* function_literal) {
5078  // We might be able to de-dupe the SFI against a SFI that was
5079  // created when deserializing the snapshot (or when calling a function which
5080  // was included in the snapshot). In that case, we can find it based on the
5081  // start position in shared_function_info_table.
5082  Handle<ObjectHashTable> shared_function_info_table = handle(
5083      ObjectHashTable::cast(script->shared_function_info_table()), isolate);
5084  {
5085    DisallowHeapAllocation no_gc;
5086    Object index_object = shared_function_info_table->Lookup(
5087        handle(Smi::FromInt(function_literal->start_position()), isolate));
5088    if (!index_object.IsTheHole()) {
5089      int index = Smi::cast(index_object).value();
5090      DCHECK_LT(index, script->shared_function_info_count());
5091      MaybeObject maybe_shared = script->shared_function_infos().Get(index);
5092      HeapObject heap_object;
5093      if (!maybe_shared->GetHeapObject(&heap_object)) {
5094        // We found the correct location but it's not filled in (e.g., the weak
5095        // pointer to the SharedFunctionInfo has been cleared). Record the
5096        // location in the FunctionLiteral, so that it will be refilled later.
5097        // SharedFunctionInfo::SetScript will write the SharedFunctionInfo in
5098        // the shared_function_infos.
5099        function_literal->set_function_literal_id(index);
5100        return MaybeHandle<SharedFunctionInfo>();
5101      }
5102      SharedFunctionInfo shared = SharedFunctionInfo::cast(heap_object);
5103      DCHECK_EQ(shared.StartPosition(), function_literal->start_position());
5104      DCHECK_EQ(shared.EndPosition(), function_literal->end_position());
5105      return handle(shared, isolate);
5106    }
5107  }
5108
5109  // It's possible that FunctionLiterals which were processed before this one
5110  // were deduplicated against existing ones. Decrease function_literal_id to
5111  // avoid holes in shared_function_infos.
5112  int old_length = script->shared_function_info_count();
5113  int function_literal_id = old_length;
5114  function_literal->set_function_literal_id(function_literal_id);
5115
5116  // Also add to shared_function_info_table.
5117  shared_function_info_table = ObjectHashTable::Put(
5118      shared_function_info_table,
5119      handle(Smi::FromInt(function_literal->start_position()), isolate),
5120      handle(Smi::FromInt(function_literal_id), isolate));
5121  script->set_shared_function_info_table(*shared_function_info_table);
5122
5123  // Grow shared_function_infos if needed (we don't know the correct amount of
5124  // space needed upfront).
5125  int new_length = old_length + 1;
5126  Handle<WeakFixedArray> old_infos =
5127      handle(script->shared_function_infos(), isolate);
5128  if (new_length > old_infos->length()) {
5129    int capacity = WeakArrayList::CapacityForLength(new_length);
5130    Handle<WeakFixedArray> new_infos(
5131        isolate->factory()->NewWeakFixedArray(capacity, AllocationType::kOld));
5132    new_infos->CopyElements(isolate, 0, *old_infos, 0, old_length,
5133                            WriteBarrierMode::UPDATE_WRITE_BARRIER);
5134    script->set_shared_function_infos(*new_infos);
5135  }
5136  return MaybeHandle<SharedFunctionInfo>();
5137}
5138
5139MaybeHandle<SharedFunctionInfo> Script::FindWebSnapshotSharedFunctionInfo(
5140    Handle<Script> script, LocalIsolate* isolate,
5141    FunctionLiteral* function_literal) {
5142  // Off-thread serialization of web snapshots is not implemented.
5143  UNREACHABLE();
5144}
5145
5146Script::Iterator::Iterator(Isolate* isolate)
5147    : iterator_(isolate->heap()->script_list()) {}
5148
5149Script Script::Iterator::Next() {
5150  Object o = iterator_.Next();
5151  if (o != Object()) {
5152    return Script::cast(o);
5153  }
5154  return Script();
5155}
5156
5157// static
5158void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
5159  DCHECK_GE(capacity, 0);
5160  array->GetIsolate()->factory()->NewJSArrayStorage(
5161      array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
5162}
5163
5164Maybe<bool> JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
5165  if (array->SetLengthWouldNormalize(new_length)) {
5166    JSObject::NormalizeElements(array);
5167  }
5168  return array->GetElementsAccessor()->SetLength(array, new_length);
5169}
5170
5171// ES6: 9.5.2 [[SetPrototypeOf]] (V)
5172// static
5173Maybe<bool> JSProxy::SetPrototype(Isolate* isolate, Handle<JSProxy> proxy,
5174                                  Handle<Object> value, bool from_javascript,
5175                                  ShouldThrow should_throw) {
5176  STACK_CHECK(isolate, Nothing<bool>());
5177  Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
5178  // 1. Assert: Either Type(V) is Object or Type(V) is Null.
5179  DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
5180  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
5181  Handle<Object> handler(proxy->handler(), isolate);
5182  // 3. If handler is null, throw a TypeError exception.
5183  // 4. Assert: Type(handler) is Object.
5184  if (proxy->IsRevoked()) {
5185    isolate->Throw(*isolate->factory()->NewTypeError(
5186        MessageTemplate::kProxyRevoked, trap_name));
5187    return Nothing<bool>();
5188  }
5189  // 5. Let target be the value of the [[ProxyTarget]] internal slot.
5190  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
5191  // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
5192  Handle<Object> trap;
5193  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5194      isolate, trap,
5195      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
5196      Nothing<bool>());
5197  // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
5198  if (trap->IsUndefined(isolate)) {
5199    return JSReceiver::SetPrototype(isolate, target, value, from_javascript,
5200                                    should_throw);
5201  }
5202  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)).
5203  Handle<Object> argv[] = {target, value};
5204  Handle<Object> trap_result;
5205  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5206      isolate, trap_result,
5207      Execution::Call(isolate, trap, handler, arraysize(argv), argv),
5208      Nothing<bool>());
5209  bool bool_trap_result = trap_result->BooleanValue(isolate);
5210  // 9. If booleanTrapResult is false, return false.
5211  if (!bool_trap_result) {
5212    RETURN_FAILURE(
5213        isolate, should_throw,
5214        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
5215  }
5216  // 10. Let extensibleTarget be ? IsExtensible(target).
5217  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
5218  if (is_extensible.IsNothing()) return Nothing<bool>();
5219  // 11. If extensibleTarget is true, return true.
5220  if (is_extensible.FromJust()) {
5221    if (bool_trap_result) return Just(true);
5222    RETURN_FAILURE(
5223        isolate, should_throw,
5224        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
5225  }
5226  // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
5227  Handle<Object> target_proto;
5228  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
5229                                   JSReceiver::GetPrototype(isolate, target),
5230                                   Nothing<bool>());
5231  // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
5232  if (bool_trap_result && !value->SameValue(*target_proto)) {
5233    isolate->Throw(*isolate->factory()->NewTypeError(
5234        MessageTemplate::kProxySetPrototypeOfNonExtensible));
5235    return Nothing<bool>();
5236  }
5237  // 14. Return true.
5238  return Just(true);
5239}
5240
5241bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
5242  if (!HasFastElements()) return false;
5243  uint32_t capacity = static_cast<uint32_t>(elements().length());
5244  uint32_t new_capacity;
5245  return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
5246         ShouldConvertToSlowElements(*this, capacity, new_length - 1,
5247                                     &new_capacity);
5248}
5249
5250const double AllocationSite::kPretenureRatio = 0.85;
5251
5252void AllocationSite::ResetPretenureDecision() {
5253  set_pretenure_decision(kUndecided);
5254  set_memento_found_count(0);
5255  set_memento_create_count(0);
5256}
5257
5258AllocationType AllocationSite::GetAllocationType() const {
5259  PretenureDecision mode = pretenure_decision();
5260  // Zombie objects "decide" to be untenured.
5261  return mode == kTenure ? AllocationType::kOld : AllocationType::kYoung;
5262}
5263
5264bool AllocationSite::IsNested() {
5265  DCHECK(FLAG_trace_track_allocation_sites);
5266  Object current = boilerplate().GetHeap()->allocation_sites_list();
5267  while (current.IsAllocationSite()) {
5268    AllocationSite current_site = AllocationSite::cast(current);
5269    if (current_site.nested_site() == *this) {
5270      return true;
5271    }
5272    current = current_site.weak_next();
5273  }
5274  return false;
5275}
5276
5277bool AllocationSite::ShouldTrack(ElementsKind from, ElementsKind to) {
5278  if (!V8_ALLOCATION_SITE_TRACKING_BOOL) return false;
5279  return IsMoreGeneralElementsKindTransition(from, to);
5280}
5281
5282const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
5283  switch (decision) {
5284    case kUndecided:
5285      return "undecided";
5286    case kDontTenure:
5287      return "don't tenure";
5288    case kMaybeTenure:
5289      return "maybe tenure";
5290    case kTenure:
5291      return "tenure";
5292    case kZombie:
5293      return "zombie";
5294    default:
5295      UNREACHABLE();
5296  }
5297}
5298
5299// static
5300bool JSArray::MayHaveReadOnlyLength(Map js_array_map) {
5301  DCHECK(js_array_map.IsJSArrayMap());
5302  if (js_array_map.is_dictionary_map()) return true;
5303
5304  // Fast path: "length" is the first fast property of arrays with non
5305  // dictionary properties. Since it's not configurable, it's guaranteed to be
5306  // the first in the descriptor array.
5307  InternalIndex first(0);
5308  DCHECK(js_array_map.instance_descriptors().GetKey(first) ==
5309         js_array_map.GetReadOnlyRoots().length_string());
5310  return js_array_map.instance_descriptors().GetDetails(first).IsReadOnly();
5311}
5312
5313bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
5314  Map map = array->map();
5315
5316  // If map guarantees that there can't be a read-only length, we are done.
5317  if (!MayHaveReadOnlyLength(map)) return false;
5318
5319  // Look at the object.
5320  Isolate* isolate = array->GetIsolate();
5321  LookupIterator it(isolate, array, isolate->factory()->length_string(), array,
5322                    LookupIterator::OWN_SKIP_INTERCEPTOR);
5323  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
5324  return it.IsReadOnly();
5325}
5326
5327bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index) {
5328  uint32_t length = 0;
5329  CHECK(array->length().ToArrayLength(&length));
5330  if (length <= index) return HasReadOnlyLength(array);
5331  return false;
5332}
5333
5334int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
5335  return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
5336          ElementsKindToShiftSize(kind));
5337}
5338
5339bool FixedArrayBase::IsCowArray() const {
5340  return map() == GetReadOnlyRoots().fixed_cow_array_map();
5341}
5342
5343const char* Symbol::PrivateSymbolToName() const {
5344  ReadOnlyRoots roots = GetReadOnlyRoots();
5345#define SYMBOL_CHECK_AND_PRINT(_, name) \
5346  if (*this == roots.name()) return #name;
5347  PRIVATE_SYMBOL_LIST_GENERATOR(SYMBOL_CHECK_AND_PRINT, /* not used */)
5348#undef SYMBOL_CHECK_AND_PRINT
5349  return "UNKNOWN";
5350}
5351
5352void Symbol::SymbolShortPrint(std::ostream& os) {
5353  os << "<Symbol:";
5354  if (!description().IsUndefined()) {
5355    os << " ";
5356    String description_as_string = String::cast(description());
5357    description_as_string.PrintUC16(os, 0, description_as_string.length());
5358  } else {
5359    os << " (" << PrivateSymbolToName() << ")";
5360  }
5361  os << ">";
5362}
5363
5364v8::Promise::PromiseState JSPromise::status() const {
5365  int value = flags() & StatusBits::kMask;
5366  DCHECK(value == 0 || value == 1 || value == 2);
5367  return static_cast<v8::Promise::PromiseState>(value);
5368}
5369
5370void JSPromise::set_status(Promise::PromiseState status) {
5371  int value = flags() & ~StatusBits::kMask;
5372  set_flags(value | status);
5373}
5374
5375// static
5376const char* JSPromise::Status(v8::Promise::PromiseState status) {
5377  switch (status) {
5378    case v8::Promise::kFulfilled:
5379      return "fulfilled";
5380    case v8::Promise::kPending:
5381      return "pending";
5382    case v8::Promise::kRejected:
5383      return "rejected";
5384  }
5385  UNREACHABLE();
5386}
5387
5388int JSPromise::async_task_id() const {
5389  return AsyncTaskIdBits::decode(flags());
5390}
5391
5392void JSPromise::set_async_task_id(int id) {
5393  set_flags(AsyncTaskIdBits::update(flags(), id));
5394}
5395
5396// static
5397Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
5398                                  Handle<Object> value) {
5399  Isolate* const isolate = promise->GetIsolate();
5400
5401#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
5402  if (isolate->HasContextPromiseHooks()) {
5403    isolate->raw_native_context().RunPromiseHook(
5404        PromiseHookType::kResolve, promise,
5405        isolate->factory()->undefined_value());
5406  }
5407#endif
5408
5409  // 1. Assert: The value of promise.[[PromiseState]] is "pending".
5410  CHECK_EQ(Promise::kPending, promise->status());
5411
5412  // 2. Let reactions be promise.[[PromiseFulfillReactions]].
5413  Handle<Object> reactions(promise->reactions(), isolate);
5414
5415  // 3. Set promise.[[PromiseResult]] to value.
5416  // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
5417  // 5. Set promise.[[PromiseRejectReactions]] to undefined.
5418  promise->set_reactions_or_result(*value);
5419
5420  // 6. Set promise.[[PromiseState]] to "fulfilled".
5421  promise->set_status(Promise::kFulfilled);
5422
5423  // 7. Return TriggerPromiseReactions(reactions, value).
5424  return TriggerPromiseReactions(isolate, reactions, value,
5425                                 PromiseReaction::kFulfill);
5426}
5427
5428static void MoveMessageToPromise(Isolate* isolate, Handle<JSPromise> promise) {
5429  if (!isolate->has_pending_message()) return;
5430
5431  Handle<Object> message = handle(isolate->pending_message(), isolate);
5432  Handle<Symbol> key = isolate->factory()->promise_debug_message_symbol();
5433  Object::SetProperty(isolate, promise, key, message, StoreOrigin::kMaybeKeyed,
5434                      Just(ShouldThrow::kThrowOnError))
5435      .Assert();
5436
5437  // The message object for a rejected promise was only stored for this purpose.
5438  // Clear it, otherwise we might leak memory.
5439  isolate->clear_pending_message();
5440}
5441
5442// static
5443Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
5444                                 Handle<Object> reason, bool debug_event) {
5445  Isolate* const isolate = promise->GetIsolate();
5446  DCHECK(
5447      !reinterpret_cast<v8::Isolate*>(isolate)->GetCurrentContext().IsEmpty());
5448
5449  if (isolate->debug()->is_active()) MoveMessageToPromise(isolate, promise);
5450
5451  if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
5452  isolate->RunAllPromiseHooks(PromiseHookType::kResolve, promise,
5453                              isolate->factory()->undefined_value());
5454
5455  // 1. Assert: The value of promise.[[PromiseState]] is "pending".
5456  CHECK_EQ(Promise::kPending, promise->status());
5457
5458  // 2. Let reactions be promise.[[PromiseRejectReactions]].
5459  Handle<Object> reactions(promise->reactions(), isolate);
5460
5461  // 3. Set promise.[[PromiseResult]] to reason.
5462  // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
5463  // 5. Set promise.[[PromiseRejectReactions]] to undefined.
5464  promise->set_reactions_or_result(*reason);
5465
5466  // 6. Set promise.[[PromiseState]] to "rejected".
5467  promise->set_status(Promise::kRejected);
5468
5469  // 7. If promise.[[PromiseIsHandled]] is false, perform
5470  //    HostPromiseRejectionTracker(promise, "reject").
5471  if (!promise->has_handler()) {
5472    isolate->ReportPromiseReject(promise, reason, kPromiseRejectWithNoHandler);
5473  }
5474
5475  // 8. Return TriggerPromiseReactions(reactions, reason).
5476  return TriggerPromiseReactions(isolate, reactions, reason,
5477                                 PromiseReaction::kReject);
5478}
5479
5480// https://tc39.es/ecma262/#sec-promise-resolve-functions
5481// static
5482MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
5483                                       Handle<Object> resolution) {
5484  Isolate* const isolate = promise->GetIsolate();
5485  DCHECK(
5486      !reinterpret_cast<v8::Isolate*>(isolate)->GetCurrentContext().IsEmpty());
5487
5488  isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
5489                          isolate->factory()->undefined_value());
5490
5491  // 7. If SameValue(resolution, promise) is true, then
5492  if (promise.is_identical_to(resolution)) {
5493    // a. Let selfResolutionError be a newly created TypeError object.
5494    Handle<Object> self_resolution_error = isolate->factory()->NewTypeError(
5495        MessageTemplate::kPromiseCyclic, resolution);
5496    // b. Return RejectPromise(promise, selfResolutionError).
5497    return Reject(promise, self_resolution_error);
5498  }
5499
5500  // 8. If Type(resolution) is not Object, then
5501  if (!resolution->IsJSReceiver()) {
5502    // a. Return FulfillPromise(promise, resolution).
5503    return Fulfill(promise, resolution);
5504  }
5505
5506  // 9. Let then be Get(resolution, "then").
5507  MaybeHandle<Object> then;
5508  Handle<JSReceiver> receiver(Handle<JSReceiver>::cast(resolution));
5509
5510  // Make sure a lookup of "then" on any JSPromise whose [[Prototype]] is the
5511  // initial %PromisePrototype% yields the initial method. In addition this
5512  // protector also guards the negative lookup of "then" on the intrinsic
5513  // %ObjectPrototype%, meaning that such lookups are guaranteed to yield
5514  // undefined without triggering any side-effects.
5515  if (receiver->IsJSPromise() &&
5516      isolate->IsInAnyContext(receiver->map().prototype(),
5517                              Context::PROMISE_PROTOTYPE_INDEX) &&
5518      Protectors::IsPromiseThenLookupChainIntact(isolate)) {
5519    // We can skip the "then" lookup on {resolution} if its [[Prototype]]
5520    // is the (initial) Promise.prototype and the Promise#then protector
5521    // is intact, as that guards the lookup path for the "then" property
5522    // on JSPromise instances which have the (initial) %PromisePrototype%.
5523    then = isolate->promise_then();
5524  } else {
5525    then = JSReceiver::GetProperty(isolate, receiver,
5526                                   isolate->factory()->then_string());
5527  }
5528
5529  // 10. If then is an abrupt completion, then
5530  Handle<Object> then_action;
5531  if (!then.ToHandle(&then_action)) {
5532    // The "then" lookup can cause termination.
5533    if (!isolate->is_catchable_by_javascript(isolate->pending_exception())) {
5534      return kNullMaybeHandle;
5535    }
5536
5537    // a. Return RejectPromise(promise, then.[[Value]]).
5538    Handle<Object> reason(isolate->pending_exception(), isolate);
5539    isolate->clear_pending_exception();
5540    return Reject(promise, reason, false);
5541  }
5542
5543  // 11. Let thenAction be then.[[Value]].
5544  // 12. If IsCallable(thenAction) is false, then
5545  if (!then_action->IsCallable()) {
5546    // a. Return FulfillPromise(promise, resolution).
5547    return Fulfill(promise, resolution);
5548  }
5549
5550  // 13. Let job be NewPromiseResolveThenableJob(promise, resolution,
5551  //                                             thenAction).
5552  Handle<NativeContext> then_context;
5553  if (!JSReceiver::GetContextForMicrotask(Handle<JSReceiver>::cast(then_action))
5554           .ToHandle(&then_context)) {
5555    then_context = isolate->native_context();
5556  }
5557
5558  Handle<PromiseResolveThenableJobTask> task =
5559      isolate->factory()->NewPromiseResolveThenableJobTask(
5560          promise, Handle<JSReceiver>::cast(resolution),
5561          Handle<JSReceiver>::cast(then_action), then_context);
5562  if (isolate->debug()->is_active() && resolution->IsJSPromise()) {
5563    // Mark the dependency of the new {promise} on the {resolution}.
5564    Object::SetProperty(isolate, resolution,
5565                        isolate->factory()->promise_handled_by_symbol(),
5566                        promise)
5567        .Check();
5568  }
5569  MicrotaskQueue* microtask_queue = then_context->microtask_queue();
5570  if (microtask_queue) microtask_queue->EnqueueMicrotask(*task);
5571
5572  // 15. Return undefined.
5573  return isolate->factory()->undefined_value();
5574}
5575
5576// static
5577Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
5578                                                  Handle<Object> reactions,
5579                                                  Handle<Object> argument,
5580                                                  PromiseReaction::Type type) {
5581  CHECK(reactions->IsSmi() || reactions->IsPromiseReaction());
5582
5583  // We need to reverse the {reactions} here, since we record them
5584  // on the JSPromise in the reverse order.
5585  {
5586    DisallowGarbageCollection no_gc;
5587    Object current = *reactions;
5588    Object reversed = Smi::zero();
5589    while (!current.IsSmi()) {
5590      Object next = PromiseReaction::cast(current).next();
5591      PromiseReaction::cast(current).set_next(reversed);
5592      reversed = current;
5593      current = next;
5594    }
5595    reactions = handle(reversed, isolate);
5596  }
5597
5598  // Morph the {reactions} into PromiseReactionJobTasks
5599  // and push them onto the microtask queue.
5600  while (!reactions->IsSmi()) {
5601    Handle<HeapObject> task = Handle<HeapObject>::cast(reactions);
5602    Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(task);
5603    reactions = handle(reaction->next(), isolate);
5604
5605    // According to HTML, we use the context of the appropriate handler as the
5606    // context of the microtask. See step 3 of HTML's EnqueueJob:
5607    // https://html.spec.whatwg.org/C/#enqueuejob(queuename,-job,-arguments)
5608    Handle<NativeContext> handler_context;
5609
5610    Handle<HeapObject> primary_handler;
5611    Handle<HeapObject> secondary_handler;
5612    if (type == PromiseReaction::kFulfill) {
5613      primary_handler = handle(reaction->fulfill_handler(), isolate);
5614      secondary_handler = handle(reaction->reject_handler(), isolate);
5615    } else {
5616      primary_handler = handle(reaction->reject_handler(), isolate);
5617      secondary_handler = handle(reaction->fulfill_handler(), isolate);
5618    }
5619
5620    bool has_handler_context = false;
5621    if (primary_handler->IsJSReceiver()) {
5622      has_handler_context = JSReceiver::GetContextForMicrotask(
5623                                Handle<JSReceiver>::cast(primary_handler))
5624                                .ToHandle(&handler_context);
5625    }
5626    if (!has_handler_context && secondary_handler->IsJSReceiver()) {
5627      has_handler_context = JSReceiver::GetContextForMicrotask(
5628                                Handle<JSReceiver>::cast(secondary_handler))
5629                                .ToHandle(&handler_context);
5630    }
5631    if (!has_handler_context) handler_context = isolate->native_context();
5632
5633    STATIC_ASSERT(
5634        static_cast<int>(PromiseReaction::kSize) ==
5635        static_cast<int>(
5636            PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks));
5637    if (type == PromiseReaction::kFulfill) {
5638      task->set_map(
5639          ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map(),
5640          kReleaseStore);
5641      Handle<PromiseFulfillReactionJobTask>::cast(task)->set_argument(
5642          *argument);
5643      Handle<PromiseFulfillReactionJobTask>::cast(task)->set_context(
5644          *handler_context);
5645      STATIC_ASSERT(
5646          static_cast<int>(PromiseReaction::kFulfillHandlerOffset) ==
5647          static_cast<int>(PromiseFulfillReactionJobTask::kHandlerOffset));
5648      STATIC_ASSERT(
5649          static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
5650          static_cast<int>(
5651              PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset));
5652      STATIC_ASSERT(
5653          static_cast<int>(
5654              PromiseReaction::kContinuationPreservedEmbedderDataOffset) ==
5655          static_cast<int>(PromiseFulfillReactionJobTask::
5656                               kContinuationPreservedEmbedderDataOffset));
5657    } else {
5658      DisallowGarbageCollection no_gc;
5659      task->set_map(
5660          ReadOnlyRoots(isolate).promise_reject_reaction_job_task_map(),
5661          kReleaseStore);
5662      Handle<PromiseRejectReactionJobTask>::cast(task)->set_argument(*argument);
5663      Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
5664          *handler_context);
5665      Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(
5666          *primary_handler);
5667      STATIC_ASSERT(
5668          static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
5669          static_cast<int>(
5670              PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset));
5671      STATIC_ASSERT(
5672          static_cast<int>(
5673              PromiseReaction::kContinuationPreservedEmbedderDataOffset) ==
5674          static_cast<int>(PromiseRejectReactionJobTask::
5675                               kContinuationPreservedEmbedderDataOffset));
5676    }
5677
5678    MicrotaskQueue* microtask_queue = handler_context->microtask_queue();
5679    if (microtask_queue) {
5680      microtask_queue->EnqueueMicrotask(
5681          *Handle<PromiseReactionJobTask>::cast(task));
5682    }
5683  }
5684
5685  return isolate->factory()->undefined_value();
5686}
5687
5688template <typename Derived, typename Shape>
5689void HashTable<Derived, Shape>::IteratePrefix(ObjectVisitor* v) {
5690  BodyDescriptorBase::IteratePointers(*this, 0, kElementsStartOffset, v);
5691}
5692
5693template <typename Derived, typename Shape>
5694void HashTable<Derived, Shape>::IterateElements(ObjectVisitor* v) {
5695  BodyDescriptorBase::IteratePointers(*this, kElementsStartOffset,
5696                                      SizeFor(length()), v);
5697}
5698
5699template <typename Derived, typename Shape>
5700template <typename IsolateT>
5701Handle<Derived> HashTable<Derived, Shape>::New(
5702    IsolateT* isolate, int at_least_space_for, AllocationType allocation,
5703    MinimumCapacity capacity_option) {
5704  DCHECK_LE(0, at_least_space_for);
5705  DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
5706                 base::bits::IsPowerOfTwo(at_least_space_for));
5707
5708  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
5709                     ? at_least_space_for
5710                     : ComputeCapacity(at_least_space_for);
5711  if (capacity > HashTable::kMaxCapacity) {
5712    isolate->FatalProcessOutOfHeapMemory("invalid table size");
5713  }
5714  return NewInternal(isolate, capacity, allocation);
5715}
5716
5717template <typename Derived, typename Shape>
5718template <typename IsolateT>
5719Handle<Derived> HashTable<Derived, Shape>::NewInternal(
5720    IsolateT* isolate, int capacity, AllocationType allocation) {
5721  auto* factory = isolate->factory();
5722  int length = EntryToIndex(InternalIndex(capacity));
5723  Handle<FixedArray> array = factory->NewFixedArrayWithMap(
5724      Derived::GetMap(ReadOnlyRoots(isolate)), length, allocation);
5725  Handle<Derived> table = Handle<Derived>::cast(array);
5726
5727  table->SetNumberOfElements(0);
5728  table->SetNumberOfDeletedElements(0);
5729  table->SetCapacity(capacity);
5730  return table;
5731}
5732
5733template <typename Derived, typename Shape>
5734void HashTable<Derived, Shape>::Rehash(PtrComprCageBase cage_base,
5735                                       Derived new_table) {
5736  DisallowGarbageCollection no_gc;
5737  WriteBarrierMode mode = new_table.GetWriteBarrierMode(no_gc);
5738
5739  DCHECK_LT(NumberOfElements(), new_table.Capacity());
5740
5741  // Copy prefix to new array.
5742  for (int i = kPrefixStartIndex; i < kElementsStartIndex; i++) {
5743    new_table.set(i, get(cage_base, i), mode);
5744  }
5745
5746  // Rehash the elements.
5747  ReadOnlyRoots roots = GetReadOnlyRoots(cage_base);
5748  for (InternalIndex i : this->IterateEntries()) {
5749    uint32_t from_index = EntryToIndex(i);
5750    Object k = this->get(cage_base, from_index);
5751    if (!IsKey(roots, k)) continue;
5752    uint32_t hash = Shape::HashForObject(roots, k);
5753    uint32_t insertion_index =
5754        EntryToIndex(new_table.FindInsertionEntry(cage_base, roots, hash));
5755    new_table.set_key(insertion_index, get(cage_base, from_index), mode);
5756    for (int j = 1; j < Shape::kEntrySize; j++) {
5757      new_table.set(insertion_index + j, get(cage_base, from_index + j), mode);
5758    }
5759  }
5760  new_table.SetNumberOfElements(NumberOfElements());
5761  new_table.SetNumberOfDeletedElements(0);
5762}
5763
5764template <typename Derived, typename Shape>
5765InternalIndex HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots,
5766                                                       Object k, int probe,
5767                                                       InternalIndex expected) {
5768  uint32_t hash = Shape::HashForObject(roots, k);
5769  uint32_t capacity = this->Capacity();
5770  InternalIndex entry = FirstProbe(hash, capacity);
5771  for (int i = 1; i < probe; i++) {
5772    if (entry == expected) return expected;
5773    entry = NextProbe(entry, i, capacity);
5774  }
5775  return entry;
5776}
5777
5778template <typename Derived, typename Shape>
5779void HashTable<Derived, Shape>::Swap(InternalIndex entry1, InternalIndex entry2,
5780                                     WriteBarrierMode mode) {
5781  int index1 = EntryToIndex(entry1);
5782  int index2 = EntryToIndex(entry2);
5783  Object temp[Shape::kEntrySize];
5784  Derived* self = static_cast<Derived*>(this);
5785  for (int j = 0; j < Shape::kEntrySize; j++) {
5786    temp[j] = get(index1 + j);
5787  }
5788  self->set_key(index1, get(index2), mode);
5789  for (int j = 1; j < Shape::kEntrySize; j++) {
5790    set(index1 + j, get(index2 + j), mode);
5791  }
5792  self->set_key(index2, temp[0], mode);
5793  for (int j = 1; j < Shape::kEntrySize; j++) {
5794    set(index2 + j, temp[j], mode);
5795  }
5796}
5797
5798template <typename Derived, typename Shape>
5799void HashTable<Derived, Shape>::Rehash(PtrComprCageBase cage_base) {
5800  DisallowGarbageCollection no_gc;
5801  WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
5802  ReadOnlyRoots roots = GetReadOnlyRoots(cage_base);
5803  uint32_t capacity = Capacity();
5804  bool done = false;
5805  for (int probe = 1; !done; probe++) {
5806    // All elements at entries given by one of the first _probe_ probes
5807    // are placed correctly. Other elements might need to be moved.
5808    done = true;
5809    for (InternalIndex current(0); current.raw_value() < capacity;
5810         /* {current} is advanced manually below, when appropriate.*/) {
5811      Object current_key = KeyAt(cage_base, current);
5812      if (!IsKey(roots, current_key)) {
5813        ++current;  // Advance to next entry.
5814        continue;
5815      }
5816      InternalIndex target = EntryForProbe(roots, current_key, probe, current);
5817      if (current == target) {
5818        ++current;  // Advance to next entry.
5819        continue;
5820      }
5821      Object target_key = KeyAt(cage_base, target);
5822      if (!IsKey(roots, target_key) ||
5823          EntryForProbe(roots, target_key, probe, target) != target) {
5824        // Put the current element into the correct position.
5825        Swap(current, target, mode);
5826        // The other element will be processed on the next iteration,
5827        // so don't advance {current} here!
5828      } else {
5829        // The place for the current element is occupied. Leave the element
5830        // for the next probe.
5831        done = false;
5832        ++current;  // Advance to next entry.
5833      }
5834    }
5835  }
5836  // Wipe deleted entries.
5837  Object the_hole = roots.the_hole_value();
5838  HeapObject undefined = roots.undefined_value();
5839  Derived* self = static_cast<Derived*>(this);
5840  for (InternalIndex current : InternalIndex::Range(capacity)) {
5841    if (KeyAt(cage_base, current) == the_hole) {
5842      self->set_key(EntryToIndex(current) + kEntryKeyIndex, undefined,
5843                    SKIP_WRITE_BARRIER);
5844    }
5845  }
5846  SetNumberOfDeletedElements(0);
5847}
5848
5849template <typename Derived, typename Shape>
5850template <typename IsolateT>
5851Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
5852    IsolateT* isolate, Handle<Derived> table, int n,
5853    AllocationType allocation) {
5854  if (table->HasSufficientCapacityToAdd(n)) return table;
5855
5856  int capacity = table->Capacity();
5857  int new_nof = table->NumberOfElements() + n;
5858
5859  bool should_pretenure = allocation == AllocationType::kOld ||
5860                          ((capacity > kMinCapacityForPretenure) &&
5861                           !Heap::InYoungGeneration(*table));
5862  Handle<Derived> new_table = HashTable::New(
5863      isolate, new_nof,
5864      should_pretenure ? AllocationType::kOld : AllocationType::kYoung);
5865
5866  table->Rehash(isolate, *new_table);
5867  return new_table;
5868}
5869
5870template <typename Derived, typename Shape>
5871bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
5872    int number_of_additional_elements) {
5873  return HasSufficientCapacityToAdd(Capacity(), NumberOfElements(),
5874                                    NumberOfDeletedElements(),
5875                                    number_of_additional_elements);
5876}
5877
5878// static
5879template <typename Derived, typename Shape>
5880bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
5881    int capacity, int number_of_elements, int number_of_deleted_elements,
5882    int number_of_additional_elements) {
5883  int nof = number_of_elements + number_of_additional_elements;
5884  // Return true if:
5885  //   50% is still free after adding number_of_additional_elements elements and
5886  //   at most 50% of the free elements are deleted elements.
5887  if ((nof < capacity) &&
5888      ((number_of_deleted_elements <= (capacity - nof) / 2))) {
5889    int needed_free = nof / 2;
5890    if (nof + needed_free <= capacity) return true;
5891  }
5892  return false;
5893}
5894
5895// static
5896template <typename Derived, typename Shape>
5897int HashTable<Derived, Shape>::ComputeCapacityWithShrink(
5898    int current_capacity, int at_least_room_for) {
5899  // Shrink to fit the number of elements if only a quarter of the
5900  // capacity is filled with elements.
5901  if (at_least_room_for > (current_capacity / 4)) return current_capacity;
5902  // Recalculate the smaller capacity actually needed.
5903  int new_capacity = ComputeCapacity(at_least_room_for);
5904  DCHECK_GE(new_capacity, at_least_room_for);
5905  // Don't go lower than room for {kMinShrinkCapacity} elements.
5906  if (new_capacity < Derived::kMinShrinkCapacity) return current_capacity;
5907  return new_capacity;
5908}
5909
5910// static
5911template <typename Derived, typename Shape>
5912Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
5913                                                  Handle<Derived> table,
5914                                                  int additional_capacity) {
5915  int new_capacity = ComputeCapacityWithShrink(
5916      table->Capacity(), table->NumberOfElements() + additional_capacity);
5917  if (new_capacity == table->Capacity()) return table;
5918  DCHECK_GE(new_capacity, Derived::kMinShrinkCapacity);
5919
5920  bool pretenure = (new_capacity > kMinCapacityForPretenure) &&
5921                   !Heap::InYoungGeneration(*table);
5922  Handle<Derived> new_table =
5923      HashTable::New(isolate, new_capacity,
5924                     pretenure ? AllocationType::kOld : AllocationType::kYoung,
5925                     USE_CUSTOM_MINIMUM_CAPACITY);
5926
5927  table->Rehash(isolate, *new_table);
5928  return new_table;
5929}
5930
5931template <typename Derived, typename Shape>
5932InternalIndex HashTable<Derived, Shape>::FindInsertionEntry(
5933    PtrComprCageBase cage_base, ReadOnlyRoots roots, uint32_t hash) {
5934  uint32_t capacity = Capacity();
5935  uint32_t count = 1;
5936  // EnsureCapacity will guarantee the hash table is never full.
5937  for (InternalIndex entry = FirstProbe(hash, capacity);;
5938       entry = NextProbe(entry, count++, capacity)) {
5939    if (!IsKey(roots, KeyAt(cage_base, entry))) return entry;
5940  }
5941}
5942
5943base::Optional<PropertyCell>
5944GlobalDictionary::TryFindPropertyCellForConcurrentLookupIterator(
5945    Isolate* isolate, Handle<Name> name, RelaxedLoadTag tag) {
5946  // This reimplements HashTable::FindEntry for use in a concurrent setting.
5947  // 1) Atomic loads.
5948  // 2) IsPendingAllocation checks.
5949  // 3) Return the PropertyCell value instead of the InternalIndex to avoid a
5950  //   repeated load (unsafe with concurrent modifications).
5951
5952  DisallowGarbageCollection no_gc;
5953  PtrComprCageBase cage_base{isolate};
5954  ReadOnlyRoots roots(isolate);
5955  const int32_t hash = ShapeT::Hash(roots, name);
5956  const uint32_t capacity = Capacity();
5957  uint32_t count = 1;
5958  Object undefined = roots.undefined_value();
5959  Object the_hole = roots.the_hole_value();
5960  // EnsureCapacity will guarantee the hash table is never full.
5961  for (InternalIndex entry = FirstProbe(hash, capacity);;
5962       entry = NextProbe(entry, count++, capacity)) {
5963    Object element = KeyAt(cage_base, entry, kRelaxedLoad);
5964    if (isolate->heap()->IsPendingAllocation(element)) return {};
5965    if (element == undefined) return {};
5966    if (ShapeT::kMatchNeedsHoleCheck && element == the_hole) continue;
5967    if (!ShapeT::IsMatch(name, element)) continue;
5968    CHECK(element.IsPropertyCell(cage_base));
5969    return PropertyCell::cast(element);
5970  }
5971}
5972
5973Handle<StringSet> StringSet::New(Isolate* isolate) {
5974  return HashTable::New(isolate, 0);
5975}
5976
5977Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
5978                                 Handle<String> name) {
5979  if (!stringset->Has(isolate, name)) {
5980    stringset = EnsureCapacity(isolate, stringset);
5981    uint32_t hash = ShapeT::Hash(ReadOnlyRoots(isolate), *name);
5982    InternalIndex entry = stringset->FindInsertionEntry(isolate, hash);
5983    stringset->set(EntryToIndex(entry), *name);
5984    stringset->ElementAdded();
5985  }
5986  return stringset;
5987}
5988
5989bool StringSet::Has(Isolate* isolate, Handle<String> name) {
5990  return FindEntry(isolate, *name).is_found();
5991}
5992
5993Handle<RegisteredSymbolTable> RegisteredSymbolTable::Add(
5994    Isolate* isolate, Handle<RegisteredSymbolTable> table, Handle<String> key,
5995    Handle<Symbol> symbol) {
5996  // Validate that the key is absent.
5997  SLOW_DCHECK(table->FindEntry(isolate, key).is_not_found());
5998
5999  table = EnsureCapacity(isolate, table);
6000  uint32_t hash = ShapeT::Hash(ReadOnlyRoots(isolate), key);
6001  InternalIndex entry = table->FindInsertionEntry(isolate, hash);
6002  table->set(EntryToIndex(entry), *key);
6003  table->set(EntryToValueIndex(entry), *symbol);
6004  table->ElementAdded();
6005  return table;
6006}
6007
6008Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
6009                                         Handle<ObjectHashSet> set,
6010                                         Handle<Object> key) {
6011  int32_t hash = key->GetOrCreateHash(isolate).value();
6012  if (!set->Has(isolate, key, hash)) {
6013    set = EnsureCapacity(isolate, set);
6014    InternalIndex entry = set->FindInsertionEntry(isolate, hash);
6015    set->set(EntryToIndex(entry), *key);
6016    set->ElementAdded();
6017  }
6018  return set;
6019}
6020
6021template <typename Derived, typename Shape>
6022template <typename IsolateT>
6023Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
6024    IsolateT* isolate, int at_least_space_for, AllocationType allocation,
6025    MinimumCapacity capacity_option) {
6026  DCHECK_LE(0, at_least_space_for);
6027  Handle<Derived> dict = Dictionary<Derived, Shape>::New(
6028      isolate, at_least_space_for, allocation, capacity_option);
6029  dict->SetHash(PropertyArray::kNoHashSentinel);
6030  dict->set_next_enumeration_index(PropertyDetails::kInitialIndex);
6031  return dict;
6032}
6033
6034template <typename Derived, typename Shape>
6035int BaseNameDictionary<Derived, Shape>::NextEnumerationIndex(
6036    Isolate* isolate, Handle<Derived> dictionary) {
6037  int index = dictionary->next_enumeration_index();
6038  // Check whether the next enumeration index is valid.
6039  if (!PropertyDetails::IsValidIndex(index)) {
6040    // If not, we generate new indices for the properties.
6041    Handle<FixedArray> iteration_order = IterationIndices(isolate, dictionary);
6042    int length = iteration_order->length();
6043    DCHECK_LE(length, dictionary->NumberOfElements());
6044
6045    // Iterate over the dictionary using the enumeration order and update
6046    // the dictionary with new enumeration indices.
6047    for (int i = 0; i < length; i++) {
6048      InternalIndex internal_index(Smi::ToInt(iteration_order->get(i)));
6049      DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
6050                               dictionary->KeyAt(isolate, internal_index)));
6051
6052      int enum_index = PropertyDetails::kInitialIndex + i;
6053
6054      PropertyDetails details = dictionary->DetailsAt(internal_index);
6055      PropertyDetails new_details = details.set_index(enum_index);
6056      dictionary->DetailsAtPut(internal_index, new_details);
6057    }
6058
6059    index = PropertyDetails::kInitialIndex + length;
6060  }
6061
6062  // Don't update the next enumeration index here, since we might be looking at
6063  // an immutable empty dictionary.
6064  return index;
6065}
6066
6067template <typename Derived, typename Shape>
6068Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
6069    Isolate* isolate, Handle<Derived> dictionary, InternalIndex entry) {
6070  DCHECK(Shape::kEntrySize != 3 ||
6071         dictionary->DetailsAt(entry).IsConfigurable());
6072  dictionary->ClearEntry(entry);
6073  dictionary->ElementRemoved();
6074  return Shrink(isolate, dictionary);
6075}
6076
6077template <typename Derived, typename Shape>
6078Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
6079                                                  Handle<Derived> dictionary,
6080                                                  Key key, Handle<Object> value,
6081                                                  PropertyDetails details) {
6082  InternalIndex entry = dictionary->FindEntry(isolate, key);
6083
6084  // If the entry is present set the value;
6085  if (entry.is_not_found()) {
6086    return Derived::Add(isolate, dictionary, key, value, details);
6087  }
6088
6089  // We don't need to copy over the enumeration index.
6090  dictionary->ValueAtPut(entry, *value);
6091  if (Shape::kEntrySize == 3) dictionary->DetailsAtPut(entry, details);
6092  return dictionary;
6093}
6094
6095template <typename Derived, typename Shape>
6096template <typename IsolateT>
6097Handle<Derived>
6098BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
6099    IsolateT* isolate, Handle<Derived> dictionary, Key key,
6100    Handle<Object> value, PropertyDetails details, InternalIndex* entry_out) {
6101  // Insert element at empty or deleted entry.
6102  return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
6103                                         details, entry_out);
6104}
6105
6106template <typename Derived, typename Shape>
6107Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
6108    Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
6109    PropertyDetails details, InternalIndex* entry_out) {
6110  // Insert element at empty or deleted entry
6111  DCHECK_EQ(0, details.dictionary_index());
6112  // Assign an enumeration index to the property and update
6113  // SetNextEnumerationIndex.
6114  int index = Derived::NextEnumerationIndex(isolate, dictionary);
6115  details = details.set_index(index);
6116  dictionary = AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
6117                                               details, entry_out);
6118  // Update enumeration index here in order to avoid potential modification of
6119  // the canonical empty dictionary which lives in read only space.
6120  dictionary->set_next_enumeration_index(index + 1);
6121  return dictionary;
6122}
6123
6124template <typename Derived, typename Shape>
6125template <typename IsolateT>
6126Handle<Derived> Dictionary<Derived, Shape>::Add(IsolateT* isolate,
6127                                                Handle<Derived> dictionary,
6128                                                Key key, Handle<Object> value,
6129                                                PropertyDetails details,
6130                                                InternalIndex* entry_out) {
6131  ReadOnlyRoots roots(isolate);
6132  uint32_t hash = Shape::Hash(roots, key);
6133  // Validate that the key is absent.
6134  SLOW_DCHECK(dictionary->FindEntry(isolate, key).is_not_found());
6135  // Check whether the dictionary should be extended.
6136  dictionary = Derived::EnsureCapacity(isolate, dictionary);
6137
6138  // Compute the key object.
6139  Handle<Object> k = Shape::AsHandle(isolate, key);
6140
6141  InternalIndex entry = dictionary->FindInsertionEntry(isolate, roots, hash);
6142  dictionary->SetEntry(entry, *k, *value, details);
6143  DCHECK(dictionary->KeyAt(isolate, entry).IsNumber() ||
6144         Shape::Unwrap(dictionary->KeyAt(isolate, entry)).IsUniqueName());
6145  dictionary->ElementAdded();
6146  if (entry_out) *entry_out = entry;
6147  return dictionary;
6148}
6149
6150template <typename Derived, typename Shape>
6151Handle<Derived> Dictionary<Derived, Shape>::ShallowCopy(
6152    Isolate* isolate, Handle<Derived> dictionary) {
6153  return Handle<Derived>::cast(isolate->factory()->CopyFixedArrayWithMap(
6154      dictionary, Derived::GetMap(ReadOnlyRoots(isolate))));
6155}
6156
6157// static
6158Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
6159    Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
6160    Handle<Object> value) {
6161  return AtPut(isolate, dictionary, key, value, PropertyDetails::Empty());
6162}
6163
6164void NumberDictionary::UpdateMaxNumberKey(uint32_t key,
6165                                          Handle<JSObject> dictionary_holder) {
6166  DisallowGarbageCollection no_gc;
6167  // If the dictionary requires slow elements an element has already
6168  // been added at a high index.
6169  if (requires_slow_elements()) return;
6170  // Check if this index is high enough that we should require slow
6171  // elements.
6172  if (key > kRequiresSlowElementsLimit) {
6173    if (!dictionary_holder.is_null()) {
6174      dictionary_holder->RequireSlowElements(*this);
6175    }
6176    set_requires_slow_elements();
6177    return;
6178  }
6179  // Update max key value.
6180  Object max_index_object = get(kMaxNumberKeyIndex);
6181  if (!max_index_object.IsSmi() || max_number_key() < key) {
6182    FixedArray::set(kMaxNumberKeyIndex,
6183                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
6184  }
6185}
6186
6187Handle<NumberDictionary> NumberDictionary::Set(
6188    Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
6189    Handle<Object> value, Handle<JSObject> dictionary_holder,
6190    PropertyDetails details) {
6191  // We could call Set with empty dictionaries. UpdateMaxNumberKey doesn't
6192  // expect empty dictionaries so make sure to call AtPut that correctly handles
6193  // them by creating new dictionary when required.
6194  Handle<NumberDictionary> new_dictionary =
6195      AtPut(isolate, dictionary, key, value, details);
6196  new_dictionary->UpdateMaxNumberKey(key, dictionary_holder);
6197  return new_dictionary;
6198}
6199
6200void NumberDictionary::CopyValuesTo(FixedArray elements) {
6201  ReadOnlyRoots roots = GetReadOnlyRoots();
6202  int pos = 0;
6203  DisallowGarbageCollection no_gc;
6204  WriteBarrierMode mode = elements.GetWriteBarrierMode(no_gc);
6205  for (InternalIndex i : this->IterateEntries()) {
6206    Object k;
6207    if (this->ToKey(roots, i, &k)) {
6208      elements.set(pos++, this->ValueAt(i), mode);
6209    }
6210  }
6211  DCHECK_EQ(pos, elements.length());
6212}
6213
6214template <typename Derived, typename Shape>
6215int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
6216  ReadOnlyRoots roots = this->GetReadOnlyRoots();
6217  int result = 0;
6218  for (InternalIndex i : this->IterateEntries()) {
6219    Object k;
6220    if (!this->ToKey(roots, i, &k)) continue;
6221    if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
6222    PropertyDetails details = this->DetailsAt(i);
6223    PropertyAttributes attr = details.attributes();
6224    if ((attr & ONLY_ENUMERABLE) == 0) result++;
6225  }
6226  return result;
6227}
6228
6229template <typename Derived, typename Shape>
6230Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
6231    Isolate* isolate, Handle<Derived> dictionary) {
6232  Handle<FixedArray> array =
6233      isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
6234  ReadOnlyRoots roots(isolate);
6235  int array_size = 0;
6236  {
6237    DisallowGarbageCollection no_gc;
6238    Derived raw_dictionary = *dictionary;
6239    for (InternalIndex i : dictionary->IterateEntries()) {
6240      Object k;
6241      if (!raw_dictionary.ToKey(roots, i, &k)) continue;
6242      array->set(array_size++, Smi::FromInt(i.as_int()));
6243    }
6244
6245    // The global dictionary doesn't track its deletion count, so we may iterate
6246    // fewer entries than the count of elements claimed by the dictionary.
6247    if (std::is_same<Derived, GlobalDictionary>::value) {
6248      DCHECK_LE(array_size, dictionary->NumberOfElements());
6249    } else {
6250      DCHECK_EQ(array_size, dictionary->NumberOfElements());
6251    }
6252
6253    EnumIndexComparator<Derived> cmp(raw_dictionary);
6254    // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
6255    // store operations that are safe for concurrent marking.
6256    AtomicSlot start(array->GetFirstElementAddress());
6257    std::sort(start, start + array_size, cmp);
6258  }
6259  return FixedArray::ShrinkOrEmpty(isolate, array, array_size);
6260}
6261
6262// Backwards lookup (slow).
6263template <typename Derived, typename Shape>
6264Object Dictionary<Derived, Shape>::SlowReverseLookup(Object value) {
6265  Derived dictionary = Derived::cast(*this);
6266  ReadOnlyRoots roots = dictionary.GetReadOnlyRoots();
6267  for (InternalIndex i : dictionary.IterateEntries()) {
6268    Object k;
6269    if (!dictionary.ToKey(roots, i, &k)) continue;
6270    Object e = dictionary.ValueAt(i);
6271    if (e == value) return k;
6272  }
6273  return roots.undefined_value();
6274}
6275
6276template <typename Derived, typename Shape>
6277void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
6278    Handle<Derived> table) {
6279  int length = table->length();
6280  for (int i = Derived::EntryToIndex(InternalIndex(0)); i < length; i++) {
6281    table->set_the_hole(i);
6282  }
6283}
6284
6285template <typename Derived, typename Shape>
6286Object ObjectHashTableBase<Derived, Shape>::Lookup(PtrComprCageBase cage_base,
6287                                                   Handle<Object> key,
6288                                                   int32_t hash) {
6289  DisallowGarbageCollection no_gc;
6290  ReadOnlyRoots roots = this->GetReadOnlyRoots(cage_base);
6291  DCHECK(this->IsKey(roots, *key));
6292
6293  InternalIndex entry = this->FindEntry(cage_base, roots, key, hash);
6294  if (entry.is_not_found()) return roots.the_hole_value();
6295  return this->get(Derived::EntryToIndex(entry) + 1);
6296}
6297
6298// The implementation should be in sync with
6299// CodeStubAssembler::NameToIndexHashTableLookup.
6300int NameToIndexHashTable::Lookup(Handle<Name> key) {
6301  DisallowGarbageCollection no_gc;
6302  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
6303  ReadOnlyRoots roots = this->GetReadOnlyRoots(cage_base);
6304
6305  InternalIndex entry = this->FindEntry(cage_base, roots, key, key->hash());
6306  if (entry.is_not_found()) return -1;
6307  return Smi::cast(this->get(EntryToValueIndex(entry))).value();
6308}
6309
6310template <typename Derived, typename Shape>
6311Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key) {
6312  DisallowGarbageCollection no_gc;
6313
6314  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
6315  ReadOnlyRoots roots = this->GetReadOnlyRoots(cage_base);
6316  DCHECK(this->IsKey(roots, *key));
6317
6318  // If the object does not have an identity hash, it was never used as a key.
6319  Object hash = key->GetHash();
6320  if (hash.IsUndefined(roots)) {
6321    return roots.the_hole_value();
6322  }
6323  return Lookup(cage_base, key, Smi::ToInt(hash));
6324}
6325
6326template <typename Derived, typename Shape>
6327Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
6328                                                   int32_t hash) {
6329  return Lookup(GetPtrComprCageBase(*this), key, hash);
6330}
6331
6332template <typename Derived, typename Shape>
6333Object ObjectHashTableBase<Derived, Shape>::ValueAt(InternalIndex entry) {
6334  return this->get(EntryToValueIndex(entry));
6335}
6336
6337Object RegisteredSymbolTable::ValueAt(InternalIndex entry) {
6338  return this->get(EntryToValueIndex(entry));
6339}
6340
6341Object NameToIndexHashTable::ValueAt(InternalIndex entry) {
6342  return this->get(EntryToValueIndex(entry));
6343}
6344
6345int NameToIndexHashTable::IndexAt(InternalIndex entry) {
6346  Object value = ValueAt(entry);
6347  if (value.IsSmi()) {
6348    int index = Smi::ToInt(value);
6349    DCHECK_LE(0, index);
6350    return index;
6351  }
6352  return -1;
6353}
6354
6355template <typename Derived, typename Shape>
6356Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Handle<Derived> table,
6357                                                         Handle<Object> key,
6358                                                         Handle<Object> value) {
6359  Isolate* isolate = Heap::FromWritableHeapObject(*table)->isolate();
6360  DCHECK(table->IsKey(ReadOnlyRoots(isolate), *key));
6361  DCHECK(!value->IsTheHole(ReadOnlyRoots(isolate)));
6362
6363  // Make sure the key object has an identity hash code.
6364  int32_t hash = key->GetOrCreateHash(isolate).value();
6365
6366  return ObjectHashTableBase<Derived, Shape>::Put(isolate, table, key, value,
6367                                                  hash);
6368}
6369
6370template <typename Derived, typename Shape>
6371Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
6372                                                         Handle<Derived> table,
6373                                                         Handle<Object> key,
6374                                                         Handle<Object> value,
6375                                                         int32_t hash) {
6376  ReadOnlyRoots roots(isolate);
6377  DCHECK(table->IsKey(roots, *key));
6378  DCHECK(!value->IsTheHole(roots));
6379
6380  InternalIndex entry = table->FindEntry(isolate, roots, key, hash);
6381
6382  // Key is already in table, just overwrite value.
6383  if (entry.is_found()) {
6384    table->set(Derived::EntryToValueIndex(entry), *value);
6385    return table;
6386  }
6387
6388  // Rehash if more than 33% of the entries are deleted entries.
6389  // TODO(verwaest): Consider to shrink the fixed array in place.
6390  if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
6391    table->Rehash(isolate);
6392  }
6393  // If we're out of luck, we didn't get a GC recently, and so rehashing
6394  // isn't enough to avoid a crash.
6395  if (!table->HasSufficientCapacityToAdd(1)) {
6396    int nof = table->NumberOfElements() + 1;
6397    int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
6398    if (capacity > ObjectHashTable::kMaxCapacity) {
6399      for (size_t i = 0; i < 2; ++i) {
6400        isolate->heap()->CollectAllGarbage(
6401            Heap::kNoGCFlags, GarbageCollectionReason::kFullHashtable);
6402      }
6403      table->Rehash(isolate);
6404    }
6405  }
6406
6407  // Check whether the hash table should be extended.
6408  table = Derived::EnsureCapacity(isolate, table);
6409  table->AddEntry(table->FindInsertionEntry(isolate, hash), *key, *value);
6410  return table;
6411}
6412
6413template <typename Derived, typename Shape>
6414Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
6415    Isolate* isolate, Handle<Derived> table, Handle<Object> key,
6416    bool* was_present) {
6417  DCHECK(table->IsKey(table->GetReadOnlyRoots(), *key));
6418
6419  Object hash = key->GetHash();
6420  if (hash.IsUndefined()) {
6421    *was_present = false;
6422    return table;
6423  }
6424
6425  return Remove(isolate, table, key, was_present, Smi::ToInt(hash));
6426}
6427
6428template <typename Derived, typename Shape>
6429Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
6430    Isolate* isolate, Handle<Derived> table, Handle<Object> key,
6431    bool* was_present, int32_t hash) {
6432  ReadOnlyRoots roots = table->GetReadOnlyRoots();
6433  DCHECK(table->IsKey(roots, *key));
6434
6435  InternalIndex entry = table->FindEntry(isolate, roots, key, hash);
6436  if (entry.is_not_found()) {
6437    *was_present = false;
6438    return table;
6439  }
6440
6441  *was_present = true;
6442  table->RemoveEntry(entry);
6443  return Derived::Shrink(isolate, table);
6444}
6445
6446template <typename Derived, typename Shape>
6447void ObjectHashTableBase<Derived, Shape>::AddEntry(InternalIndex entry,
6448                                                   Object key, Object value) {
6449  Derived* self = static_cast<Derived*>(this);
6450  self->set_key(Derived::EntryToIndex(entry), key);
6451  self->set(Derived::EntryToValueIndex(entry), value);
6452  self->ElementAdded();
6453}
6454
6455template <typename Derived, typename Shape>
6456void ObjectHashTableBase<Derived, Shape>::RemoveEntry(InternalIndex entry) {
6457  this->set_the_hole(Derived::EntryToIndex(entry));
6458  this->set_the_hole(Derived::EntryToValueIndex(entry));
6459  this->ElementRemoved();
6460}
6461
6462void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
6463  Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
6464  set->set_table(*table);
6465}
6466
6467void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) {
6468  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
6469  table = OrderedHashSet::Clear(isolate, table);
6470  set->set_table(*table);
6471}
6472
6473void JSSet::Rehash(Isolate* isolate) {
6474  Handle<OrderedHashSet> table_handle(OrderedHashSet::cast(table()), isolate);
6475  Handle<OrderedHashSet> new_table =
6476      OrderedHashSet::Rehash(isolate, table_handle).ToHandleChecked();
6477  set_table(*new_table);
6478}
6479
6480void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
6481  Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
6482  map->set_table(*table);
6483}
6484
6485void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
6486  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
6487  table = OrderedHashMap::Clear(isolate, table);
6488  map->set_table(*table);
6489}
6490
6491void JSMap::Rehash(Isolate* isolate) {
6492  Handle<OrderedHashMap> table_handle(OrderedHashMap::cast(table()), isolate);
6493  Handle<OrderedHashMap> new_table =
6494      OrderedHashMap::Rehash(isolate, table_handle).ToHandleChecked();
6495  set_table(*new_table);
6496}
6497
6498void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
6499                                  Isolate* isolate) {
6500  Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);
6501  weak_collection->set_table(*table);
6502}
6503
6504void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
6505                           Handle<Object> key, Handle<Object> value,
6506                           int32_t hash) {
6507  DCHECK(key->IsJSReceiver() || key->IsSymbol());
6508  Handle<EphemeronHashTable> table(
6509      EphemeronHashTable::cast(weak_collection->table()),
6510      weak_collection->GetIsolate());
6511  DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
6512  Handle<EphemeronHashTable> new_table = EphemeronHashTable::Put(
6513      weak_collection->GetIsolate(), table, key, value, hash);
6514  weak_collection->set_table(*new_table);
6515  if (*table != *new_table) {
6516    // Zap the old table since we didn't record slots for its elements.
6517    EphemeronHashTable::FillEntriesWithHoles(table);
6518  }
6519}
6520
6521bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
6522                              Handle<Object> key, int32_t hash) {
6523  DCHECK(key->IsJSReceiver() || key->IsSymbol());
6524  Handle<EphemeronHashTable> table(
6525      EphemeronHashTable::cast(weak_collection->table()),
6526      weak_collection->GetIsolate());
6527  DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
6528  bool was_present = false;
6529  Handle<EphemeronHashTable> new_table = EphemeronHashTable::Remove(
6530      weak_collection->GetIsolate(), table, key, &was_present, hash);
6531  weak_collection->set_table(*new_table);
6532  if (*table != *new_table) {
6533    // Zap the old table since we didn't record slots for its elements.
6534    EphemeronHashTable::FillEntriesWithHoles(table);
6535  }
6536  return was_present;
6537}
6538
6539Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
6540                                             int max_entries) {
6541  Isolate* isolate = holder->GetIsolate();
6542  Handle<EphemeronHashTable> table(EphemeronHashTable::cast(holder->table()),
6543                                   isolate);
6544  if (max_entries == 0 || max_entries > table->NumberOfElements()) {
6545    max_entries = table->NumberOfElements();
6546  }
6547  int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
6548  Handle<FixedArray> entries =
6549      isolate->factory()->NewFixedArray(max_entries * values_per_entry);
6550  // Recompute max_values because GC could have removed elements from the table.
6551  if (max_entries > table->NumberOfElements()) {
6552    max_entries = table->NumberOfElements();
6553  }
6554
6555  {
6556    DisallowGarbageCollection no_gc;
6557    ReadOnlyRoots roots = ReadOnlyRoots(isolate);
6558    int count = 0;
6559    for (int i = 0;
6560         count / values_per_entry < max_entries && i < table->Capacity(); i++) {
6561      Object key;
6562      if (table->ToKey(roots, InternalIndex(i), &key)) {
6563        entries->set(count++, key);
6564        if (values_per_entry > 1) {
6565          Object value = table->Lookup(handle(key, isolate));
6566          entries->set(count++, value);
6567        }
6568      }
6569    }
6570    DCHECK_EQ(max_entries * values_per_entry, count);
6571  }
6572  return isolate->factory()->NewJSArrayWithElements(entries);
6573}
6574
6575void PropertyCell::ClearAndInvalidate(ReadOnlyRoots roots) {
6576  DCHECK(!value().IsTheHole(roots));
6577  PropertyDetails details = property_details();
6578  details = details.set_cell_type(PropertyCellType::kConstant);
6579  Transition(details, roots.the_hole_value_handle());
6580  // TODO(11527): pass Isolate as an argument.
6581  Isolate* isolate = GetIsolateFromWritableObject(*this);
6582  dependent_code().DeoptimizeDependentCodeGroup(
6583      isolate, DependentCode::kPropertyCellChangedGroup);
6584}
6585
6586// static
6587Handle<PropertyCell> PropertyCell::InvalidateAndReplaceEntry(
6588    Isolate* isolate, Handle<GlobalDictionary> dictionary, InternalIndex entry,
6589    PropertyDetails new_details, Handle<Object> new_value) {
6590  Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
6591  Handle<Name> name(cell->name(), isolate);
6592  DCHECK(cell->property_details().IsConfigurable());
6593  DCHECK(!cell->value().IsTheHole(isolate));
6594
6595  // Swap with a new property cell.
6596  Handle<PropertyCell> new_cell =
6597      isolate->factory()->NewPropertyCell(name, new_details, new_value);
6598  dictionary->ValueAtPut(entry, *new_cell);
6599
6600  cell->ClearAndInvalidate(ReadOnlyRoots(isolate));
6601  return new_cell;
6602}
6603
6604static bool RemainsConstantType(PropertyCell cell, Object value) {
6605  DisallowGarbageCollection no_gc;
6606  // TODO(dcarney): double->smi and smi->double transition from kConstant
6607  if (cell.value().IsSmi() && value.IsSmi()) {
6608    return true;
6609  } else if (cell.value().IsHeapObject() && value.IsHeapObject()) {
6610    Map map = HeapObject::cast(value).map();
6611    return HeapObject::cast(cell.value()).map() == map && map.is_stable();
6612  }
6613  return false;
6614}
6615
6616// static
6617PropertyCellType PropertyCell::InitialType(Isolate* isolate, Object value) {
6618  return value.IsUndefined(isolate) ? PropertyCellType::kUndefined
6619                                    : PropertyCellType::kConstant;
6620}
6621
6622// static
6623PropertyCellType PropertyCell::UpdatedType(Isolate* isolate, PropertyCell cell,
6624                                           Object value,
6625                                           PropertyDetails details) {
6626  DisallowGarbageCollection no_gc;
6627  DCHECK(!value.IsTheHole(isolate));
6628  DCHECK(!cell.value().IsTheHole(isolate));
6629  switch (details.cell_type()) {
6630    case PropertyCellType::kUndefined:
6631      return PropertyCellType::kConstant;
6632    case PropertyCellType::kConstant:
6633      if (value == cell.value()) return PropertyCellType::kConstant;
6634      V8_FALLTHROUGH;
6635    case PropertyCellType::kConstantType:
6636      if (RemainsConstantType(cell, value)) {
6637        return PropertyCellType::kConstantType;
6638      }
6639      V8_FALLTHROUGH;
6640    case PropertyCellType::kMutable:
6641      return PropertyCellType::kMutable;
6642    case PropertyCellType::kInTransition:
6643      UNREACHABLE();
6644  }
6645}
6646
6647Handle<PropertyCell> PropertyCell::PrepareForAndSetValue(
6648    Isolate* isolate, Handle<GlobalDictionary> dictionary, InternalIndex entry,
6649    Handle<Object> value, PropertyDetails details) {
6650  DCHECK(!value->IsTheHole(isolate));
6651  PropertyCell raw_cell = dictionary->CellAt(entry);
6652  CHECK(!raw_cell.value().IsTheHole(isolate));
6653  const PropertyDetails original_details = raw_cell.property_details();
6654  // Data accesses could be cached in ics or optimized code.
6655  bool invalidate = original_details.kind() == PropertyKind::kData &&
6656                    details.kind() == PropertyKind::kAccessor;
6657  int index = original_details.dictionary_index();
6658  DCHECK_LT(0, index);
6659  details = details.set_index(index);
6660
6661  PropertyCellType new_type =
6662      UpdatedType(isolate, raw_cell, *value, original_details);
6663  details = details.set_cell_type(new_type);
6664
6665  Handle<PropertyCell> cell(raw_cell, isolate);
6666
6667  if (invalidate) {
6668    cell = PropertyCell::InvalidateAndReplaceEntry(isolate, dictionary, entry,
6669                                                   details, value);
6670  } else {
6671    cell->Transition(details, value);
6672    // Deopt when transitioning from a constant type or when making a writable
6673    // property read-only. Making a read-only property writable again is not
6674    // interesting because Turbofan does not currently rely on read-only unless
6675    // the property is also configurable, in which case it will stay read-only
6676    // forever.
6677    if (original_details.cell_type() != new_type ||
6678        (!original_details.IsReadOnly() && details.IsReadOnly())) {
6679      cell->dependent_code().DeoptimizeDependentCodeGroup(
6680          isolate, DependentCode::kPropertyCellChangedGroup);
6681    }
6682  }
6683  return cell;
6684}
6685
6686// static
6687void PropertyCell::InvalidateProtector() {
6688  if (value() != Smi::FromInt(Protectors::kProtectorInvalid)) {
6689    DCHECK_EQ(value(), Smi::FromInt(Protectors::kProtectorValid));
6690    set_value(Smi::FromInt(Protectors::kProtectorInvalid), kReleaseStore);
6691    // TODO(11527): pass Isolate as an argument.
6692    Isolate* isolate = GetIsolateFromWritableObject(*this);
6693    dependent_code().DeoptimizeDependentCodeGroup(
6694        isolate, DependentCode::kPropertyCellChangedGroup);
6695  }
6696}
6697
6698// static
6699bool PropertyCell::CheckDataIsCompatible(PropertyDetails details,
6700                                         Object value) {
6701  DisallowGarbageCollection no_gc;
6702  PropertyCellType cell_type = details.cell_type();
6703  CHECK_NE(cell_type, PropertyCellType::kInTransition);
6704  if (value.IsTheHole()) {
6705    CHECK_EQ(cell_type, PropertyCellType::kConstant);
6706  } else {
6707    CHECK_EQ(value.IsAccessorInfo() || value.IsAccessorPair(),
6708             details.kind() == PropertyKind::kAccessor);
6709    DCHECK_IMPLIES(cell_type == PropertyCellType::kUndefined,
6710                   value.IsUndefined());
6711  }
6712  return true;
6713}
6714
6715#ifdef DEBUG
6716bool PropertyCell::CanTransitionTo(PropertyDetails new_details,
6717                                   Object new_value) const {
6718  // Extending the implementation of PropertyCells with additional states
6719  // and/or transitions likely requires changes to PropertyCellData::Serialize.
6720  DisallowGarbageCollection no_gc;
6721  DCHECK(CheckDataIsCompatible(new_details, new_value));
6722  switch (property_details().cell_type()) {
6723    case PropertyCellType::kUndefined:
6724      return new_details.cell_type() != PropertyCellType::kUndefined;
6725    case PropertyCellType::kConstant:
6726      return !value().IsTheHole() &&
6727             new_details.cell_type() != PropertyCellType::kUndefined;
6728    case PropertyCellType::kConstantType:
6729      return new_details.cell_type() == PropertyCellType::kConstantType ||
6730             new_details.cell_type() == PropertyCellType::kMutable ||
6731             (new_details.cell_type() == PropertyCellType::kConstant &&
6732              new_value.IsTheHole());
6733    case PropertyCellType::kMutable:
6734      return new_details.cell_type() == PropertyCellType::kMutable ||
6735             (new_details.cell_type() == PropertyCellType::kConstant &&
6736              new_value.IsTheHole());
6737    case PropertyCellType::kInTransition:
6738      UNREACHABLE();
6739  }
6740}
6741#endif  // DEBUG
6742
6743int JSGeneratorObject::source_position() const {
6744  CHECK(is_suspended());
6745  DCHECK(function().shared().HasBytecodeArray());
6746  Isolate* isolate = GetIsolate();
6747  DCHECK(
6748      function().shared().GetBytecodeArray(isolate).HasSourcePositionTable());
6749
6750  int code_offset = Smi::ToInt(input_or_debug_pos());
6751
6752  // The stored bytecode offset is relative to a different base than what
6753  // is used in the source position table, hence the subtraction.
6754  code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
6755  AbstractCode code =
6756      AbstractCode::cast(function().shared().GetBytecodeArray(isolate));
6757  return code.SourcePosition(code_offset);
6758}
6759
6760// static
6761AccessCheckInfo AccessCheckInfo::Get(Isolate* isolate,
6762                                     Handle<JSObject> receiver) {
6763  DisallowGarbageCollection no_gc;
6764  DCHECK(receiver->map().is_access_check_needed());
6765  Object maybe_constructor = receiver->map().GetConstructor();
6766  if (maybe_constructor.IsFunctionTemplateInfo()) {
6767    Object data_obj =
6768        FunctionTemplateInfo::cast(maybe_constructor).GetAccessCheckInfo();
6769    if (data_obj.IsUndefined(isolate)) return AccessCheckInfo();
6770    return AccessCheckInfo::cast(data_obj);
6771  }
6772  // Might happen for a detached context.
6773  if (!maybe_constructor.IsJSFunction()) return AccessCheckInfo();
6774  JSFunction constructor = JSFunction::cast(maybe_constructor);
6775  // Might happen for the debug context.
6776  if (!constructor.shared().IsApiFunction()) return AccessCheckInfo();
6777
6778  Object data_obj =
6779      constructor.shared().get_api_func_data().GetAccessCheckInfo();
6780  if (data_obj.IsUndefined(isolate)) return AccessCheckInfo();
6781
6782  return AccessCheckInfo::cast(data_obj);
6783}
6784
6785Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
6786  DisallowGarbageCollection no_gc;
6787  DisallowJavascriptExecution no_js(isolate);
6788
6789  int x_value = Smi::ToInt(x);
6790  int y_value = Smi::ToInt(y);
6791
6792  // If the integers are equal so are the string representations.
6793  if (x_value == y_value) return Smi::FromInt(0).ptr();
6794
6795  // If one of the integers is zero the normal integer order is the
6796  // same as the lexicographic order of the string representations.
6797  if (x_value == 0 || y_value == 0) {
6798    return Smi::FromInt(x_value < y_value ? -1 : 1).ptr();
6799  }
6800
6801  // If only one of the integers is negative the negative number is
6802  // smallest because the char code of '-' is less than the char code
6803  // of any digit.  Otherwise, we make both values positive.
6804
6805  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
6806  // architectures using 32-bit Smis.
6807  uint32_t x_scaled = x_value;
6808  uint32_t y_scaled = y_value;
6809  if (x_value < 0) {
6810    if (y_value >= 0) {
6811      return Smi::FromInt(-1).ptr();
6812    } else {
6813      y_scaled = base::NegateWithWraparound(y_value);
6814    }
6815    x_scaled = base::NegateWithWraparound(x_value);
6816  } else if (y_value < 0) {
6817    return Smi::FromInt(1).ptr();
6818  }
6819
6820  // clang-format off
6821  static const uint32_t kPowersOf10[] = {
6822      1,                 10,                100,         1000,
6823      10 * 1000,         100 * 1000,        1000 * 1000, 10 * 1000 * 1000,
6824      100 * 1000 * 1000, 1000 * 1000 * 1000};
6825  // clang-format on
6826
6827  // If the integers have the same number of decimal digits they can be
6828  // compared directly as the numeric order is the same as the
6829  // lexicographic order.  If one integer has fewer digits, it is scaled
6830  // by some power of 10 to have the same number of digits as the longer
6831  // integer.  If the scaled integers are equal it means the shorter
6832  // integer comes first in the lexicographic order.
6833
6834  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
6835  int x_log2 = 31 - base::bits::CountLeadingZeros(x_scaled);
6836  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
6837  x_log10 -= x_scaled < kPowersOf10[x_log10];
6838
6839  int y_log2 = 31 - base::bits::CountLeadingZeros(y_scaled);
6840  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
6841  y_log10 -= y_scaled < kPowersOf10[y_log10];
6842
6843  int tie = 0;
6844
6845  if (x_log10 < y_log10) {
6846    // X has fewer digits.  We would like to simply scale up X but that
6847    // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
6848    // be scaled up to 9_000_000_000. So we scale up by the next
6849    // smallest power and scale down Y to drop one digit. It is OK to
6850    // drop one digit from the longer integer since the final digit is
6851    // past the length of the shorter integer.
6852    x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
6853    y_scaled /= 10;
6854    tie = -1;
6855  } else if (y_log10 < x_log10) {
6856    y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
6857    x_scaled /= 10;
6858    tie = 1;
6859  }
6860
6861  if (x_scaled < y_scaled) return Smi::FromInt(-1).ptr();
6862  if (x_scaled > y_scaled) return Smi::FromInt(1).ptr();
6863  return Smi::FromInt(tie).ptr();
6864}
6865
6866// Force instantiation of template instances class.
6867// Please note this list is compiler dependent.
6868// Keep this at the end of this file
6869
6870#define EXTERN_DEFINE_HASH_TABLE(DERIVED, SHAPE)                            \
6871  template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)                  \
6872      HashTable<DERIVED, SHAPE>;                                            \
6873                                                                            \
6874  template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED>        \
6875  HashTable<DERIVED, SHAPE>::New(Isolate*, int, AllocationType,             \
6876                                 MinimumCapacity);                          \
6877  template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED>        \
6878  HashTable<DERIVED, SHAPE>::New(LocalIsolate*, int, AllocationType,        \
6879                                 MinimumCapacity);                          \
6880                                                                            \
6881  template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED>        \
6882  HashTable<DERIVED, SHAPE>::EnsureCapacity(Isolate*, Handle<DERIVED>, int, \
6883                                            AllocationType);                \
6884  template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Handle<DERIVED>        \
6885  HashTable<DERIVED, SHAPE>::EnsureCapacity(LocalIsolate*, Handle<DERIVED>, \
6886                                            int, AllocationType);
6887
6888#define EXTERN_DEFINE_OBJECT_BASE_HASH_TABLE(DERIVED, SHAPE) \
6889  EXTERN_DEFINE_HASH_TABLE(DERIVED, SHAPE)                   \
6890  template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)   \
6891      ObjectHashTableBase<DERIVED, SHAPE>;
6892
6893#define EXTERN_DEFINE_DICTIONARY(DERIVED, SHAPE)                               \
6894  EXTERN_DEFINE_HASH_TABLE(DERIVED, SHAPE)                                     \
6895  template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)                     \
6896      Dictionary<DERIVED, SHAPE>;                                              \
6897                                                                               \
6898  template V8_EXPORT_PRIVATE Handle<DERIVED> Dictionary<DERIVED, SHAPE>::Add(  \
6899      Isolate* isolate, Handle<DERIVED>, Key, Handle<Object>, PropertyDetails, \
6900      InternalIndex*);                                                         \
6901  template V8_EXPORT_PRIVATE Handle<DERIVED> Dictionary<DERIVED, SHAPE>::Add(  \
6902      LocalIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>,             \
6903      PropertyDetails, InternalIndex*);
6904
6905#define EXTERN_DEFINE_BASE_NAME_DICTIONARY(DERIVED, SHAPE)                     \
6906  EXTERN_DEFINE_DICTIONARY(DERIVED, SHAPE)                                     \
6907  template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)                     \
6908      BaseNameDictionary<DERIVED, SHAPE>;                                      \
6909                                                                               \
6910  template V8_EXPORT_PRIVATE Handle<DERIVED>                                   \
6911  BaseNameDictionary<DERIVED, SHAPE>::New(Isolate*, int, AllocationType,       \
6912                                          MinimumCapacity);                    \
6913  template V8_EXPORT_PRIVATE Handle<DERIVED>                                   \
6914  BaseNameDictionary<DERIVED, SHAPE>::New(LocalIsolate*, int, AllocationType,  \
6915                                          MinimumCapacity);                    \
6916                                                                               \
6917  template Handle<DERIVED>                                                     \
6918  BaseNameDictionary<DERIVED, SHAPE>::AddNoUpdateNextEnumerationIndex(         \
6919      Isolate* isolate, Handle<DERIVED>, Key, Handle<Object>, PropertyDetails, \
6920      InternalIndex*);                                                         \
6921  template Handle<DERIVED>                                                     \
6922  BaseNameDictionary<DERIVED, SHAPE>::AddNoUpdateNextEnumerationIndex(         \
6923      LocalIsolate* isolate, Handle<DERIVED>, Key, Handle<Object>,             \
6924      PropertyDetails, InternalIndex*);
6925
6926EXTERN_DEFINE_HASH_TABLE(StringSet, StringSetShape)
6927EXTERN_DEFINE_HASH_TABLE(CompilationCacheTable, CompilationCacheShape)
6928EXTERN_DEFINE_HASH_TABLE(ObjectHashSet, ObjectHashSetShape)
6929EXTERN_DEFINE_HASH_TABLE(NameToIndexHashTable, NameToIndexShape)
6930EXTERN_DEFINE_HASH_TABLE(RegisteredSymbolTable, RegisteredSymbolTableShape)
6931
6932EXTERN_DEFINE_OBJECT_BASE_HASH_TABLE(ObjectHashTable, ObjectHashTableShape)
6933EXTERN_DEFINE_OBJECT_BASE_HASH_TABLE(EphemeronHashTable, ObjectHashTableShape)
6934
6935EXTERN_DEFINE_DICTIONARY(SimpleNumberDictionary, SimpleNumberDictionaryShape)
6936EXTERN_DEFINE_DICTIONARY(NumberDictionary, NumberDictionaryShape)
6937
6938EXTERN_DEFINE_BASE_NAME_DICTIONARY(NameDictionary, NameDictionaryShape)
6939EXTERN_DEFINE_BASE_NAME_DICTIONARY(GlobalDictionary, GlobalDictionaryShape)
6940
6941#undef EXTERN_DEFINE_HASH_TABLE
6942#undef EXTERN_DEFINE_OBJECT_BASE_HASH_TABLE
6943#undef EXTERN_DEFINE_DICTIONARY
6944#undef EXTERN_DEFINE_BASE_NAME_DICTIONARY
6945
6946void JSFinalizationRegistry::RemoveCellFromUnregisterTokenMap(
6947    Isolate* isolate, Address raw_finalization_registry,
6948    Address raw_weak_cell) {
6949  DisallowGarbageCollection no_gc;
6950  JSFinalizationRegistry finalization_registry =
6951      JSFinalizationRegistry::cast(Object(raw_finalization_registry));
6952  WeakCell weak_cell = WeakCell::cast(Object(raw_weak_cell));
6953  DCHECK(!weak_cell.unregister_token().IsUndefined(isolate));
6954  HeapObject undefined = ReadOnlyRoots(isolate).undefined_value();
6955
6956  // Remove weak_cell from the linked list of other WeakCells with the same
6957  // unregister token and remove its unregister token from key_map if necessary
6958  // without shrinking it. Since shrinking may allocate, it is performed by the
6959  // caller after looping, or on exception.
6960  if (weak_cell.key_list_prev().IsUndefined(isolate)) {
6961    SimpleNumberDictionary key_map =
6962        SimpleNumberDictionary::cast(finalization_registry.key_map());
6963    HeapObject unregister_token = weak_cell.unregister_token();
6964    uint32_t key = Smi::ToInt(unregister_token.GetHash());
6965    InternalIndex entry = key_map.FindEntry(isolate, key);
6966    DCHECK(entry.is_found());
6967
6968    if (weak_cell.key_list_next().IsUndefined(isolate)) {
6969      // weak_cell is the only one associated with its key; remove the key
6970      // from the hash table.
6971      key_map.ClearEntry(entry);
6972      key_map.ElementRemoved();
6973    } else {
6974      // weak_cell is the list head for its key; we need to change the value
6975      // of the key in the hash table.
6976      WeakCell next = WeakCell::cast(weak_cell.key_list_next());
6977      DCHECK_EQ(next.key_list_prev(), weak_cell);
6978      next.set_key_list_prev(undefined);
6979      key_map.ValueAtPut(entry, next);
6980    }
6981  } else {
6982    // weak_cell is somewhere in the middle of its key list.
6983    WeakCell prev = WeakCell::cast(weak_cell.key_list_prev());
6984    prev.set_key_list_next(weak_cell.key_list_next());
6985    if (!weak_cell.key_list_next().IsUndefined()) {
6986      WeakCell next = WeakCell::cast(weak_cell.key_list_next());
6987      next.set_key_list_prev(weak_cell.key_list_prev());
6988    }
6989  }
6990
6991  // weak_cell is now removed from the unregister token map, so clear its
6992  // unregister token-related fields.
6993  weak_cell.set_unregister_token(undefined);
6994  weak_cell.set_key_list_prev(undefined);
6995  weak_cell.set_key_list_next(undefined);
6996}
6997
6998}  // namespace internal
6999}  // namespace v8
7000