5 #include "src/objects.h" 13 #include "src/objects-inl.h" 15 #include "src/accessors.h" 16 #include "src/allocation-site-scopes.h" 17 #include "src/api-arguments-inl.h" 18 #include "src/api-natives.h" 20 #include "src/arguments.h" 21 #include "src/ast/ast.h" 22 #include "src/ast/scopes.h" 23 #include "src/base/bits.h" 24 #include "src/base/utils/random-number-generator.h" 25 #include "src/bootstrapper.h" 26 #include "src/builtins/builtins.h" 27 #include "src/code-stubs.h" 28 #include "src/compiler.h" 29 #include "src/counters-inl.h" 30 #include "src/counters.h" 32 #include "src/debug/debug.h" 33 #include "src/deoptimizer.h" 34 #include "src/elements.h" 35 #include "src/execution.h" 36 #include "src/field-index-inl.h" 37 #include "src/field-index.h" 38 #include "src/field-type.h" 39 #include "src/frames-inl.h" 40 #include "src/globals.h" 41 #include "src/ic/ic.h" 42 #include "src/identity-map.h" 43 #include "src/interpreter/bytecode-array-iterator.h" 44 #include "src/interpreter/bytecode-decoder.h" 45 #include "src/interpreter/interpreter.h" 46 #include "src/isolate-inl.h" 49 #include "src/lookup-inl.h" 50 #include "src/macro-assembler.h" 51 #include "src/map-updater.h" 52 #include "src/message-template.h" 53 #include "src/objects-body-descriptors-inl.h" 54 #include "src/objects/api-callbacks.h" 55 #include "src/objects/arguments-inl.h" 56 #include "src/objects/bigint.h" 57 #include "src/objects/code-inl.h" 58 #include "src/objects/compilation-cache-inl.h" 59 #include "src/objects/debug-objects-inl.h" 60 #include "src/objects/frame-array-inl.h" 61 #include "src/objects/hash-table-inl.h" 62 #include "src/objects/js-array-inl.h" 63 #ifdef V8_INTL_SUPPORT 64 #include "src/objects/js-break-iterator.h" 65 #include "src/objects/js-collator.h" 66 #endif // V8_INTL_SUPPORT 67 #include "src/objects/js-collection-inl.h" 68 #ifdef V8_INTL_SUPPORT 69 #include "src/objects/js-date-time-format.h" 70 #endif // V8_INTL_SUPPORT 71 #include "src/objects/js-generator-inl.h" 72 #ifdef V8_INTL_SUPPORT 73 #include "src/objects/js-list-format.h" 74 #include "src/objects/js-locale.h" 75 #include "src/objects/js-number-format.h" 76 #include "src/objects/js-plural-rules.h" 77 #endif // V8_INTL_SUPPORT 78 #include "src/objects/js-regexp-inl.h" 79 #include "src/objects/js-regexp-string-iterator.h" 80 #ifdef V8_INTL_SUPPORT 81 #include "src/objects/js-relative-time-format.h" 82 #include "src/objects/js-segment-iterator.h" 83 #include "src/objects/js-segmenter.h" 84 #endif // V8_INTL_SUPPORT 85 #include "src/objects/js-weak-refs-inl.h" 86 #include "src/objects/literal-objects-inl.h" 87 #include "src/objects/map.h" 88 #include "src/objects/microtask-inl.h" 89 #include "src/objects/module-inl.h" 90 #include "src/objects/promise-inl.h" 91 #include "src/objects/slots-atomic-inl.h" 92 #include "src/objects/stack-frame-info-inl.h" 93 #include "src/parsing/preparsed-scope-data.h" 94 #include "src/property-descriptor.h" 95 #include "src/prototype.h" 96 #include "src/regexp/jsregexp.h" 97 #include "src/safepoint-table.h" 98 #include "src/snapshot/code-serializer.h" 99 #include "src/snapshot/snapshot.h" 100 #include "src/source-position-table.h" 101 #include "src/string-builder-inl.h" 102 #include "src/string-search.h" 103 #include "src/string-stream.h" 104 #include "src/unicode-decoder.h" 105 #include "src/unicode-inl.h" 106 #include "src/utils-inl.h" 107 #include "src/wasm/wasm-engine.h" 108 #include "src/wasm/wasm-objects.h" 109 #include "src/zone/zone.h" 111 #ifdef ENABLE_DISASSEMBLER 112 #include "src/disasm.h" 113 #include "src/disassembler.h" 114 #include "src/eh-frame.h" 120 bool ComparisonResultToBool(Operation op, ComparisonResult result) {
122 case Operation::kLessThan:
123 return result == ComparisonResult::kLessThan;
124 case Operation::kLessThanOrEqual:
125 return result == ComparisonResult::kLessThan ||
126 result == ComparisonResult::kEqual;
127 case Operation::kGreaterThan:
128 return result == ComparisonResult::kGreaterThan;
129 case Operation::kGreaterThanOrEqual:
130 return result == ComparisonResult::kGreaterThan ||
131 result == ComparisonResult::kEqual;
138 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
139 switch (instance_type) {
140 #define WRITE_TYPE(TYPE) \ 143 INSTANCE_TYPE_LIST(WRITE_TYPE)
149 Handle<FieldType> Object::OptimalType(Isolate* isolate,
150 Representation representation) {
151 if (representation.IsNone())
return FieldType::None(isolate);
152 if (FLAG_track_field_types) {
153 if (representation.IsHeapObject() && IsHeapObject()) {
155 Handle<Map> map(HeapObject::cast(
this)->map(), isolate);
156 if (map->is_stable() && map->IsJSReceiverMap()) {
157 return FieldType::Class(map, isolate);
161 return FieldType::Any(isolate);
164 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
165 Handle<Object>
object,
166 Handle<Context> native_context,
167 const char* method_name) {
168 if (object->IsJSReceiver())
return Handle<JSReceiver>::cast(
object);
169 Handle<JSFunction> constructor;
170 if (object->IsSmi()) {
171 constructor = handle(native_context->number_function(), isolate);
173 int constructor_function_index =
174 Handle<HeapObject>::cast(
object)->map()->GetConstructorFunctionIndex();
175 if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
176 if (method_name !=
nullptr) {
180 MessageTemplate::kCalledOnNullOrUndefined,
181 isolate->factory()->NewStringFromAsciiChecked(method_name)),
184 THROW_NEW_ERROR(isolate,
185 NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
188 constructor = handle(
189 JSFunction::cast(native_context->get(constructor_function_index)),
192 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
193 Handle<JSValue>::cast(result)->set_value(*
object);
199 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
200 Handle<Object>
object) {
201 if (object->IsJSReceiver())
return Handle<JSReceiver>::cast(
object);
202 if (object->IsNullOrUndefined(isolate)) {
203 return isolate->global_proxy();
205 return Object::ToObject(isolate,
object);
209 MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
210 Handle<Object> input,
213 if (input->IsNumber()) {
216 if (input->IsString()) {
217 return String::ToNumber(isolate, Handle<String>::cast(input));
219 if (input->IsOddball()) {
220 return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
222 if (input->IsSymbol()) {
223 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
226 if (input->IsBigInt()) {
227 if (mode == Conversion::kToNumeric)
return input;
228 DCHECK_EQ(mode, Conversion::kToNumber);
229 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
232 ASSIGN_RETURN_ON_EXCEPTION(
233 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
234 ToPrimitiveHint::kNumber),
240 MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
241 Handle<Object> input) {
242 ASSIGN_RETURN_ON_EXCEPTION(
244 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
245 if (input->IsSmi())
return input;
246 return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
250 MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
251 Handle<Object> input) {
252 ASSIGN_RETURN_ON_EXCEPTION(
254 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
255 if (input->IsSmi())
return input;
256 return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
260 MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
261 Handle<Object> input) {
262 ASSIGN_RETURN_ON_EXCEPTION(
264 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
265 if (input->IsSmi())
return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
266 return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
270 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
271 Handle<Object> input) {
272 ASSIGN_RETURN_ON_EXCEPTION(
273 isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
275 if (input->IsName())
return Handle<Name>::cast(input);
276 return ToString(isolate, input);
281 MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
282 Handle<Object> value) {
284 MaybeHandle<Object> maybe_key =
285 Object::ToPrimitive(value, ToPrimitiveHint::kString);
288 if (!maybe_key.ToHandle(&key))
return key;
290 if (key->IsSymbol())
return key;
293 if (key->IsSmi())
return key;
294 if (key->IsHeapNumber()) {
296 if (value->ToArrayLength(&uint_value) &&
297 uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
298 return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
301 return Object::ToString(isolate, key);
305 MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
306 Handle<Object> input) {
308 if (input->IsOddball()) {
309 return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
311 if (input->IsNumber()) {
312 return isolate->factory()->NumberToString(input);
314 if (input->IsSymbol()) {
315 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
318 if (input->IsBigInt()) {
319 return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
321 ASSIGN_RETURN_ON_EXCEPTION(
322 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
323 ToPrimitiveHint::kString),
327 if (input->IsString()) {
328 return Handle<String>::cast(input);
335 bool IsErrorObject(Isolate* isolate, Handle<Object>
object) {
336 if (!object->IsJSReceiver())
return false;
337 Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
338 return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(
object), symbol)
342 Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object>
object) {
343 return object->IsString() ? Handle<String>::cast(
object)
344 : isolate->factory()->empty_string();
347 Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
348 Handle<Object> input) {
349 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
351 Handle<Name> name_key = isolate->factory()->name_string();
352 Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
353 Handle<String> name_str = AsStringOrEmpty(isolate, name);
355 Handle<Name> msg_key = isolate->factory()->message_string();
356 Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
357 Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
359 if (name_str->length() == 0)
return msg_str;
360 if (msg_str->length() == 0)
return name_str;
362 IncrementalStringBuilder builder(isolate);
363 builder.AppendString(name_str);
364 builder.AppendCString(
": ");
365 builder.AppendString(msg_str);
367 return builder.Finish().ToHandleChecked();
373 Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
374 Handle<Object> input) {
375 DisallowJavascriptExecution no_js(isolate);
377 if (input->IsString() || input->IsNumber() || input->IsOddball()) {
378 return Object::ToString(isolate, input).ToHandleChecked();
379 }
else if (input->IsBigInt()) {
380 MaybeHandle<String> maybe_string =
381 BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
382 Handle<String> result;
383 if (maybe_string.ToHandle(&result))
return result;
386 return isolate->factory()->NewStringFromStaticChars(
387 "<a very large BigInt>");
388 }
else if (input->IsFunction()) {
390 Handle<String> fun_str;
391 if (input->IsJSBoundFunction()) {
392 fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
394 DCHECK(input->IsJSFunction());
395 fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
398 if (fun_str->length() > 128) {
399 IncrementalStringBuilder builder(isolate);
400 builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
401 builder.AppendCString(
"...<omitted>...");
402 builder.AppendString(isolate->factory()->NewSubString(
403 fun_str, fun_str->length() - 2, fun_str->length()));
405 return builder.Finish().ToHandleChecked();
408 }
else if (input->IsSymbol()) {
410 Handle<Symbol> symbol = Handle<Symbol>::cast(input);
412 IncrementalStringBuilder builder(isolate);
413 builder.AppendCString(
"Symbol(");
414 if (symbol->name()->IsString()) {
415 builder.AppendString(handle(String::cast(symbol->name()), isolate));
417 builder.AppendCharacter(
')');
419 return builder.Finish().ToHandleChecked();
420 }
else if (input->IsJSReceiver()) {
422 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
423 Handle<Object> to_string = JSReceiver::GetDataProperty(
424 receiver, isolate->factory()->toString_string());
426 if (IsErrorObject(isolate, input) ||
427 *to_string == *isolate->error_to_string()) {
431 return NoSideEffectsErrorToString(isolate, input);
432 }
else if (*to_string == *isolate->object_to_string()) {
433 Handle<Object> ctor = JSReceiver::GetDataProperty(
434 receiver, isolate->factory()->constructor_string());
435 if (ctor->IsFunction()) {
436 Handle<String> ctor_name;
437 if (ctor->IsJSBoundFunction()) {
438 ctor_name = JSBoundFunction::GetName(
439 isolate, Handle<JSBoundFunction>::cast(ctor))
441 }
else if (ctor->IsJSFunction()) {
442 Handle<Object> ctor_name_obj =
443 JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
444 ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
447 if (ctor_name->length() != 0) {
448 IncrementalStringBuilder builder(isolate);
449 builder.AppendCString(
"#<");
450 builder.AppendString(ctor_name);
451 builder.AppendCString(
">");
453 return builder.Finish().ToHandleChecked();
461 Handle<JSReceiver> receiver;
462 if (input->IsJSReceiver()) {
463 receiver = Handle<JSReceiver>::cast(input);
466 DCHECK(!input->IsSmi());
467 int constructor_function_index =
468 Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
469 if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
470 return isolate->factory()->NewStringFromAsciiChecked(
"[object Unknown]");
473 receiver = Object::ToObject(isolate, input, isolate->native_context())
477 Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
478 Handle<Object> tag_obj = JSReceiver::GetDataProperty(
479 receiver, isolate->factory()->to_string_tag_symbol());
481 tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
483 IncrementalStringBuilder builder(isolate);
484 builder.AppendCString(
"[object ");
485 builder.AppendString(tag);
486 builder.AppendCString(
"]");
488 return builder.Finish().ToHandleChecked();
492 MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
493 Handle<Object> input) {
494 ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
495 if (input->IsSmi()) {
496 int value = std::max(Smi::ToInt(*input), 0);
497 return handle(Smi::FromInt(value), isolate);
499 double len = DoubleToInteger(input->Number());
501 return handle(Smi::kZero, isolate);
502 }
else if (len >= kMaxSafeInteger) {
503 len = kMaxSafeInteger;
505 return isolate->factory()->NewNumber(len);
509 MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
510 Handle<Object> input,
511 MessageTemplate error_index) {
512 if (input->IsUndefined(isolate))
return handle(Smi::kZero, isolate);
513 ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
514 if (input->IsSmi() && Smi::ToInt(*input) >= 0)
return input;
515 double len = DoubleToInteger(input->Number()) + 0.0;
516 auto js_len = isolate->factory()->NewNumber(len);
517 if (len < 0.0 || len > kMaxSafeInteger) {
518 THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
523 bool Object::BooleanValue(Isolate* isolate) {
524 if (IsSmi())
return Smi::ToInt(
this) != 0;
525 DCHECK(IsHeapObject());
526 if (IsBoolean())
return IsTrue(isolate);
527 if (IsNullOrUndefined(isolate))
return false;
528 if (IsUndetectable())
return false;
529 if (IsString())
return String::cast(
this)->length() != 0;
530 if (IsHeapNumber())
return DoubleToBoolean(HeapNumber::cast(
this)->value());
531 if (IsBigInt())
return BigInt::cast(
this)->ToBoolean();
535 bool ObjectPtr::BooleanValue(Isolate* isolate) {
536 return reinterpret_cast<Object*
>(ptr())->BooleanValue(isolate);
543 ComparisonResult NumberCompare(
double x,
double y) {
544 if (std::isnan(x) || std::isnan(y)) {
545 return ComparisonResult::kUndefined;
547 return ComparisonResult::kLessThan;
549 return ComparisonResult::kGreaterThan;
551 return ComparisonResult::kEqual;
555 bool NumberEquals(
double x,
double y) {
557 if (std::isnan(x))
return false;
558 if (std::isnan(y))
return false;
562 bool NumberEquals(
const Object* x,
const Object* y) {
563 return NumberEquals(x->Number(), y->Number());
566 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
567 return NumberEquals(*x, *y);
570 ComparisonResult Reverse(ComparisonResult result) {
571 if (result == ComparisonResult::kLessThan) {
572 return ComparisonResult::kGreaterThan;
574 if (result == ComparisonResult::kGreaterThan) {
575 return ComparisonResult::kLessThan;
583 Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
586 if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
587 !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
588 return Nothing<ComparisonResult>();
590 if (x->IsString() && y->IsString()) {
592 return Just(String::Compare(isolate, Handle<String>::cast(x),
593 Handle<String>::cast(y)));
595 if (x->IsBigInt() && y->IsString()) {
596 return Just(BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
597 Handle<String>::cast(y)));
599 if (x->IsString() && y->IsBigInt()) {
600 return Just(Reverse(BigInt::CompareToString(
601 isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x))));
604 if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
605 !Object::ToNumeric(isolate, y).ToHandle(&y)) {
606 return Nothing<ComparisonResult>();
609 bool x_is_number = x->IsNumber();
610 bool y_is_number = y->IsNumber();
611 if (x_is_number && y_is_number) {
612 return Just(NumberCompare(x->Number(), y->Number()));
613 }
else if (!x_is_number && !y_is_number) {
614 return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
615 Handle<BigInt>::cast(y)));
616 }
else if (x_is_number) {
617 return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
619 return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
625 Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
632 return Just(NumberEquals(x, y));
633 }
else if (y->IsBoolean()) {
634 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
635 }
else if (y->IsString()) {
636 return Just(NumberEquals(
637 x, String::ToNumber(isolate, Handle<String>::cast(y))));
638 }
else if (y->IsBigInt()) {
639 return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
640 }
else if (y->IsJSReceiver()) {
641 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
643 return Nothing<bool>();
648 }
else if (x->IsString()) {
650 return Just(String::Equals(isolate, Handle<String>::cast(x),
651 Handle<String>::cast(y)));
652 }
else if (y->IsNumber()) {
653 x = String::ToNumber(isolate, Handle<String>::cast(x));
654 return Just(NumberEquals(x, y));
655 }
else if (y->IsBoolean()) {
656 x = String::ToNumber(isolate, Handle<String>::cast(x));
657 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
658 }
else if (y->IsBigInt()) {
659 return Just(BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
660 Handle<String>::cast(x)));
661 }
else if (y->IsJSReceiver()) {
662 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
664 return Nothing<bool>();
669 }
else if (x->IsBoolean()) {
670 if (y->IsOddball()) {
671 return Just(x.is_identical_to(y));
672 }
else if (y->IsNumber()) {
673 return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
674 }
else if (y->IsString()) {
675 y = String::ToNumber(isolate, Handle<String>::cast(y));
676 return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
677 }
else if (y->IsBigInt()) {
678 x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
679 return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
680 }
else if (y->IsJSReceiver()) {
681 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
683 return Nothing<bool>();
685 x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
689 }
else if (x->IsSymbol()) {
691 return Just(x.is_identical_to(y));
692 }
else if (y->IsJSReceiver()) {
693 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
695 return Nothing<bool>();
700 }
else if (x->IsBigInt()) {
702 return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
704 return Equals(isolate, y, x);
705 }
else if (x->IsJSReceiver()) {
706 if (y->IsJSReceiver()) {
707 return Just(x.is_identical_to(y));
708 }
else if (y->IsUndetectable()) {
709 return Just(x->IsUndetectable());
710 }
else if (y->IsBoolean()) {
711 y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
712 }
else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
714 return Nothing<bool>();
717 return Just(x->IsUndetectable() && y->IsUndetectable());
723 bool Object::StrictEquals(Object* that) {
724 if (this->IsNumber()) {
725 if (!that->IsNumber())
return false;
726 return NumberEquals(
this, that);
727 }
else if (this->IsString()) {
728 if (!that->IsString())
return false;
729 return String::cast(
this)->Equals(String::cast(that));
730 }
else if (this->IsBigInt()) {
731 if (!that->IsBigInt())
return false;
732 return BigInt::EqualToBigInt(BigInt::cast(
this), BigInt::cast(that));
739 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object>
object) {
740 if (object->IsNumber())
return isolate->factory()->number_string();
741 if (object->IsOddball())
742 return handle(Oddball::cast(*object)->type_of(), isolate);
743 if (object->IsUndetectable()) {
744 return isolate->factory()->undefined_string();
746 if (object->IsString())
return isolate->factory()->string_string();
747 if (object->IsSymbol())
return isolate->factory()->symbol_string();
748 if (object->IsBigInt())
return isolate->factory()->bigint_string();
749 if (object->IsCallable())
return isolate->factory()->function_string();
750 return isolate->factory()->object_string();
755 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
756 Handle<Object> rhs) {
757 if (lhs->IsNumber() && rhs->IsNumber()) {
758 return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
759 }
else if (lhs->IsString() && rhs->IsString()) {
760 return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
761 Handle<String>::cast(rhs));
763 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
764 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
765 if (lhs->IsString() || rhs->IsString()) {
766 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
768 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
770 return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
771 Handle<String>::cast(rhs));
773 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
775 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
777 return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
782 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
783 Handle<Object> callable,
784 Handle<Object>
object) {
786 if (!callable->IsCallable())
return isolate->factory()->false_value();
790 if (callable->IsJSBoundFunction()) {
791 Handle<Object> bound_callable(
792 Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
794 return Object::InstanceOf(isolate,
object, bound_callable);
798 if (!object->IsJSReceiver())
return isolate->factory()->false_value();
801 Handle<Object> prototype;
802 ASSIGN_RETURN_ON_EXCEPTION(
804 Object::GetProperty(isolate, callable,
805 isolate->factory()->prototype_string()),
807 if (!prototype->IsJSReceiver()) {
810 NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
815 Maybe<bool> result = JSReceiver::HasInPrototypeChain(
816 isolate, Handle<JSReceiver>::cast(
object), prototype);
817 if (result.IsNothing())
return MaybeHandle<Object>();
818 return isolate->factory()->ToBoolean(result.FromJust());
822 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object>
object,
823 Handle<Object> callable) {
825 if (!callable->IsJSReceiver()) {
826 THROW_NEW_ERROR(isolate,
827 NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
832 Handle<Object> inst_of_handler;
833 ASSIGN_RETURN_ON_EXCEPTION(
834 isolate, inst_of_handler,
835 JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
836 isolate->factory()->has_instance_symbol()),
838 if (!inst_of_handler->IsUndefined(isolate)) {
840 Handle<Object> result;
841 ASSIGN_RETURN_ON_EXCEPTION(
843 Execution::Call(isolate, inst_of_handler, callable, 1, &
object),
845 return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
849 if (!callable->IsCallable()) {
851 isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
856 Handle<Object> result;
857 ASSIGN_RETURN_ON_EXCEPTION(
859 JSReceiver::OrdinaryHasInstance(isolate, callable,
object), Object);
864 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
867 Isolate* isolate = receiver->GetIsolate();
868 ASSIGN_RETURN_ON_EXCEPTION(
869 isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
870 if (func->IsNullOrUndefined(isolate)) {
871 return isolate->factory()->undefined_value();
873 if (!func->IsCallable()) {
874 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
875 func, name, receiver),
883 MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
884 Isolate* isolate, Handle<Object>
object, ElementTypes element_types) {
885 if (element_types == ElementTypes::kAll) {
886 if (object->IsJSArray()) {
887 Handle<JSArray> array = Handle<JSArray>::cast(
object);
889 if (!array->HasArrayPrototype(isolate) ||
890 !array->length()->ToUint32(&length) || !array->HasFastElements() ||
891 !JSObject::PrototypeHasNoElements(isolate, *array)) {
892 return MaybeHandle<FixedArray>();
894 return array->GetElementsAccessor()->CreateListFromArrayLike(
895 isolate, array, length);
896 }
else if (object->IsJSTypedArray()) {
897 Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(
object);
898 size_t length = array->length_value();
899 if (array->WasNeutered() ||
900 length >
static_cast<size_t>(FixedArray::kMaxLength)) {
901 return MaybeHandle<FixedArray>();
903 return array->GetElementsAccessor()->CreateListFromArrayLike(
904 isolate, array, static_cast<uint32_t>(length));
907 return MaybeHandle<FixedArray>();
913 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
914 Isolate* isolate, Handle<Object>
object, ElementTypes element_types) {
916 MaybeHandle<FixedArray> fast_result =
917 CreateListFromArrayLikeFastPath(isolate,
object, element_types);
918 if (!fast_result.is_null())
return fast_result;
922 if (!object->IsJSReceiver()) {
923 THROW_NEW_ERROR(isolate,
924 NewTypeError(MessageTemplate::kCalledOnNonObject,
925 isolate->factory()->NewStringFromAsciiChecked(
926 "CreateListFromArrayLike")),
931 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(
object);
932 Handle<Object> raw_length_number;
933 ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
934 Object::GetLengthFromArrayLike(isolate, receiver),
937 if (!raw_length_number->ToUint32(&len) ||
938 len >
static_cast<uint32_t>(FixedArray::kMaxLength)) {
939 THROW_NEW_ERROR(isolate,
940 NewRangeError(MessageTemplate::kInvalidArrayLength),
944 Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
947 for (
uint32_t index = 0; index < len; ++index) {
951 ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
952 JSReceiver::GetElement(isolate, receiver, index),
954 switch (element_types) {
955 case ElementTypes::kAll:
958 case ElementTypes::kStringAndSymbol: {
961 if (!next->IsName()) {
962 THROW_NEW_ERROR(isolate,
963 NewTypeError(MessageTemplate::kNotPropertyName, next),
968 next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
972 list->set(index, *next);
981 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
982 Handle<JSReceiver>
object) {
984 Handle<Name> key = isolate->factory()->length_string();
985 ASSIGN_RETURN_ON_EXCEPTION(
986 isolate, val, JSReceiver::GetProperty(isolate,
object, key), Object);
987 return Object::ToLength(isolate, val);
991 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
992 for (; it->IsFound(); it->Next()) {
993 switch (it->state()) {
994 case LookupIterator::NOT_FOUND:
995 case LookupIterator::TRANSITION:
997 case LookupIterator::JSPROXY:
998 return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
1000 case LookupIterator::INTERCEPTOR: {
1001 Maybe<PropertyAttributes> result =
1002 JSObject::GetPropertyAttributesWithInterceptor(it);
1003 if (result.IsNothing())
return Nothing<bool>();
1004 if (result.FromJust() != ABSENT)
return Just(
true);
1007 case LookupIterator::ACCESS_CHECK: {
1008 if (it->HasAccess())
break;
1009 Maybe<PropertyAttributes> result =
1010 JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
1011 if (result.IsNothing())
return Nothing<bool>();
1012 return Just(result.FromJust() != ABSENT);
1014 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1017 case LookupIterator::ACCESSOR:
1018 case LookupIterator::DATA:
1026 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver>
object,
1027 Handle<Name> name) {
1028 if (object->IsJSModuleNamespace()) {
1029 PropertyDescriptor desc;
1030 return JSReceiver::GetOwnPropertyDescriptor(object->GetIsolate(), object,
1034 if (object->IsJSObject()) {
1035 LookupIterator it = LookupIterator::PropertyOrElement(
1036 object->GetIsolate(), object, name, object, LookupIterator::OWN);
1037 return HasProperty(&it);
1040 Maybe<PropertyAttributes> attributes =
1041 JSReceiver::GetOwnPropertyAttributes(
object, name);
1042 MAYBE_RETURN(attributes, Nothing<bool>());
1043 return Just(attributes.FromJust() != ABSENT);
1047 MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
1048 OnNonExistent on_non_existent) {
1049 for (; it->IsFound(); it->Next()) {
1050 switch (it->state()) {
1051 case LookupIterator::NOT_FOUND:
1052 case LookupIterator::TRANSITION:
1054 case LookupIterator::JSPROXY: {
1056 MaybeHandle<Object> result =
1057 JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
1058 it->GetName(), it->GetReceiver(), &was_found);
1059 if (!was_found) it->NotFound();
1062 case LookupIterator::INTERCEPTOR: {
1064 Handle<Object> result;
1065 ASSIGN_RETURN_ON_EXCEPTION(
1066 it->isolate(), result,
1067 JSObject::GetPropertyWithInterceptor(it, &done), Object);
1068 if (done)
return result;
1071 case LookupIterator::ACCESS_CHECK:
1072 if (it->HasAccess())
break;
1073 return JSObject::GetPropertyWithFailedAccessCheck(it);
1074 case LookupIterator::ACCESSOR:
1075 return GetPropertyWithAccessor(it);
1076 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1077 return it->isolate()->factory()->undefined_value();
1078 case LookupIterator::DATA:
1079 return it->GetDataValue();
1083 if (on_non_existent == OnNonExistent::kThrowReferenceError) {
1084 THROW_NEW_ERROR(it->isolate(),
1085 NewReferenceError(MessageTemplate::kNotDefined, it->name()),
1088 return it->isolate()->factory()->undefined_value();
1093 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
1094 Handle<JSProxy> proxy,
1096 Handle<Object> receiver,
1100 DCHECK(!name->IsPrivate());
1101 STACK_CHECK(isolate, MaybeHandle<Object>());
1102 Handle<Name> trap_name = isolate->factory()->get_string();
1105 Handle<Object> handler(proxy->handler(), isolate);
1108 if (proxy->IsRevoked()) {
1109 THROW_NEW_ERROR(isolate,
1110 NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1114 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1116 Handle<Object> trap;
1117 ASSIGN_RETURN_ON_EXCEPTION(
1119 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
1121 if (trap->IsUndefined(isolate)) {
1124 LookupIterator::PropertyOrElement(isolate, receiver, name, target);
1125 MaybeHandle<Object> result = Object::GetProperty(&it);
1126 *was_found = it.IsFound();
1130 Handle<Object> trap_result;
1131 Handle<Object> args[] = {target, name, receiver};
1132 ASSIGN_RETURN_ON_EXCEPTION(
1133 isolate, trap_result,
1134 Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
1136 MaybeHandle<Object> result =
1137 JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
1138 if (result.is_null()) {
1147 MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
1149 Handle<JSReceiver> target,
1150 Handle<Object> trap_result,
1151 AccessKind access_kind) {
1153 PropertyDescriptor target_desc;
1154 Maybe<bool> target_found =
1155 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
1156 MAYBE_RETURN_NULL(target_found);
1158 if (target_found.FromJust()) {
1163 bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
1164 !target_desc.configurable() &&
1165 !target_desc.writable() &&
1166 !trap_result->SameValue(*target_desc.value());
1168 if (access_kind == kGet) {
1171 NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
1172 target_desc.value(), trap_result),
1175 isolate->Throw(*isolate->factory()->NewTypeError(
1176 MessageTemplate::kProxySetFrozenData, name));
1177 return MaybeHandle<Object>();
1183 if (access_kind == kGet) {
1184 inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1185 !target_desc.configurable() &&
1186 target_desc.get()->IsUndefined(isolate) &&
1187 !trap_result->IsUndefined(isolate);
1189 inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1190 !target_desc.configurable() &&
1191 target_desc.set()->IsUndefined(isolate);
1194 if (access_kind == kGet) {
1197 NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
1201 isolate->Throw(*isolate->factory()->NewTypeError(
1202 MessageTemplate::kProxySetFrozenAccessor, name));
1203 return MaybeHandle<Object>();
1207 return isolate->factory()->undefined_value();
1211 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
1212 for (; it->IsFound(); it->Next()) {
1213 switch (it->state()) {
1214 case LookupIterator::INTERCEPTOR:
1215 case LookupIterator::NOT_FOUND:
1216 case LookupIterator::TRANSITION:
1218 case LookupIterator::ACCESS_CHECK:
1221 if (!it->isolate()->context().is_null() && it->HasAccess())
continue;
1223 case LookupIterator::JSPROXY:
1225 return it->isolate()->factory()->undefined_value();
1226 case LookupIterator::ACCESSOR:
1230 return it->isolate()->factory()->undefined_value();
1231 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1232 return it->isolate()->factory()->undefined_value();
1233 case LookupIterator::DATA:
1234 return it->GetDataValue();
1237 return it->isolate()->factory()->undefined_value();
1241 bool Object::ToInt32(int32_t* value) {
1243 *value = Smi::ToInt(
this);
1246 if (IsHeapNumber()) {
1247 double num = HeapNumber::cast(
this)->value();
1249 if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1250 *value = FastD2I(num);
1259 constexpr ObjectPtr Smi::kZero;
1260 constexpr ObjectPtr SharedFunctionInfo::kNoSharedNameSentinel;
1262 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
1263 Isolate* isolate, Handle<FunctionTemplateInfo> info,
1264 MaybeHandle<Name> maybe_name) {
1265 Object* current_info = info->shared_function_info();
1266 if (current_info->IsSharedFunctionInfo()) {
1267 return handle(SharedFunctionInfo::cast(current_info), isolate);
1270 Handle<String> name_string;
1271 if (maybe_name.ToHandle(&name) && name->IsString()) {
1272 name_string = Handle<String>::cast(name);
1273 }
else if (info->class_name()->IsString()) {
1274 name_string = handle(String::cast(info->class_name()), isolate);
1276 name_string = isolate->factory()->empty_string();
1278 FunctionKind function_kind;
1279 if (info->remove_prototype()) {
1280 function_kind = kConciseMethod;
1282 function_kind = kNormalFunction;
1284 Handle<SharedFunctionInfo> result =
1285 isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info,
1288 result->set_length(info->length());
1289 result->DontAdaptArguments();
1290 DCHECK(result->IsApiFunction());
1292 info->set_shared_function_info(*result);
1296 bool FunctionTemplateInfo::IsTemplateFor(Map map) {
1298 if (!map->IsJSObjectMap())
return false;
1300 Object* cons_obj = map->GetConstructor();
1302 if (cons_obj->IsJSFunction()) {
1303 JSFunction* fun = JSFunction::cast(cons_obj);
1304 type = fun->shared()->function_data();
1305 }
else if (cons_obj->IsFunctionTemplateInfo()) {
1306 type = FunctionTemplateInfo::cast(cons_obj);
1312 while (type->IsFunctionTemplateInfo()) {
1313 if (type ==
this)
return true;
1314 type = FunctionTemplateInfo::cast(type)->GetParentTemplate();
1321 FunctionTemplateRareData*
1322 FunctionTemplateInfo::AllocateFunctionTemplateRareData(
1323 Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
1324 DCHECK(function_template_info->rare_data()->IsUndefined(isolate));
1325 Handle<Struct> struct_obj =
1326 isolate->factory()->NewStruct(FUNCTION_TEMPLATE_RARE_DATA_TYPE, TENURED);
1327 Handle<FunctionTemplateRareData> rare_data =
1329 function_template_info->set_rare_data(*rare_data);
1334 Handle<TemplateList> TemplateList::New(Isolate* isolate,
int size) {
1335 Handle<FixedArray> list =
1336 isolate->factory()->NewFixedArray(kLengthIndex + size);
1337 list->set(kLengthIndex, Smi::kZero);
1338 return Handle<TemplateList>::cast(list);
1342 Handle<TemplateList> TemplateList::Add(Isolate* isolate,
1343 Handle<TemplateList> list,
1344 Handle<i::Object> value) {
1345 STATIC_ASSERT(kFirstElementIndex == 1);
1346 int index = list->length() + 1;
1347 Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
1348 fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
1349 fixed_array->set(kLengthIndex, Smi::FromInt(index));
1350 return Handle<TemplateList>::cast(fixed_array);
1354 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
1355 Handle<JSReceiver> new_target,
1356 Handle<AllocationSite> site) {
1362 Isolate*
const isolate = constructor->GetIsolate();
1363 DCHECK(constructor->IsConstructor());
1364 DCHECK(new_target->IsConstructor());
1365 DCHECK(!constructor->has_initial_map() ||
1366 constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
1368 Handle<Map> initial_map;
1369 ASSIGN_RETURN_ON_EXCEPTION(
1370 isolate, initial_map,
1371 JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
1372 Handle<JSObject> result =
1373 isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
1374 if (initial_map->is_dictionary_map()) {
1375 Handle<NameDictionary> dictionary =
1376 NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
1377 result->SetProperties(*dictionary);
1379 isolate->counters()->constructed_objects()->Increment();
1380 isolate->counters()->constructed_objects_runtime()->Increment();
1386 MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,
1387 Handle<Object> prototype) {
1393 Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
1396 Handle<JSObject> object;
1397 if (map->is_dictionary_map()) {
1398 object = isolate->factory()->NewSlowJSObjectFromMap(map);
1400 object = isolate->factory()->NewJSObjectFromMap(map);
1405 void JSObject::EnsureWritableFastElements(Handle<JSObject>
object) {
1406 DCHECK(object->HasSmiOrObjectElements() ||
1407 object->HasFastStringWrapperElements());
1408 FixedArray raw_elems = FixedArray::cast(object->elements());
1409 Heap* heap =
object->GetHeap();
1410 if (raw_elems->map() != ReadOnlyRoots(heap).fixed_cow_array_map())
return;
1411 Isolate* isolate = heap->isolate();
1412 Handle<FixedArray> elems(raw_elems, isolate);
1413 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
1414 elems, isolate->factory()->fixed_array_map());
1415 object->set_elements(*writable_elems);
1416 isolate->counters()->cow_arrays_converted()->Increment();
1419 int JSObject::GetHeaderSize(InstanceType type,
1420 bool function_has_prototype_slot) {
1422 case JS_OBJECT_TYPE:
1423 case JS_API_OBJECT_TYPE:
1424 case JS_SPECIAL_API_OBJECT_TYPE:
1425 return JSObject::kHeaderSize;
1426 case JS_GENERATOR_OBJECT_TYPE:
1427 return JSGeneratorObject::kSize;
1428 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
1429 return JSAsyncFunctionObject::kSize;
1430 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
1431 return JSAsyncGeneratorObject::kSize;
1432 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
1433 return JSAsyncFromSyncIterator::kSize;
1434 case JS_GLOBAL_PROXY_TYPE:
1435 return JSGlobalProxy::kSize;
1436 case JS_GLOBAL_OBJECT_TYPE:
1437 return JSGlobalObject::kSize;
1438 case JS_BOUND_FUNCTION_TYPE:
1439 return JSBoundFunction::kSize;
1440 case JS_FUNCTION_TYPE:
1441 return JSFunction::GetHeaderSize(function_has_prototype_slot);
1443 return JSValue::kSize;
1445 return JSDate::kSize;
1447 return JSArray::kSize;
1448 case JS_ARRAY_BUFFER_TYPE:
1449 return JSArrayBuffer::kHeaderSize;
1450 case JS_ARRAY_ITERATOR_TYPE:
1451 return JSArrayIterator::kSize;
1452 case JS_TYPED_ARRAY_TYPE:
1453 return JSTypedArray::kHeaderSize;
1454 case JS_DATA_VIEW_TYPE:
1455 return JSDataView::kHeaderSize;
1457 return JSSet::kSize;
1459 return JSMap::kSize;
1460 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
1461 case JS_SET_VALUE_ITERATOR_TYPE:
1462 return JSSetIterator::kSize;
1463 case JS_MAP_KEY_ITERATOR_TYPE:
1464 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
1465 case JS_MAP_VALUE_ITERATOR_TYPE:
1466 return JSMapIterator::kSize;
1467 case JS_WEAK_CELL_TYPE:
1468 return JSWeakCell::kSize;
1469 case JS_WEAK_FACTORY_TYPE:
1470 return JSWeakFactory::kSize;
1471 case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
1472 return JSWeakFactoryCleanupIterator::kSize;
1473 case JS_WEAK_MAP_TYPE:
1474 return JSWeakMap::kSize;
1475 case JS_WEAK_SET_TYPE:
1476 return JSWeakSet::kSize;
1477 case JS_PROMISE_TYPE:
1478 return JSPromise::kSize;
1479 case JS_REGEXP_TYPE:
1480 return JSRegExp::kSize;
1481 case JS_REGEXP_STRING_ITERATOR_TYPE:
1482 return JSRegExpStringIterator::kSize;
1483 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1484 return JSObject::kHeaderSize;
1485 case JS_MESSAGE_OBJECT_TYPE:
1486 return JSMessageObject::kSize;
1487 case JS_ARGUMENTS_TYPE:
1488 return JSObject::kHeaderSize;
1490 return JSObject::kHeaderSize;
1491 case JS_STRING_ITERATOR_TYPE:
1492 return JSStringIterator::kSize;
1493 case JS_MODULE_NAMESPACE_TYPE:
1494 return JSModuleNamespace::kHeaderSize;
1495 #ifdef V8_INTL_SUPPORT 1496 case JS_INTL_V8_BREAK_ITERATOR_TYPE:
1497 return JSV8BreakIterator::kSize;
1498 case JS_INTL_COLLATOR_TYPE:
1499 return JSCollator::kSize;
1500 case JS_INTL_DATE_TIME_FORMAT_TYPE:
1501 return JSDateTimeFormat::kSize;
1502 case JS_INTL_LIST_FORMAT_TYPE:
1503 return JSListFormat::kSize;
1504 case JS_INTL_LOCALE_TYPE:
1505 return JSLocale::kSize;
1506 case JS_INTL_NUMBER_FORMAT_TYPE:
1507 return JSNumberFormat::kSize;
1508 case JS_INTL_PLURAL_RULES_TYPE:
1509 return JSPluralRules::kSize;
1510 case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
1511 return JSRelativeTimeFormat::kSize;
1512 case JS_INTL_SEGMENT_ITERATOR_TYPE:
1513 return JSSegmentIterator::kSize;
1514 case JS_INTL_SEGMENTER_TYPE:
1515 return JSSegmenter::kSize;
1516 #endif // V8_INTL_SUPPORT 1517 case WASM_GLOBAL_TYPE:
1518 return WasmGlobalObject::kSize;
1519 case WASM_INSTANCE_TYPE:
1520 return WasmInstanceObject::kSize;
1521 case WASM_MEMORY_TYPE:
1522 return WasmMemoryObject::kSize;
1523 case WASM_MODULE_TYPE:
1524 return WasmModuleObject::kSize;
1525 case WASM_TABLE_TYPE:
1526 return WasmTableObject::kSize;
1527 case WASM_EXCEPTION_TYPE:
1528 return WasmExceptionObject::kSize;
1536 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1537 Isolate* isolate = proxy->GetIsolate();
1538 Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1540 STACK_CHECK(isolate, MaybeHandle<Object>());
1546 if (proxy->IsRevoked()) {
1547 THROW_NEW_ERROR(isolate,
1548 NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1551 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1552 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1555 Handle<Object> trap;
1556 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
1559 if (trap->IsUndefined(isolate)) {
1560 return JSReceiver::GetPrototype(isolate, target);
1563 Handle<Object> argv[] = {target};
1564 Handle<Object> handler_proto;
1565 ASSIGN_RETURN_ON_EXCEPTION(
1566 isolate, handler_proto,
1567 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
1569 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1570 THROW_NEW_ERROR(isolate,
1571 NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1575 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1576 MAYBE_RETURN_NULL(is_extensible);
1578 if (is_extensible.FromJust())
return handler_proto;
1580 Handle<Object> target_proto;
1581 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1582 JSReceiver::GetPrototype(isolate, target), Object);
1584 if (!handler_proto->SameValue(*target_proto)) {
1587 NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1591 return handler_proto;
1594 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1595 Isolate* isolate = it->isolate();
1596 Handle<Object> structure = it->GetAccessors();
1597 Handle<Object> receiver = it->GetReceiver();
1600 if (receiver->IsJSGlobalObject()) {
1601 receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1606 DCHECK(!structure->IsForeign());
1609 Handle<JSObject> holder = it->GetHolder<JSObject>();
1610 if (structure->IsAccessorInfo()) {
1611 Handle<Name> name = it->GetName();
1612 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1613 if (!info->IsCompatibleReceiver(*receiver)) {
1614 THROW_NEW_ERROR(isolate,
1615 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1620 if (!info->has_getter())
return isolate->factory()->undefined_value();
1622 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1623 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1624 Object::ConvertReceiver(isolate, receiver),
1628 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1630 Handle<Object> result = args.CallAccessorGetter(info, name);
1631 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1632 if (result.is_null())
return isolate->factory()->undefined_value();
1633 Handle<Object> reboxed_result = handle(*result, isolate);
1634 if (info->replace_on_access() && receiver->IsJSReceiver()) {
1635 RETURN_ON_EXCEPTION(isolate,
1636 Accessors::ReplaceAccessorWithDataProperty(
1637 receiver, holder, name, result),
1640 return reboxed_result;
1644 if (it->TryLookupCachedProperty()) {
1645 return Object::GetProperty(it);
1649 Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1650 if (getter->IsFunctionTemplateInfo()) {
1651 SaveContext save(isolate);
1652 isolate->set_context(*holder->GetCreationContext());
1653 return Builtins::InvokeApiFunction(
1654 isolate,
false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1655 nullptr, isolate->factory()->undefined_value());
1656 }
else if (getter->IsCallable()) {
1658 return Object::GetPropertyWithDefinedGetter(
1659 receiver, Handle<JSReceiver>::cast(getter));
1662 return isolate->factory()->undefined_value();
1666 Address AccessorInfo::redirect(Address address, AccessorComponent component) {
1667 ApiFunction fun(address);
1668 DCHECK_EQ(ACCESSOR_GETTER, component);
1669 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1670 return ExternalReference::Create(&fun, type).address();
1673 Address AccessorInfo::redirected_getter()
const {
1674 Address accessor = v8::ToCData<Address>(getter());
1675 if (accessor == kNullAddress)
return kNullAddress;
1676 return redirect(accessor, ACCESSOR_GETTER);
1679 Address CallHandlerInfo::redirected_callback()
const {
1680 Address address = v8::ToCData<Address>(callback());
1681 ApiFunction fun(address);
1682 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
1683 return ExternalReference::Create(&fun, type).address();
1686 bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
1688 if (!info->HasExpectedReceiverType())
return true;
1689 if (!map->IsJSObjectMap())
return false;
1690 return FunctionTemplateInfo::cast(info->expected_receiver_type())
1691 ->IsTemplateFor(*map);
1694 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
1695 Handle<Object> value,
1696 ShouldThrow should_throw) {
1697 Isolate* isolate = it->isolate();
1698 Handle<Object> structure = it->GetAccessors();
1699 Handle<Object> receiver = it->GetReceiver();
1702 if (receiver->IsJSGlobalObject()) {
1703 receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1708 DCHECK(!structure->IsForeign());
1711 Handle<JSObject> holder = it->GetHolder<JSObject>();
1712 if (structure->IsAccessorInfo()) {
1713 Handle<Name> name = it->GetName();
1714 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1715 if (!info->IsCompatibleReceiver(*receiver)) {
1716 isolate->Throw(*isolate->factory()->NewTypeError(
1717 MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1718 return Nothing<bool>();
1721 if (!info->has_setter()) {
1728 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1729 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1730 isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1740 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1742 Handle<Object> result = args.CallAccessorSetter(info, name, value);
1747 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1748 if (result.is_null())
return Just(
true);
1749 DCHECK(result->BooleanValue(isolate) || should_throw == kDontThrow);
1750 return Just(result->BooleanValue(isolate));
1754 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1755 if (setter->IsFunctionTemplateInfo()) {
1756 SaveContext save(isolate);
1757 isolate->set_context(*holder->GetCreationContext());
1758 Handle<Object> argv[] = {value};
1759 RETURN_ON_EXCEPTION_VALUE(
1760 isolate, Builtins::InvokeApiFunction(
1761 isolate,
false, Handle<FunctionTemplateInfo>::cast(setter),
1762 receiver, arraysize(argv), argv,
1763 isolate->factory()->undefined_value()),
1766 }
else if (setter->IsCallable()) {
1768 return SetPropertyWithDefinedSetter(
1769 receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
1772 RETURN_FAILURE(isolate, should_throw,
1773 NewTypeError(MessageTemplate::kNoSetterInCallback,
1774 it->GetName(), it->GetHolder<JSObject>()));
1778 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1779 Handle<Object> receiver,
1780 Handle<JSReceiver> getter) {
1781 Isolate* isolate = getter->GetIsolate();
1791 StackLimitCheck check(isolate);
1792 if (check.JsHasOverflowed()) {
1793 isolate->StackOverflow();
1794 return MaybeHandle<Object>();
1797 return Execution::Call(isolate, getter, receiver, 0,
nullptr);
1801 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
1802 Handle<JSReceiver> setter,
1803 Handle<Object> value,
1804 ShouldThrow should_throw) {
1805 Isolate* isolate = setter->GetIsolate();
1807 Handle<Object> argv[] = { value };
1808 RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1809 arraysize(argv), argv),
1816 bool JSObject::AllCanRead(LookupIterator* it) {
1819 DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
1820 it->state() == LookupIterator::INTERCEPTOR);
1821 for (it->Next(); it->IsFound(); it->Next()) {
1822 if (it->state() == LookupIterator::ACCESSOR) {
1823 auto accessors = it->GetAccessors();
1824 if (accessors->IsAccessorInfo()) {
1825 if (AccessorInfo::cast(*accessors)->all_can_read())
return true;
1827 }
else if (it->state() == LookupIterator::INTERCEPTOR) {
1828 if (it->GetInterceptor()->all_can_read())
return true;
1829 }
else if (it->state() == LookupIterator::JSPROXY) {
1839 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
1840 LookupIterator* it, Handle<InterceptorInfo> interceptor,
bool* done) {
1842 Isolate* isolate = it->isolate();
1845 AssertNoContextChange ncc(isolate);
1847 if (interceptor->getter()->IsUndefined(isolate)) {
1848 return isolate->factory()->undefined_value();
1851 Handle<JSObject> holder = it->GetHolder<JSObject>();
1852 Handle<Object> result;
1853 Handle<Object> receiver = it->GetReceiver();
1854 if (!receiver->IsJSReceiver()) {
1855 ASSIGN_RETURN_ON_EXCEPTION(
1856 isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
1858 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1859 *holder, kDontThrow);
1861 if (it->IsElement()) {
1862 result = args.CallIndexedGetter(interceptor, it->index());
1864 result = args.CallNamedGetter(interceptor, it->name());
1867 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1868 if (result.is_null())
return isolate->factory()->undefined_value();
1871 return handle(*result, isolate);
1874 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
1875 LookupIterator* it, Handle<InterceptorInfo> interceptor) {
1876 Isolate* isolate = it->isolate();
1879 AssertNoContextChange ncc(isolate);
1880 HandleScope scope(isolate);
1882 Handle<JSObject> holder = it->GetHolder<JSObject>();
1883 DCHECK_IMPLIES(!it->IsElement() && it->name()->IsSymbol(),
1884 interceptor->can_intercept_symbols());
1885 Handle<Object> receiver = it->GetReceiver();
1886 if (!receiver->IsJSReceiver()) {
1887 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1888 Object::ConvertReceiver(isolate, receiver),
1889 Nothing<PropertyAttributes>());
1891 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1892 *holder, kDontThrow);
1893 if (!interceptor->query()->IsUndefined(isolate)) {
1894 Handle<Object> result;
1895 if (it->IsElement()) {
1896 result = args.CallIndexedQuery(interceptor, it->index());
1898 result = args.CallNamedQuery(interceptor, it->name());
1900 if (!result.is_null()) {
1902 CHECK(result->ToInt32(&value));
1903 return Just(static_cast<PropertyAttributes>(value));
1905 }
else if (!interceptor->getter()->IsUndefined(isolate)) {
1907 Handle<Object> result;
1908 if (it->IsElement()) {
1909 result = args.CallIndexedGetter(interceptor, it->index());
1911 result = args.CallNamedGetter(interceptor, it->name());
1913 if (!result.is_null())
return Just(DONT_ENUM);
1916 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
1917 return Just(ABSENT);
1920 Maybe<bool> SetPropertyWithInterceptorInternal(
1921 LookupIterator* it, Handle<InterceptorInfo> interceptor,
1922 ShouldThrow should_throw, Handle<Object> value) {
1923 Isolate* isolate = it->isolate();
1926 AssertNoContextChange ncc(isolate);
1928 if (interceptor->setter()->IsUndefined(isolate))
return Just(
false);
1930 Handle<JSObject> holder = it->GetHolder<JSObject>();
1932 Handle<Object> receiver = it->GetReceiver();
1933 if (!receiver->IsJSReceiver()) {
1934 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1935 Object::ConvertReceiver(isolate, receiver),
1938 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1939 *holder, should_throw);
1941 if (it->IsElement()) {
1944 result = !args.CallIndexedSetter(interceptor, it->index(), value).is_null();
1946 result = !args.CallNamedSetter(interceptor, it->name(), value).is_null();
1949 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
1950 return Just(result);
1953 Maybe<bool> DefinePropertyWithInterceptorInternal(
1954 LookupIterator* it, Handle<InterceptorInfo> interceptor,
1955 ShouldThrow should_throw, PropertyDescriptor& desc) {
1956 Isolate* isolate = it->isolate();
1959 AssertNoContextChange ncc(isolate);
1961 if (interceptor->definer()->IsUndefined(isolate))
return Just(
false);
1963 Handle<JSObject> holder = it->GetHolder<JSObject>();
1965 Handle<Object> receiver = it->GetReceiver();
1966 if (!receiver->IsJSReceiver()) {
1967 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1968 Object::ConvertReceiver(isolate, receiver),
1971 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1972 *holder, should_throw);
1974 std::unique_ptr<v8::PropertyDescriptor> descriptor(
1976 if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
1978 v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
1979 }
else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
1980 if (desc.has_writable()) {
1982 v8::Utils::ToLocal(desc.value()), desc.writable()));
1988 if (desc.has_enumerable()) {
1989 descriptor->set_enumerable(desc.enumerable());
1991 if (desc.has_configurable()) {
1992 descriptor->set_configurable(desc.configurable());
1995 if (it->IsElement()) {
1996 result = !args.CallIndexedDefiner(interceptor, it->index(), *descriptor)
2000 !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null();
2003 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
2004 return Just(result);
2009 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
2010 LookupIterator* it) {
2011 Isolate* isolate = it->isolate();
2012 Handle<JSObject> checked = it->GetHolder<JSObject>();
2013 Handle<InterceptorInfo> interceptor =
2014 it->GetInterceptorForFailedAccessCheck();
2015 if (interceptor.is_null()) {
2016 while (AllCanRead(it)) {
2017 if (it->state() == LookupIterator::ACCESSOR) {
2018 return GetPropertyWithAccessor(it);
2020 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
2022 Handle<Object> result;
2023 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
2024 GetPropertyWithInterceptor(it, &done), Object);
2025 if (done)
return result;
2029 Handle<Object> result;
2031 ASSIGN_RETURN_ON_EXCEPTION(
2033 GetPropertyWithInterceptorInternal(it, interceptor, &done), Object);
2034 if (done)
return result;
2039 Handle<Name> name = it->GetName();
2040 if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
2041 return it->factory()->undefined_value();
2044 isolate->ReportFailedAccessCheck(checked);
2045 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2046 return it->factory()->undefined_value();
2050 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
2051 LookupIterator* it) {
2052 Isolate* isolate = it->isolate();
2053 Handle<JSObject> checked = it->GetHolder<JSObject>();
2054 Handle<InterceptorInfo> interceptor =
2055 it->GetInterceptorForFailedAccessCheck();
2056 if (interceptor.is_null()) {
2057 while (AllCanRead(it)) {
2058 if (it->state() == LookupIterator::ACCESSOR) {
2059 return Just(it->property_attributes());
2061 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
2062 auto result = GetPropertyAttributesWithInterceptor(it);
2063 if (isolate->has_scheduled_exception())
break;
2064 if (result.IsJust() && result.FromJust() != ABSENT)
return result;
2067 Maybe<PropertyAttributes> result =
2068 GetPropertyAttributesWithInterceptorInternal(it, interceptor);
2069 if (isolate->has_pending_exception())
return Nothing<PropertyAttributes>();
2070 if (result.FromMaybe(ABSENT) != ABSENT)
return result;
2072 isolate->ReportFailedAccessCheck(checked);
2073 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
2074 return Just(ABSENT);
2079 bool JSObject::AllCanWrite(LookupIterator* it) {
2080 for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
2081 if (it->state() == LookupIterator::ACCESSOR) {
2082 Handle<Object> accessors = it->GetAccessors();
2083 if (accessors->IsAccessorInfo()) {
2084 if (AccessorInfo::cast(*accessors)->all_can_write())
return true;
2092 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
2093 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
2094 Isolate* isolate = it->isolate();
2095 Handle<JSObject> checked = it->GetHolder<JSObject>();
2096 Handle<InterceptorInfo> interceptor =
2097 it->GetInterceptorForFailedAccessCheck();
2098 if (interceptor.is_null()) {
2099 if (AllCanWrite(it)) {
2100 return SetPropertyWithAccessor(it, value, should_throw);
2103 Maybe<bool> result = SetPropertyWithInterceptorInternal(
2104 it, interceptor, should_throw, value);
2105 if (isolate->has_pending_exception())
return Nothing<bool>();
2106 if (result.IsJust())
return result;
2108 isolate->ReportFailedAccessCheck(checked);
2109 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
2114 void JSObject::SetNormalizedProperty(Handle<JSObject>
object,
2116 Handle<Object> value,
2117 PropertyDetails details) {
2118 DCHECK(!object->HasFastProperties());
2119 DCHECK(name->IsUniqueName());
2120 Isolate* isolate =
object->GetIsolate();
2124 if (object->IsJSGlobalObject()) {
2125 Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(
object);
2126 Handle<GlobalDictionary> dictionary(global_obj->global_dictionary(),
2128 int entry = dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
2130 if (entry == GlobalDictionary::kNotFound) {
2131 DCHECK_IMPLIES(global_obj->map()->is_prototype_map(),
2132 Map::IsPrototypeChainInvalidated(global_obj->map()));
2133 auto cell = isolate->factory()->NewPropertyCell(name);
2134 cell->set_value(*value);
2135 auto cell_type = value->IsUndefined(isolate)
2136 ? PropertyCellType::kUndefined
2137 : PropertyCellType::kConstant;
2138 details = details.set_cell_type(cell_type);
2141 GlobalDictionary::Add(isolate, dictionary, name, value, details);
2142 global_obj->set_global_dictionary(*dictionary);
2144 Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
2145 isolate, dictionary, entry, value, details);
2146 cell->set_value(*value);
2149 Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
2151 int entry = dictionary->FindEntry(isolate, name);
2152 if (entry == NameDictionary::kNotFound) {
2153 DCHECK_IMPLIES(object->map()->is_prototype_map(),
2154 Map::IsPrototypeChainInvalidated(object->map()));
2156 NameDictionary::Add(isolate, dictionary, name, value, details);
2157 object->SetProperties(*dictionary);
2159 PropertyDetails original_details = dictionary->DetailsAt(entry);
2160 int enumeration_index = original_details.dictionary_index();
2161 DCHECK_GT(enumeration_index, 0);
2162 details = details.set_index(enumeration_index);
2163 dictionary->SetEntry(isolate, entry, *name, *value, details);
2169 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
2170 Handle<JSReceiver>
object,
2171 Handle<Object> proto) {
2172 PrototypeIterator iter(isolate,
object, kStartAtReceiver);
2174 if (!iter.AdvanceFollowingProxies())
return Nothing<bool>();
2175 if (iter.IsAtEnd())
return Just(
false);
2176 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
2184 bool HasExcludedProperty(
2185 const ScopedVector<Handle<Object>>* excluded_properties,
2186 Handle<Object> search_element) {
2188 for (
int i = 0;
i < excluded_properties->length();
i++) {
2189 if (search_element->SameValue(*excluded_properties->at(
i))) {
2197 V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
2198 Handle<JSReceiver> target, Handle<Object> source,
2199 const ScopedVector<Handle<Object>>* excluded_properties,
bool use_set) {
2202 if (!source->IsJSReceiver()) {
2203 return Just(!source->IsString() || String::cast(*source)->length() == 0);
2210 if (target->map()->is_deprecated()) {
2211 JSObject::MigrateInstance(Handle<JSObject>::cast(target));
2214 Isolate* isolate = target->GetIsolate();
2215 Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
2217 if (!map->IsJSObjectMap())
return Just(
false);
2218 if (!map->OnlyHasSimpleProperties())
return Just(
false);
2220 Handle<JSObject> from = Handle<JSObject>::cast(source);
2221 if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
2225 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
2226 int length = map->NumberOfOwnDescriptors();
2230 for (
int i = 0;
i < length;
i++) {
2231 Handle<Name> next_key(descriptors->GetKey(
i), isolate);
2232 Handle<Object> prop_value;
2235 PropertyDetails details = descriptors->GetDetails(
i);
2236 if (!details.IsEnumerable())
continue;
2237 if (details.kind() == kData) {
2238 if (details.location() == kDescriptor) {
2239 prop_value = handle(descriptors->GetStrongValue(
i), isolate);
2241 Representation representation = details.representation();
2242 FieldIndex index = FieldIndex::ForDescriptor(*map,
i);
2243 prop_value = JSObject::FastPropertyAt(from, representation, index);
2246 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2247 isolate, prop_value,
2248 JSReceiver::GetProperty(isolate, from, next_key), Nothing<bool>());
2249 stable = from->map() == *map;
2254 LookupIterator it(from, next_key, from,
2255 LookupIterator::OWN_SKIP_INTERCEPTOR);
2256 if (!it.IsFound())
continue;
2257 DCHECK(it.state() == LookupIterator::DATA ||
2258 it.state() == LookupIterator::ACCESSOR);
2259 if (!it.IsEnumerable())
continue;
2260 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2261 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
2265 LookupIterator it(target, next_key, target);
2266 Maybe<bool> result = Object::SetProperty(
2267 &it, prop_value, LanguageMode::kStrict, StoreOrigin::kNamed);
2268 if (result.IsNothing())
return result;
2269 if (stable) stable = from->map() == *map;
2271 if (excluded_properties !=
nullptr &&
2272 HasExcludedProperty(excluded_properties, next_key)) {
2278 LookupIterator it = LookupIterator::PropertyOrElement(
2279 isolate, target, next_key, &success, LookupIterator::OWN);
2281 CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
2291 Maybe<bool> JSReceiver::SetOrCopyDataProperties(
2292 Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
2293 const ScopedVector<Handle<Object>>* excluded_properties,
bool use_set) {
2294 Maybe<bool> fast_assign =
2295 FastAssign(target, source, excluded_properties, use_set);
2296 if (fast_assign.IsNothing())
return Nothing<bool>();
2297 if (fast_assign.FromJust())
return Just(
true);
2299 Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
2301 Handle<FixedArray> keys;
2302 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2304 KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2305 GetKeysConversion::kKeepNumbers),
2309 for (
int j = 0; j < keys->length(); ++j) {
2310 Handle<Object> next_key(keys->get(j), isolate);
2312 PropertyDescriptor desc;
2314 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
2315 if (found.IsNothing())
return Nothing<bool>();
2317 if (found.FromJust() && desc.enumerable()) {
2319 Handle<Object> prop_value;
2320 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2321 isolate, prop_value,
2322 Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
2326 Handle<Object> status;
2327 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2329 Runtime::SetObjectProperty(isolate, target, next_key, prop_value,
2330 LanguageMode::kStrict,
2331 StoreOrigin::kMaybeKeyed),
2334 if (excluded_properties !=
nullptr &&
2335 HasExcludedProperty(excluded_properties, next_key)) {
2341 LookupIterator it = LookupIterator::PropertyOrElement(
2342 isolate, target, next_key, &success, LookupIterator::OWN);
2344 CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
2353 Map Object::GetPrototypeChainRootMap(Isolate* isolate)
const {
2354 DisallowHeapAllocation no_alloc;
2356 Context native_context = isolate->context()->native_context();
2357 return native_context->number_function()->initial_map();
2360 const HeapObject* heap_object = HeapObject::cast(
this);
2361 return heap_object->map()->GetPrototypeChainRootMap(isolate);
2364 Map Map::GetPrototypeChainRootMap(Isolate* isolate)
const {
2365 DisallowHeapAllocation no_alloc;
2366 if (IsJSReceiverMap()) {
2369 int constructor_function_index = GetConstructorFunctionIndex();
2370 if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
2371 Context native_context = isolate->context()->native_context();
2372 JSFunction* constructor_function =
2373 JSFunction::cast(native_context->get(constructor_function_index));
2374 return constructor_function->initial_map();
2376 return ReadOnlyRoots(isolate).null_value()->map();
2379 Smi Object::GetOrCreateHash(Isolate* isolate) {
2380 DisallowHeapAllocation no_gc;
2381 Object* hash = Object::GetSimpleHash(
this);
2382 if (hash->IsSmi())
return Smi::cast(hash);
2384 DCHECK(IsJSReceiver());
2385 return JSReceiver::cast(
this)->GetOrCreateIdentityHash(isolate);
2388 Smi ObjectPtr::GetOrCreateHash(Isolate* isolate) {
2389 return reinterpret_cast<Object*
>(ptr())->GetOrCreateHash(isolate);
2392 bool Object::SameValue(Object* other) {
2393 if (other ==
this)
return true;
2395 if (IsNumber() && other->IsNumber()) {
2396 double this_value = Number();
2397 double other_value = other->Number();
2399 if (this_value != other_value) {
2400 return std::isnan(this_value) && std::isnan(other_value);
2403 return (std::signbit(this_value) == std::signbit(other_value));
2405 if (IsString() && other->IsString()) {
2406 return String::cast(
this)->Equals(String::cast(other));
2408 if (IsBigInt() && other->IsBigInt()) {
2409 return BigInt::EqualToBigInt(BigInt::cast(
this), BigInt::cast(other));
2414 bool ObjectPtr::SameValue(Object* other) {
2415 return reinterpret_cast<Object*
>(ptr())->SameValue(other);
2418 bool Object::SameValueZero(Object* other) {
2419 if (other ==
this)
return true;
2421 if (IsNumber() && other->IsNumber()) {
2422 double this_value = Number();
2423 double other_value = other->Number();
2425 return this_value == other_value ||
2426 (std::isnan(this_value) && std::isnan(other_value));
2428 if (IsString() && other->IsString()) {
2429 return String::cast(
this)->Equals(String::cast(other));
2431 if (IsBigInt() && other->IsBigInt()) {
2432 return BigInt::EqualToBigInt(BigInt::cast(
this), BigInt::cast(other));
2438 MaybeHandle<Object> Object::ArraySpeciesConstructor(
2439 Isolate* isolate, Handle<Object> original_array) {
2440 Handle<Object> default_species = isolate->array_function();
2441 if (original_array->IsJSArray() &&
2442 Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
2443 isolate->IsArraySpeciesLookupChainIntact()) {
2444 return default_species;
2446 Handle<Object> constructor = isolate->factory()->undefined_value();
2447 Maybe<bool> is_array = Object::IsArray(original_array);
2448 MAYBE_RETURN_NULL(is_array);
2449 if (is_array.FromJust()) {
2450 ASSIGN_RETURN_ON_EXCEPTION(
2451 isolate, constructor,
2452 Object::GetProperty(isolate, original_array,
2453 isolate->factory()->constructor_string()),
2455 if (constructor->IsConstructor()) {
2456 Handle<Context> constructor_context;
2457 ASSIGN_RETURN_ON_EXCEPTION(
2458 isolate, constructor_context,
2459 JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
2461 if (*constructor_context != *isolate->native_context() &&
2462 *constructor == constructor_context->array_function()) {
2463 constructor = isolate->factory()->undefined_value();
2466 if (constructor->IsJSReceiver()) {
2467 ASSIGN_RETURN_ON_EXCEPTION(
2468 isolate, constructor,
2469 JSReceiver::GetProperty(isolate,
2470 Handle<JSReceiver>::cast(constructor),
2471 isolate->factory()->species_symbol()),
2473 if (constructor->IsNull(isolate)) {
2474 constructor = isolate->factory()->undefined_value();
2478 if (constructor->IsUndefined(isolate)) {
2479 return default_species;
2481 if (!constructor->IsConstructor()) {
2482 THROW_NEW_ERROR(isolate,
2483 NewTypeError(MessageTemplate::kSpeciesNotConstructor),
2491 V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
2492 Isolate* isolate, Handle<JSReceiver> recv,
2493 Handle<JSFunction> default_ctor) {
2494 Handle<Object> ctor_obj;
2495 ASSIGN_RETURN_ON_EXCEPTION(
2497 JSObject::GetProperty(isolate, recv,
2498 isolate->factory()->constructor_string()),
2501 if (ctor_obj->IsUndefined(isolate))
return default_ctor;
2503 if (!ctor_obj->IsJSReceiver()) {
2504 THROW_NEW_ERROR(isolate,
2505 NewTypeError(MessageTemplate::kConstructorNotReceiver),
2509 Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
2511 Handle<Object> species;
2512 ASSIGN_RETURN_ON_EXCEPTION(
2514 JSObject::GetProperty(isolate, ctor,
2515 isolate->factory()->species_symbol()),
2518 if (species->IsNullOrUndefined(isolate)) {
2519 return default_ctor;
2522 if (species->IsConstructor())
return species;
2525 isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
2528 bool Object::IterationHasObservableEffects() {
2530 if (!IsJSArray())
return true;
2531 JSArray* array = JSArray::cast(
this);
2532 Isolate* isolate = array->GetIsolate();
2534 #ifdef V8_ENABLE_FORCE_SLOW_PATH 2535 if (isolate->force_slow_path())
return true;
2539 if (!array->map()->prototype()->IsJSObject())
return true;
2540 JSObject* array_proto = JSObject::cast(array->map()->prototype());
2541 if (!isolate->is_initial_array_prototype(array_proto))
return true;
2545 if (!isolate->IsArrayIteratorLookupChainIntact())
return true;
2549 ElementsKind array_kind = array->GetElementsKind();
2550 if (IsFastPackedElementsKind(array_kind))
return false;
2555 if (IsHoleyElementsKind(array_kind) &&
2556 isolate->IsNoElementsProtectorIntact()) {
2562 void Object::ShortPrint(FILE* out) {
2568 void Object::ShortPrint(StringStream* accumulator) {
2569 std::ostringstream os;
2571 accumulator->Add(os.str().c_str());
2574 void Object::ShortPrint(std::ostream& os) { os << Brief(
this); }
2576 void ObjectPtr::ShortPrint(std::ostream& os) { os << Brief(*
this); }
2578 void MaybeObject::ShortPrint(FILE* out) {
2583 void MaybeObject::ShortPrint(StringStream* accumulator) {
2584 std::ostringstream os;
2586 accumulator->Add(os.str().c_str());
2589 void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(*
this); }
2591 Brief::Brief(
const Object* v) : value(v->ptr()) {}
2592 Brief::Brief(
const MaybeObject v) : value(v.ptr()) {}
2594 std::ostream& operator<<(std::ostream& os,
const Brief& v) {
2595 MaybeObject maybe_object(v.value);
2597 HeapObject* heap_object;
2598 if (maybe_object->ToSmi(&smi)) {
2600 }
else if (maybe_object->IsCleared()) {
2602 }
else if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
2604 heap_object->HeapObjectShortPrint(os);
2605 }
else if (maybe_object->GetHeapObjectIfStrong(&heap_object)) {
2606 heap_object->HeapObjectShortPrint(os);
2613 void Smi::SmiPrint(std::ostream& os)
const {
2617 Handle<String> String::SlowFlatten(Isolate* isolate, Handle<ConsString> cons,
2618 PretenureFlag pretenure) {
2619 DCHECK_NE(cons->second()->length(), 0);
2622 while (cons->first()->length() == 0) {
2626 if (cons->second()->IsConsString() && !cons->second()->IsFlat()) {
2627 cons = handle(ConsString::cast(cons->second()), isolate);
2629 return String::Flatten(isolate, handle(cons->second(), isolate));
2633 DCHECK(AllowHeapAllocation::IsAllowed());
2634 int length = cons->length();
2635 PretenureFlag tenure = Heap::InNewSpace(*cons) ? pretenure : TENURED;
2636 Handle<SeqString> result;
2637 if (cons->IsOneByteRepresentation()) {
2638 Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
2639 length, tenure).ToHandleChecked();
2640 DisallowHeapAllocation no_gc;
2641 WriteToFlat(*cons, flat->GetChars(), 0, length);
2644 Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
2645 length, tenure).ToHandleChecked();
2646 DisallowHeapAllocation no_gc;
2647 WriteToFlat(*cons, flat->GetChars(), 0, length);
2650 cons->set_first(isolate, *result);
2651 cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
2652 DCHECK(result->IsFlat());
2659 DisallowHeapAllocation no_allocation;
2662 DCHECK(this->SupportsExternalization());
2664 #ifdef ENABLE_SLOW_DCHECKS 2665 if (FLAG_enable_slow_asserts) {
2667 DCHECK(static_cast<size_t>(this->length()) == resource->
length());
2668 ScopedVector<uc16> smart_chars(this->length());
2669 String::WriteToFlat(*
this, smart_chars.start(), 0, this->length());
2670 DCHECK_EQ(0, memcmp(smart_chars.start(), resource->
data(),
2671 resource->
length() *
sizeof(smart_chars[0])));
2674 int size = this->Size();
2676 if (size < ExternalString::kUncachedSize)
return false;
2680 if (!Isolate::FromWritableHeapObject(*
this, &isolate))
return false;
2681 Heap* heap = isolate->heap();
2682 bool is_one_byte = this->IsOneByteRepresentation();
2683 bool is_internalized = this->IsInternalizedString();
2684 bool has_pointers = StringShape(*this).IsIndirect();
2686 heap->NotifyObjectLayoutChange(*
this, size, no_allocation);
2695 ReadOnlyRoots roots(heap);
2696 if (size < ExternalString::kSize) {
2697 if (is_internalized) {
2701 .uncached_external_internalized_string_with_one_byte_data_map();
2703 new_map = roots.uncached_external_internalized_string_map();
2706 new_map = is_one_byte
2707 ? roots.uncached_external_string_with_one_byte_data_map()
2708 : roots.uncached_external_string_map();
2714 ? roots.external_internalized_string_with_one_byte_data_map()
2715 : roots.external_internalized_string_map())
2716 : (is_one_byte ? roots.external_string_with_one_byte_data_map()
2717 : roots.external_string_map());
2721 int new_size = this->SizeFromMap(new_map);
2722 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2723 ClearRecordedSlots::kNo);
2725 heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
2730 this->synchronized_set_map(new_map);
2732 ExternalTwoByteString
self = ExternalTwoByteString::cast(*
this);
2733 self->SetResource(isolate, resource);
2734 heap->RegisterExternalString(*
this);
2735 if (is_internalized)
self->Hash();
2741 DisallowHeapAllocation no_allocation;
2744 DCHECK(this->SupportsExternalization());
2746 #ifdef ENABLE_SLOW_DCHECKS 2747 if (FLAG_enable_slow_asserts) {
2749 DCHECK(static_cast<size_t>(this->length()) == resource->
length());
2750 if (this->IsTwoByteRepresentation()) {
2751 ScopedVector<uint16_t> smart_chars(this->length());
2752 String::WriteToFlat(*
this, smart_chars.start(), 0, this->length());
2753 DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
2755 ScopedVector<char> smart_chars(this->length());
2756 String::WriteToFlat(*
this, smart_chars.start(), 0, this->length());
2757 DCHECK_EQ(0, memcmp(smart_chars.start(), resource->
data(),
2758 resource->
length() *
sizeof(smart_chars[0])));
2761 int size = this->Size();
2763 if (size < ExternalString::kUncachedSize)
return false;
2767 if (!Isolate::FromWritableHeapObject(*
this, &isolate))
return false;
2768 Heap* heap = isolate->heap();
2769 bool is_internalized = this->IsInternalizedString();
2770 bool has_pointers = StringShape(*this).IsIndirect();
2773 heap->NotifyObjectLayoutChange(*
this, size, no_allocation);
2783 ReadOnlyRoots roots(heap);
2784 if (size < ExternalString::kSize) {
2785 new_map = is_internalized
2786 ? roots.uncached_external_one_byte_internalized_string_map()
2787 : roots.uncached_external_one_byte_string_map();
2789 new_map = is_internalized
2790 ? roots.external_one_byte_internalized_string_map()
2791 : roots.external_one_byte_string_map();
2795 int new_size = this->SizeFromMap(new_map);
2796 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2797 ClearRecordedSlots::kNo);
2799 heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
2804 this->synchronized_set_map(new_map);
2806 ExternalOneByteString
self = ExternalOneByteString::cast(*
this);
2807 self->SetResource(isolate, resource);
2808 heap->RegisterExternalString(*
this);
2809 if (is_internalized)
self->Hash();
2813 bool String::SupportsExternalization() {
2814 if (this->IsThinString()) {
2815 return i::ThinString::cast(*this)->actual()->SupportsExternalization();
2820 if (!Isolate::FromWritableHeapObject(*
this, &isolate)) {
2825 if (StringShape(*this).IsExternal()) {
2829 return !isolate->heap()->IsInGCPostProcessing();
2832 void String::StringShortPrint(StringStream* accumulator,
bool show_details) {
2834 if (len > kMaxShortPrintLength) {
2835 accumulator->Add(
"<Very long string[%u]>", len);
2839 if (!LooksValid()) {
2840 accumulator->Add(
"<Invalid String>");
2844 StringCharacterStream stream(*
this);
2846 bool truncated =
false;
2847 if (len > kMaxShortPrintLength) {
2848 len = kMaxShortPrintLength;
2851 bool one_byte =
true;
2852 for (
int i = 0;
i < len;
i++) {
2853 uint16_t c = stream.GetNext();
2855 if (c < 32 || c >= 127) {
2859 stream.Reset(*
this);
2861 if (show_details) accumulator->Add(
"<String[%u]: ", length());
2862 for (
int i = 0;
i < len;
i++) {
2863 accumulator->Put(static_cast<char>(stream.GetNext()));
2865 if (show_details) accumulator->Put(
'>');
2869 if (show_details) accumulator->Add(
"<String[%u]\\: ", length());
2870 for (
int i = 0;
i < len;
i++) {
2871 uint16_t c = stream.GetNext();
2873 accumulator->Add(
"\\n");
2874 }
else if (c ==
'\r') {
2875 accumulator->Add(
"\\r");
2876 }
else if (c ==
'\\') {
2877 accumulator->Add(
"\\\\");
2878 }
else if (c < 32 || c > 126) {
2879 accumulator->Add(
"\\x%02x", c);
2881 accumulator->Put(static_cast<char>(c));
2885 accumulator->Put(
'.');
2886 accumulator->Put(
'.');
2887 accumulator->Put(
'.');
2889 if (show_details) accumulator->Put(
'>');
2895 void String::PrintUC16(std::ostream& os,
int start,
int end) {
2896 if (end < 0) end = length();
2897 StringCharacterStream stream(*
this, start);
2898 for (
int i = start;
i < end && stream.HasMore();
i++) {
2899 os << AsUC16(stream.GetNext());
2904 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
2905 switch (map()->instance_type()) {
2906 case JS_ARRAY_TYPE: {
2907 double length = JSArray::cast(
this)->length()->IsUndefined()
2909 : JSArray::cast(
this)->length()->Number();
2910 accumulator->Add(
"<JSArray[%u]>", static_cast<uint32_t>(length));
2913 case JS_BOUND_FUNCTION_TYPE: {
2914 JSBoundFunction* bound_function = JSBoundFunction::cast(
this);
2915 accumulator->Add(
"<JSBoundFunction");
2917 " (BoundTargetFunction %p)>",
2918 reinterpret_cast<void*>(bound_function->bound_target_function()));
2921 case JS_WEAK_MAP_TYPE: {
2922 accumulator->Add(
"<JSWeakMap>");
2925 case JS_WEAK_SET_TYPE: {
2926 accumulator->Add(
"<JSWeakSet>");
2929 case JS_REGEXP_TYPE: {
2930 accumulator->Add(
"<JSRegExp");
2931 JSRegExp* regexp = JSRegExp::cast(
this);
2932 if (regexp->source()->IsString()) {
2933 accumulator->Add(
" ");
2934 String::cast(regexp->source())->StringShortPrint(accumulator);
2936 accumulator->Add(
">");
2940 case JS_FUNCTION_TYPE: {
2941 JSFunction*
function = JSFunction::cast(
this);
2942 Object* fun_name =
function->shared()->DebugName();
2943 bool printed =
false;
2944 if (fun_name->IsString()) {
2945 String str = String::cast(fun_name);
2946 if (str->length() > 0) {
2947 accumulator->Add(
"<JSFunction ");
2948 accumulator->Put(str);
2953 accumulator->Add(
"<JSFunction");
2955 if (FLAG_trace_file_names) {
2956 Object* source_name =
2957 Script::cast(function->shared()->script())->name();
2958 if (source_name->IsString()) {
2959 String str = String::cast(source_name);
2960 if (str->length() > 0) {
2961 accumulator->Add(
" <");
2962 accumulator->Put(str);
2963 accumulator->Add(
">");
2967 accumulator->Add(
" (sfi = %p)",
2968 reinterpret_cast<void*>(function->shared()));
2969 accumulator->Put(
'>');
2972 case JS_GENERATOR_OBJECT_TYPE: {
2973 accumulator->Add(
"<JSGenerator>");
2976 case JS_ASYNC_FUNCTION_OBJECT_TYPE: {
2977 accumulator->Add(
"<JSAsyncFunctionObject>");
2980 case JS_ASYNC_GENERATOR_OBJECT_TYPE: {
2981 accumulator->Add(
"<JS AsyncGenerator>");
2988 Map map_of_this = map();
2989 Heap* heap = GetHeap();
2990 Object* constructor = map_of_this->GetConstructor();
2991 bool printed =
false;
2992 if (constructor->IsHeapObject() &&
2993 !heap->Contains(HeapObject::cast(constructor))) {
2994 accumulator->Add(
"!!!INVALID CONSTRUCTOR!!!");
2996 bool global_object = IsJSGlobalProxy();
2997 if (constructor->IsJSFunction()) {
2998 if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
2999 accumulator->Add(
"!!!INVALID SHARED ON CONSTRUCTOR!!!");
3001 String constructor_name =
3002 JSFunction::cast(constructor)->shared()->Name();
3003 if (constructor_name->length() > 0) {
3004 accumulator->Add(global_object ?
"<GlobalObject " :
"<");
3005 accumulator->Put(constructor_name);
3008 map_of_this->is_deprecated() ?
"deprecated-" :
"",
3013 }
else if (constructor->IsFunctionTemplateInfo()) {
3014 accumulator->Add(global_object ?
"<RemoteObject>" :
"<RemoteObject>");
3018 accumulator->Add(
"<JS%sObject", global_object ?
"Global " :
"");
3022 accumulator->Add(
" value = ");
3023 JSValue::cast(
this)->value()->ShortPrint(accumulator);
3025 accumulator->Put(
'>');
3032 void JSObject::PrintElementsTransition(
3033 FILE* file, Handle<JSObject>
object,
3034 ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
3035 ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
3036 if (from_kind != to_kind) {
3038 os <<
"elements transition [" << ElementsKindToString(from_kind) <<
" -> " 3039 << ElementsKindToString(to_kind) <<
"] in ";
3040 JavaScriptFrame::PrintTop(object->GetIsolate(), file,
false,
true);
3041 PrintF(file,
" for ");
3042 object->ShortPrint(file);
3043 PrintF(file,
" from ");
3044 from_elements->ShortPrint(file);
3045 PrintF(file,
" to ");
3046 to_elements->ShortPrint(file);
3053 MaybeHandle<JSFunction> Map::GetConstructorFunction(
3054 Handle<Map> map, Handle<Context> native_context) {
3055 if (map->IsPrimitiveMap()) {
3056 int const constructor_function_index = map->GetConstructorFunctionIndex();
3057 if (constructor_function_index != kNoConstructorFunctionIndex) {
3059 JSFunction::cast(native_context->get(constructor_function_index)),
3060 native_context->GetIsolate());
3063 return MaybeHandle<JSFunction>();
3066 void Map::PrintReconfiguration(Isolate* isolate, FILE* file,
int modify_index,
3068 PropertyAttributes attributes) {
3070 os <<
"[reconfiguring]";
3071 Name name = instance_descriptors()->GetKey(modify_index);
3072 if (name->IsString()) {
3073 String::cast(name)->PrintOn(file);
3075 os <<
"{symbol " <<
reinterpret_cast<void*
>(name.ptr()) <<
"}";
3077 os <<
": " << (kind == kData ?
"kData" :
"ACCESSORS") <<
", attrs: ";
3078 os << attributes <<
" [";
3079 JavaScriptFrame::PrintTop(isolate, file,
false,
true);
3083 VisitorId Map::GetVisitorId(Map map) {
3084 STATIC_ASSERT(kVisitorIdCount <= 256);
3086 const int instance_type = map->instance_type();
3087 const bool has_unboxed_fields =
3088 FLAG_unbox_double_fields && !map->HasFastPointerLayout();
3089 if (instance_type < FIRST_NONSTRING_TYPE) {
3090 switch (instance_type & kStringRepresentationMask) {
3092 if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
3093 return kVisitSeqOneByteString;
3095 return kVisitSeqTwoByteString;
3098 case kConsStringTag:
3099 if (IsShortcutCandidate(instance_type)) {
3100 return kVisitShortcutCandidate;
3102 return kVisitConsString;
3105 case kSlicedStringTag:
3106 return kVisitSlicedString;
3108 case kExternalStringTag:
3109 return kVisitDataObject;
3111 case kThinStringTag:
3112 return kVisitThinString;
3117 switch (instance_type) {
3118 case BYTE_ARRAY_TYPE:
3119 return kVisitByteArray;
3121 case BYTECODE_ARRAY_TYPE:
3122 return kVisitBytecodeArray;
3124 case FREE_SPACE_TYPE:
3125 return kVisitFreeSpace;
3127 case EMBEDDER_DATA_ARRAY_TYPE:
3128 return kVisitEmbedderDataArray;
3130 case FIXED_ARRAY_TYPE:
3131 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
3132 case HASH_TABLE_TYPE:
3133 case ORDERED_HASH_MAP_TYPE:
3134 case ORDERED_HASH_SET_TYPE:
3135 case ORDERED_NAME_DICTIONARY_TYPE:
3136 case NAME_DICTIONARY_TYPE:
3137 case GLOBAL_DICTIONARY_TYPE:
3138 case NUMBER_DICTIONARY_TYPE:
3139 case SIMPLE_NUMBER_DICTIONARY_TYPE:
3140 case STRING_TABLE_TYPE:
3141 case SCOPE_INFO_TYPE:
3142 case SCRIPT_CONTEXT_TABLE_TYPE:
3143 return kVisitFixedArray;
3145 case AWAIT_CONTEXT_TYPE:
3146 case BLOCK_CONTEXT_TYPE:
3147 case CATCH_CONTEXT_TYPE:
3148 case DEBUG_EVALUATE_CONTEXT_TYPE:
3149 case EVAL_CONTEXT_TYPE:
3150 case FUNCTION_CONTEXT_TYPE:
3151 case MODULE_CONTEXT_TYPE:
3152 case SCRIPT_CONTEXT_TYPE:
3153 case WITH_CONTEXT_TYPE:
3154 return kVisitContext;
3156 case NATIVE_CONTEXT_TYPE:
3157 return kVisitNativeContext;
3159 case EPHEMERON_HASH_TABLE_TYPE:
3160 return kVisitEphemeronHashTable;
3162 case WEAK_FIXED_ARRAY_TYPE:
3163 case WEAK_ARRAY_LIST_TYPE:
3164 return kVisitWeakArray;
3166 case FIXED_DOUBLE_ARRAY_TYPE:
3167 return kVisitFixedDoubleArray;
3169 case PROPERTY_ARRAY_TYPE:
3170 return kVisitPropertyArray;
3172 case FEEDBACK_CELL_TYPE:
3173 return kVisitFeedbackCell;
3175 case FEEDBACK_VECTOR_TYPE:
3176 return kVisitFeedbackVector;
3179 return kVisitOddball;
3190 case PROPERTY_CELL_TYPE:
3191 return kVisitPropertyCell;
3193 case DESCRIPTOR_ARRAY_TYPE:
3194 return kVisitDescriptorArray;
3196 case TRANSITION_ARRAY_TYPE:
3197 return kVisitTransitionArray;
3199 case JS_WEAK_MAP_TYPE:
3200 case JS_WEAK_SET_TYPE:
3201 return kVisitJSWeakCollection;
3203 case CALL_HANDLER_INFO_TYPE:
3204 return kVisitStruct;
3206 case SHARED_FUNCTION_INFO_TYPE:
3207 return kVisitSharedFunctionInfo;
3210 return kVisitStruct;
3213 return kVisitSymbol;
3215 case JS_ARRAY_BUFFER_TYPE:
3216 return kVisitJSArrayBuffer;
3218 case JS_DATA_VIEW_TYPE:
3219 return kVisitJSDataView;
3221 case JS_TYPED_ARRAY_TYPE:
3222 return kVisitJSTypedArray;
3224 case SMALL_ORDERED_HASH_MAP_TYPE:
3225 return kVisitSmallOrderedHashMap;
3227 case SMALL_ORDERED_HASH_SET_TYPE:
3228 return kVisitSmallOrderedHashSet;
3230 case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
3231 return kVisitSmallOrderedNameDictionary;
3233 case CODE_DATA_CONTAINER_TYPE:
3234 return kVisitCodeDataContainer;
3236 case WASM_INSTANCE_TYPE:
3237 return kVisitWasmInstanceObject;
3239 case PRE_PARSED_SCOPE_DATA_TYPE:
3240 return kVisitPreParsedScopeData;
3242 case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
3243 return kVisitUncompiledDataWithoutPreParsedScope;
3245 case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
3246 return kVisitUncompiledDataWithPreParsedScope;
3248 case JS_OBJECT_TYPE:
3250 case JS_ARGUMENTS_TYPE:
3251 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
3252 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
3253 case JS_GENERATOR_OBJECT_TYPE:
3254 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
3255 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
3256 case JS_MODULE_NAMESPACE_TYPE:
3259 case JS_ARRAY_ITERATOR_TYPE:
3261 case JS_FUNCTION_TYPE:
3262 case JS_GLOBAL_PROXY_TYPE:
3263 case JS_GLOBAL_OBJECT_TYPE:
3264 case JS_MESSAGE_OBJECT_TYPE:
3267 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
3268 case JS_SET_VALUE_ITERATOR_TYPE:
3269 case JS_MAP_KEY_ITERATOR_TYPE:
3270 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
3271 case JS_MAP_VALUE_ITERATOR_TYPE:
3272 case JS_STRING_ITERATOR_TYPE:
3273 case JS_PROMISE_TYPE:
3274 case JS_REGEXP_TYPE:
3275 case JS_REGEXP_STRING_ITERATOR_TYPE:
3276 case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
3277 case JS_WEAK_FACTORY_TYPE:
3278 #ifdef V8_INTL_SUPPORT 3279 case JS_INTL_V8_BREAK_ITERATOR_TYPE:
3280 case JS_INTL_COLLATOR_TYPE:
3281 case JS_INTL_DATE_TIME_FORMAT_TYPE:
3282 case JS_INTL_LIST_FORMAT_TYPE:
3283 case JS_INTL_LOCALE_TYPE:
3284 case JS_INTL_NUMBER_FORMAT_TYPE:
3285 case JS_INTL_PLURAL_RULES_TYPE:
3286 case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
3287 case JS_INTL_SEGMENT_ITERATOR_TYPE:
3288 case JS_INTL_SEGMENTER_TYPE:
3289 #endif // V8_INTL_SUPPORT 3290 case WASM_EXCEPTION_TYPE:
3291 case WASM_GLOBAL_TYPE:
3292 case WASM_MEMORY_TYPE:
3293 case WASM_MODULE_TYPE:
3294 case WASM_TABLE_TYPE:
3295 case JS_BOUND_FUNCTION_TYPE:
3296 return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
3297 case JS_API_OBJECT_TYPE:
3298 case JS_SPECIAL_API_OBJECT_TYPE:
3299 return kVisitJSApiObject;
3301 case JS_WEAK_CELL_TYPE:
3302 case JS_WEAK_REF_TYPE:
3303 return kVisitJSWeakCell;
3307 case HEAP_NUMBER_TYPE:
3308 case MUTABLE_HEAP_NUMBER_TYPE:
3309 case FEEDBACK_METADATA_TYPE:
3310 return kVisitDataObject;
3313 return kVisitBigInt;
3315 case FIXED_UINT8_ARRAY_TYPE:
3316 case FIXED_INT8_ARRAY_TYPE:
3317 case FIXED_UINT16_ARRAY_TYPE:
3318 case FIXED_INT16_ARRAY_TYPE:
3319 case FIXED_UINT32_ARRAY_TYPE:
3320 case FIXED_INT32_ARRAY_TYPE:
3321 case FIXED_FLOAT32_ARRAY_TYPE:
3322 case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
3323 case FIXED_BIGUINT64_ARRAY_TYPE:
3324 case FIXED_BIGINT64_ARRAY_TYPE:
3325 return kVisitFixedTypedArrayBase;
3327 case FIXED_FLOAT64_ARRAY_TYPE:
3328 return kVisitFixedFloat64Array;
3330 case ALLOCATION_SITE_TYPE:
3331 return kVisitAllocationSite;
3333 #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE: 3334 STRUCT_LIST(MAKE_STRUCT_CASE)
3335 #undef MAKE_STRUCT_CASE 3336 if (instance_type == PROTOTYPE_INFO_TYPE) {
3337 return kVisitPrototypeInfo;
3339 return kVisitStruct;
3341 case LOAD_HANDLER_TYPE:
3342 case STORE_HANDLER_TYPE:
3343 return kVisitDataHandler;
3350 void Map::PrintGeneralization(
3351 Isolate* isolate, FILE* file,
const char* reason,
int modify_index,
3352 int split,
int descriptors,
bool descriptor_to_field,
3353 Representation old_representation, Representation new_representation,
3354 MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value,
3355 MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value) {
3357 os <<
"[generalizing]";
3358 Name name = instance_descriptors()->GetKey(modify_index);
3359 if (name->IsString()) {
3360 String::cast(name)->PrintOn(file);
3362 os <<
"{symbol " <<
reinterpret_cast<void*
>(name.ptr()) <<
"}";
3365 if (descriptor_to_field) {
3368 os << old_representation.Mnemonic() <<
"{";
3369 if (old_field_type.is_null()) {
3370 os << Brief(*(old_value.ToHandleChecked()));
3372 old_field_type.ToHandleChecked()->PrintTo(os);
3376 os <<
"->" << new_representation.Mnemonic() <<
"{";
3377 if (new_field_type.is_null()) {
3378 os << Brief(*(new_value.ToHandleChecked()));
3380 new_field_type.ToHandleChecked()->PrintTo(os);
3383 if (strlen(reason) > 0) {
3386 os <<
"+" << (descriptors - split) <<
" maps";
3389 JavaScriptFrame::PrintTop(isolate, file,
false,
true);
3393 void JSObject::PrintInstanceMigration(FILE* file, Map original_map,
3395 if (new_map->is_dictionary_map()) {
3396 PrintF(file,
"[migrating to slow]\n");
3399 PrintF(file,
"[migrating]");
3400 DescriptorArray* o = original_map->instance_descriptors();
3401 DescriptorArray* n = new_map->instance_descriptors();
3402 for (
int i = 0;
i < original_map->NumberOfOwnDescriptors();
i++) {
3403 Representation o_r = o->GetDetails(
i).representation();
3404 Representation n_r = n->GetDetails(
i).representation();
3405 if (!o_r.Equals(n_r)) {
3406 String::cast(o->GetKey(
i))->PrintOn(file);
3407 PrintF(file,
":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
3408 }
else if (o->GetDetails(
i).location() == kDescriptor &&
3409 n->GetDetails(
i).location() == kField) {
3410 Name name = o->GetKey(
i);
3411 if (name->IsString()) {
3412 String::cast(name)->PrintOn(file);
3414 PrintF(file,
"{symbol %p}", reinterpret_cast<void*>(name.ptr()));
3419 if (original_map->elements_kind() != new_map->elements_kind()) {
3420 PrintF(file,
"elements_kind[%i->%i]", original_map->elements_kind(),
3421 new_map->elements_kind());
3426 bool JSObject::IsUnmodifiedApiObject(ObjectSlot o) {
3427 Object*
object = *o;
3428 if (object->IsSmi())
return false;
3429 HeapObject* heap_object = HeapObject::cast(
object);
3430 if (!object->IsJSObject())
return false;
3431 JSObject* js_object = JSObject::cast(
object);
3432 if (!js_object->IsDroppableApiWrapper())
return false;
3433 Object* maybe_constructor = js_object->map()->GetConstructor();
3434 if (!maybe_constructor->IsJSFunction())
return false;
3435 JSFunction* constructor = JSFunction::cast(maybe_constructor);
3436 if (js_object->elements()->length() != 0)
return false;
3438 return constructor->initial_map() == heap_object->map();
3441 void HeapObject::HeapObjectShortPrint(std::ostream& os) {
3442 os << AsHex(this->ptr(), kSystemPointerHexDigits,
true) <<
" ";
3445 HeapStringAllocator allocator;
3446 StringStream accumulator(&allocator);
3447 String::cast(
this)->StringShortPrint(&accumulator);
3448 os << accumulator.ToCString().get();
3452 HeapStringAllocator allocator;
3453 StringStream accumulator(&allocator);
3454 JSObject::cast(
this)->JSObjectShortPrint(&accumulator);
3455 os << accumulator.ToCString().get();
3458 switch (map()->instance_type()) {
3461 Map mapInstance = Map::cast(
this);
3462 if (mapInstance->IsJSObjectMap()) {
3463 os <<
"(" << ElementsKindToString(mapInstance->elements_kind()) <<
")";
3464 }
else if (mapInstance->instance_size() != kVariableSizeSentinel) {
3465 os <<
"[" << mapInstance->instance_size() <<
"]";
3469 case AWAIT_CONTEXT_TYPE: {
3470 os <<
"<AwaitContext generator= ";
3471 HeapStringAllocator allocator;
3472 StringStream accumulator(&allocator);
3473 Context::cast(
this)->extension()->ShortPrint(&accumulator);
3474 os << accumulator.ToCString().get();
3478 case BLOCK_CONTEXT_TYPE: 3479 os << "<BlockContext[" << Context::cast(this)->length() << "]>"; 3481 case CATCH_CONTEXT_TYPE: 3482 os << "<CatchContext[" << Context::cast(this)->length() << "]>"; 3484 case DEBUG_EVALUATE_CONTEXT_TYPE: 3485 os << "<DebugEvaluateContext[" << Context::cast(this)->length() << "]>"; 3487 case EVAL_CONTEXT_TYPE: 3488 os << "<EvalContext[" << Context::cast(this)->length() << "]>"; 3490 case FUNCTION_CONTEXT_TYPE: 3491 os << "<FunctionContext[" << Context::cast(this)->length() << "]>"; 3493 case MODULE_CONTEXT_TYPE: 3494 os << "<ModuleContext[" << Context::cast(this)->length() << "]>"; 3496 case NATIVE_CONTEXT_TYPE: 3497 os << "<NativeContext[" << Context::cast(this)->length() << "]>"; 3499 case SCRIPT_CONTEXT_TYPE: 3500 os << "<ScriptContext[" << Context::cast(this)->length() << "]>"; 3502 case WITH_CONTEXT_TYPE: 3503 os << "<WithContext[" << Context::cast(this)->length() << "]>"; 3505 case SCRIPT_CONTEXT_TABLE_TYPE: 3506 os << "<ScriptContextTable[" << FixedArray::cast(this)->length() << "]>"; 3508 case HASH_TABLE_TYPE: 3509 os << "<HashTable[" << FixedArray::cast(this)->length() << "]>"; 3511 case ORDERED_HASH_MAP_TYPE: 3512 os << "<OrderedHashMap[" << FixedArray::cast(this)->length() << "]>"; 3514 case ORDERED_HASH_SET_TYPE: 3515 os << "<OrderedHashSet[" << FixedArray::cast(this)->length() << "]>"; 3517 case ORDERED_NAME_DICTIONARY_TYPE: 3518 os << "<OrderedNameDictionary[" << FixedArray::cast(this)->length() 3521 case NAME_DICTIONARY_TYPE: 3522 os << "<NameDictionary[" << FixedArray::cast(this)->length() << "]>"; 3524 case GLOBAL_DICTIONARY_TYPE: 3525 os << "<GlobalDictionary[" << FixedArray::cast(this)->length() << "]>"; 3527 case NUMBER_DICTIONARY_TYPE: 3528 os << "<NumberDictionary[" << FixedArray::cast(this)->length() << "]>"; 3530 case SIMPLE_NUMBER_DICTIONARY_TYPE: 3531 os << "<SimpleNumberDictionary[" << FixedArray::cast(this)->length() 3534 case STRING_TABLE_TYPE: 3535 os << "<StringTable[" << FixedArray::cast(this)->length() << "]>"; 3537 case FIXED_ARRAY_TYPE: 3538 os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>"; 3540 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE: 3541 os << "<ObjectBoilerplateDescription[" << FixedArray::cast(this)->length() 3544 case FIXED_DOUBLE_ARRAY_TYPE: 3545 os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length() 3548 case BYTE_ARRAY_TYPE: 3549 os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>"; 3551 case BYTECODE_ARRAY_TYPE: 3552 os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>"; 3554 case DESCRIPTOR_ARRAY_TYPE: 3555 os << "<DescriptorArray[" 3556 << DescriptorArray::cast(this)->number_of_descriptors() << "]>"; 3558 case TRANSITION_ARRAY_TYPE: 3559 os << "<TransitionArray[" << TransitionArray::cast(this)->length() 3562 case PROPERTY_ARRAY_TYPE: 3563 os << "<PropertyArray[" << PropertyArray::cast(this)->length() << "]>"; 3565 case FEEDBACK_CELL_TYPE: { 3567 ReadOnlyRoots roots = GetReadOnlyRoots(); 3568 os << "<FeedbackCell["; 3569 if (map() == roots.no_closures_cell_map()) { 3570 os << "no feedback"; 3571 } else if (map() == roots.no_closures_cell_map()) { 3572 os << "no closures"; 3573 } else if (map() == roots.one_closure_cell_map()) { 3574 os << "one closure"; 3575 } else if (map() == roots.many_closures_cell_map()) { 3576 os << "many closures"; 3578 os << "!!!INVALID MAP!!!"; 3584 case FEEDBACK_VECTOR_TYPE: 3585 os << "<FeedbackVector[" << FeedbackVector::cast(this)->length() << "]>"; 3587 case FREE_SPACE_TYPE: 3588 os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>"; 3590 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype) \ 3591 case FIXED_##TYPE##_ARRAY_TYPE: \ 3592 os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \ 3596 TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT) 3597 #undef TYPED_ARRAY_SHORT_PRINT 3599 case PRE_PARSED_SCOPE_DATA_TYPE: { 3600 PreParsedScopeData* data = PreParsedScopeData::cast(this); 3601 os << "<PreParsedScopeData[" << data->length() << "]>"; 3605 case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE: { 3606 UncompiledDataWithoutPreParsedScope* data = 3607 UncompiledDataWithoutPreParsedScope::cast(this); 3608 os << "<UncompiledDataWithoutPreParsedScope (" << data->start_position() 3609 << ", " << data->end_position() << ")]>"; 3613 case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE: { 3614 UncompiledDataWithPreParsedScope* data = 3615 UncompiledDataWithPreParsedScope::cast(this); 3616 os << "<UncompiledDataWithPreParsedScope (" << data->start_position() 3617 << ", " << data->end_position() 3618 << ") preparsed=" << Brief(data->pre_parsed_scope_data()) << ">"; 3622 case SHARED_FUNCTION_INFO_TYPE: { 3623 SharedFunctionInfo* shared = SharedFunctionInfo::cast(this); 3624 std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString(); 3625 if (debug_name[0] != 0) { 3626 os << "<SharedFunctionInfo " << debug_name.get() << ">"; 3628 os << "<SharedFunctionInfo>"; 3632 case JS_MESSAGE_OBJECT_TYPE: 3633 os << "<JSMessageObject>"; 3635 #define MAKE_STRUCT_CASE(TYPE, Name, name) \ 3638 Name::cast(this)->BriefPrintDetails(os); \ 3641 STRUCT_LIST(MAKE_STRUCT_CASE) 3642 #undef MAKE_STRUCT_CASE 3643 case ALLOCATION_SITE_TYPE: { 3644 os << "<AllocationSite"; 3645 AllocationSite::cast(this)->BriefPrintDetails(os); 3649 case SCOPE_INFO_TYPE: { 3650 ScopeInfo scope = ScopeInfo::cast(this); 3652 if (scope->length()) os << " " << scope->scope_type() << " "; 3653 os << "[" << scope->length() << "]>"; 3657 Code code = Code::cast(this); 3658 os << "<Code " << Code::Kind2String(code->kind()); 3659 if (code->is_stub()) { 3660 os << " " << CodeStub::MajorName(CodeStub::GetMajorKey(code)); 3661 } else if (code->is_builtin()) { 3662 os << " " << Builtins::name(code->builtin_index()); 3667 case ODDBALL_TYPE: { 3668 if (IsUndefined()) { 3669 os << "<undefined>"; 3670 } else if (IsTheHole()) { 3672 } else if (IsNull()) { 3674 } else if (IsTrue()) { 3676 } else if (IsFalse()) { 3679 os << "<Odd Oddball: "; 3680 os << Oddball::cast(this)->to_string()->ToCString().get(); 3686 Symbol symbol = Symbol::cast(this); 3687 symbol->SymbolShortPrint(os); 3690 case HEAP_NUMBER_TYPE: { 3691 os << "<HeapNumber "; 3692 HeapNumber::cast(this)->HeapNumberPrint(os); 3696 case MUTABLE_HEAP_NUMBER_TYPE: { 3697 os << "<MutableHeapNumber "; 3698 MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os); 3704 BigInt::cast(this)->BigIntShortPrint(os); 3715 os << "<Cell value= "; 3716 HeapStringAllocator allocator; 3717 StringStream accumulator(&allocator); 3718 Cell::cast(this)->value()->ShortPrint(&accumulator); 3719 os << accumulator.ToCString().get(); 3723 case PROPERTY_CELL_TYPE: { 3724 PropertyCell* cell = PropertyCell::cast(this); 3725 os << "<PropertyCell name="; 3726 cell->name()->ShortPrint(os); 3728 HeapStringAllocator allocator; 3729 StringStream accumulator(&allocator); 3730 cell->value()->ShortPrint(&accumulator); 3731 os << accumulator.ToCString().get(); 3735 case CALL_HANDLER_INFO_TYPE: { 3736 CallHandlerInfo* info = CallHandlerInfo::cast(this); 3737 os << "<CallHandlerInfo "; 3738 os << "callback= " << Brief(info->callback()); 3739 os << ", js_callback= " << Brief(info->js_callback()); 3740 os << ", data= " << Brief(info->data()); 3741 if (info->IsSideEffectFreeCallHandlerInfo()) { 3742 os << ", side_effect_free= true>"; 3744 os << ", side_effect_free= false>"; 3749 os << "<Other heap object (" << map()->instance_type() << ")>"; 3754 void Struct::BriefPrintDetails(std::ostream& os) {} 3756 void Tuple2::BriefPrintDetails(std::ostream& os) { 3757 os << " " << Brief(value1()) << ", " << Brief(value2()); 3760 void Tuple3::BriefPrintDetails(std::ostream& os) { 3761 os << " " << Brief(value1()) << ", " << Brief(value2()) << ", " 3765 void ArrayBoilerplateDescription::BriefPrintDetails(std::ostream& os) { 3766 os << " " << elements_kind() << ", " << Brief(constant_elements()); 3769 void CallableTask::BriefPrintDetails(std::ostream& os) { 3770 os << " callable=" << Brief(callable()); 3773 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); } 3776 void HeapObject::IterateBody(ObjectVisitor* v) { 3778 IterateBodyFast<ObjectVisitor>(m, SizeFromMap(m), v); 3781 void HeapObject::IterateBody(Map map, int object_size, ObjectVisitor* v) { 3782 IterateBodyFast<ObjectVisitor>(map, object_size, v); 3786 struct CallIsValidSlot { 3787 template <typename BodyDescriptor> 3788 static bool apply(Map map, HeapObject* obj, int offset, int) { 3789 return BodyDescriptor::IsValidSlot(map, obj, offset); 3793 bool HeapObject::IsValidSlot(Map map, int offset) { 3794 DCHECK_NE(0, offset); 3795 return BodyDescriptorApply<CallIsValidSlot, bool>(map->instance_type(), map, 3799 String JSReceiver::class_name() { 3800 ReadOnlyRoots roots = GetReadOnlyRoots(); 3801 if (IsFunction()) return roots.Function_string(); 3802 if (IsJSArgumentsObject()) return roots.Arguments_string(); 3803 if (IsJSArray()) return roots.Array_string(); 3804 if (IsJSArrayBuffer()) { 3805 if (JSArrayBuffer::cast(this)->is_shared()) { 3806 return roots.SharedArrayBuffer_string(); 3808 return roots.ArrayBuffer_string(); 3810 if (IsJSArrayIterator()) return roots.ArrayIterator_string(); 3811 if (IsJSDate()) return roots.Date_string(); 3812 if (IsJSError()) return roots.Error_string(); 3813 if (IsJSGeneratorObject()) return roots.Generator_string(); 3814 if (IsJSMap()) return roots.Map_string(); 3815 if (IsJSMapIterator()) return roots.MapIterator_string(); 3817 return map()->is_callable() ? roots.Function_string() 3818 : roots.Object_string(); 3820 if (IsJSRegExp()) return roots.RegExp_string(); 3821 if (IsJSSet()) return roots.Set_string(); 3822 if (IsJSSetIterator()) return roots.SetIterator_string(); 3823 if (IsJSTypedArray()) { 3824 #define SWITCH_KIND(Type, type, TYPE, ctype) \ 3825 if (map()->elements_kind() == TYPE##_ELEMENTS) { \ 3826 return roots.Type##Array_string(); \ 3828 TYPED_ARRAYS(SWITCH_KIND) 3832 Object* value = JSValue::cast(this)->value(); 3833 if (value->IsBoolean()) return roots.Boolean_string(); 3834 if (value->IsString()) return roots.String_string(); 3835 if (value->IsNumber()) return roots.Number_string(); 3836 if (value->IsBigInt()) return roots.BigInt_string(); 3837 if (value->IsSymbol()) return roots.Symbol_string(); 3838 if (value->IsScript()) return roots.Script_string(); 3841 if (IsJSWeakMap()) return roots.WeakMap_string(); 3842 if (IsJSWeakSet()) return roots.WeakSet_string(); 3843 if (IsJSGlobalProxy()) return roots.global_string(); 3845 Object* maybe_constructor = map()->GetConstructor(); 3846 if (maybe_constructor->IsJSFunction()) { 3847 JSFunction* constructor = JSFunction::cast(maybe_constructor); 3848 if (constructor->shared()->IsApiFunction()) { 3849 maybe_constructor = constructor->shared()->get_api_func_data(); 3853 if (maybe_constructor->IsFunctionTemplateInfo()) { 3854 FunctionTemplateInfo* info = FunctionTemplateInfo::cast(maybe_constructor); 3855 if (info->class_name()->IsString()) return String::cast(info->class_name()); 3858 return roots.Object_string(); 3861 bool HeapObject::CanBeRehashed() const { 3862 DCHECK(NeedsRehashing()); 3863 switch (map()->instance_type()) { 3864 case ORDERED_HASH_MAP_TYPE: 3865 case ORDERED_HASH_SET_TYPE: 3866 case ORDERED_NAME_DICTIONARY_TYPE: 3867 // TODO(yangguo): actually support rehashing OrderedHash{Map,Set}. 3869 case NAME_DICTIONARY_TYPE: 3870 case GLOBAL_DICTIONARY_TYPE: 3871 case NUMBER_DICTIONARY_TYPE: 3872 case SIMPLE_NUMBER_DICTIONARY_TYPE: 3873 case STRING_TABLE_TYPE: 3875 case DESCRIPTOR_ARRAY_TYPE: 3877 case TRANSITION_ARRAY_TYPE: 3879 case SMALL_ORDERED_HASH_MAP_TYPE: 3880 return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0; 3881 case SMALL_ORDERED_HASH_SET_TYPE: 3882 return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0; 3883 case SMALL_ORDERED_NAME_DICTIONARY_TYPE: 3884 return SmallOrderedNameDictionary::cast(this)->NumberOfElements() == 0; 3891 void HeapObject::RehashBasedOnMap(Isolate* isolate) { 3892 switch (map()->instance_type()) { 3893 case HASH_TABLE_TYPE: 3896 case NAME_DICTIONARY_TYPE: 3897 NameDictionary::cast(this)->Rehash(isolate); 3899 case GLOBAL_DICTIONARY_TYPE: 3900 GlobalDictionary::cast(this)->Rehash(isolate); 3902 case NUMBER_DICTIONARY_TYPE: 3903 NumberDictionary::cast(this)->Rehash(isolate); 3905 case SIMPLE_NUMBER_DICTIONARY_TYPE: 3906 SimpleNumberDictionary::cast(this)->Rehash(isolate); 3908 case STRING_TABLE_TYPE: 3909 StringTable::cast(this)->Rehash(isolate); 3911 case DESCRIPTOR_ARRAY_TYPE: 3912 DCHECK_LE(1, DescriptorArray::cast(this)->number_of_descriptors()); 3913 DescriptorArray::cast(this)->Sort(); 3915 case TRANSITION_ARRAY_TYPE: 3916 TransitionArray::cast(this)->Sort(); 3918 case SMALL_ORDERED_HASH_MAP_TYPE: 3919 DCHECK_EQ(0, SmallOrderedHashMap::cast(this)->NumberOfElements()); 3921 case SMALL_ORDERED_HASH_SET_TYPE: 3922 DCHECK_EQ(0, SmallOrderedHashSet::cast(this)->NumberOfElements()); 3924 case SMALL_ORDERED_NAME_DICTIONARY_TYPE: 3925 DCHECK_EQ(0, SmallOrderedNameDictionary::cast(this)->NumberOfElements()); 3933 std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper( 3934 Handle<JSReceiver> receiver) { 3935 Isolate* isolate = receiver->GetIsolate(); 3937 // If the object was instantiated simply with base == new.target, the 3938 // constructor on the map provides the most accurate name. 3939 // Don't provide the info
for prototypes, since their constructors are
3941 if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
3942 !receiver->map()->is_prototype_map()) {
3943 Object* maybe_constructor = receiver->map()->GetConstructor();
3944 if (maybe_constructor->IsJSFunction()) {
3945 JSFunction* constructor = JSFunction::cast(maybe_constructor);
3946 String name = constructor->shared()->DebugName();
3947 if (name->length() != 0 &&
3949 return std::make_pair(handle(constructor, isolate),
3950 handle(name, isolate));
3952 }
else if (maybe_constructor->IsFunctionTemplateInfo()) {
3954 FunctionTemplateInfo::cast(maybe_constructor);
3955 if (info->class_name()->IsString()) {
3956 return std::make_pair(
3958 handle(String::cast(info->class_name()), isolate));
3964 receiver, isolate->factory()->to_string_tag_symbol());
3965 if (maybe_tag->IsString())
3970 if (iter.IsAtEnd()) {
3972 handle(receiver->class_name(), isolate));
3976 LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
3977 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
3978 Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
3979 if (maybe_constructor->IsJSFunction()) {
3980 JSFunction* constructor = JSFunction::cast(*maybe_constructor);
3981 String name = constructor->shared()->DebugName();
3983 if (name->length() != 0 &&
3984 !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
3985 return std::make_pair(handle(constructor, isolate),
3986 handle(name, isolate));
3990 return std::make_pair(MaybeHandle<JSFunction>(),
3991 handle(receiver->class_name(), isolate));
3996 MaybeHandle<JSFunction> JSReceiver::GetConstructor(
3997 Handle<JSReceiver> receiver) {
3998 return GetConstructorHelper(receiver).first;
4002 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
4003 return GetConstructorHelper(receiver).second;
4006 Handle<Context> JSReceiver::GetCreationContext() {
4007 JSReceiver* receiver =
this;
4009 DCHECK(!receiver->IsExternal(GetIsolate()));
4010 Object* constructor = receiver->map()->GetConstructor();
4011 JSFunction*
function;
4012 if (constructor->IsJSFunction()) {
4013 function = JSFunction::cast(constructor);
4014 }
else if (constructor->IsFunctionTemplateInfo()) {
4016 return Handle<Context>::null();
4020 CHECK(receiver->IsJSFunction());
4021 function = JSFunction::cast(receiver);
4024 return function->has_context()
4025 ? Handle<Context>(
function->context()->native_context(),
4026 receiver->GetIsolate())
4027 : Handle<Context>::null();
4031 MaybeObjectHandle Map::WrapFieldType(Isolate* isolate, Handle<FieldType> type) {
4032 if (type->IsClass()) {
4033 return MaybeObjectHandle::Weak(type->AsClass(), isolate);
4035 return MaybeObjectHandle(type);
4039 FieldType Map::UnwrapFieldType(MaybeObject wrapped_type) {
4040 if (wrapped_type->IsCleared()) {
4041 return FieldType::None();
4043 HeapObject* heap_object;
4044 if (wrapped_type->GetHeapObjectIfWeak(&heap_object)) {
4045 return FieldType::cast(heap_object);
4047 return wrapped_type->cast<FieldType>();
4050 MaybeHandle<Map> Map::CopyWithField(Isolate* isolate, Handle<Map> map,
4051 Handle<Name> name, Handle<FieldType> type,
4052 PropertyAttributes attributes,
4053 PropertyConstness constness,
4054 Representation representation,
4055 TransitionFlag flag) {
4056 DCHECK(DescriptorArray::kNotFound ==
4057 map->instance_descriptors()->Search(
4058 *name, map->NumberOfOwnDescriptors()));
4061 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
4062 return MaybeHandle<Map>();
4066 int index = map->NextFreePropertyIndex();
4068 if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
4069 constness = PropertyConstness::kMutable;
4070 representation = Representation::Tagged();
4071 type = FieldType::Any(isolate);
4073 Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
4074 isolate, map->instance_type(), &constness, &representation, &type);
4077 MaybeObjectHandle wrapped_type = WrapFieldType(isolate, type);
4079 DCHECK_IMPLIES(!FLAG_track_constant_fields,
4080 constness == PropertyConstness::kMutable);
4081 Descriptor d = Descriptor::DataField(name, index, attributes, constness,
4082 representation, wrapped_type);
4083 Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
4084 new_map->AccountAddedPropertyField();
4088 MaybeHandle<Map> Map::CopyWithConstant(Isolate* isolate, Handle<Map> map,
4090 Handle<Object> constant,
4091 PropertyAttributes attributes,
4092 TransitionFlag flag) {
4094 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
4095 return MaybeHandle<Map>();
4098 if (FLAG_track_constant_fields) {
4099 Representation representation = constant->OptimalRepresentation();
4100 Handle<FieldType> type = constant->OptimalType(isolate, representation);
4101 return CopyWithField(isolate, map, name, type, attributes,
4102 PropertyConstness::kConst, representation, flag);
4106 Descriptor::DataConstant(isolate, name, 0, constant, attributes);
4107 Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
4112 const char* Representation::Mnemonic()
const {
4114 case kNone:
return "v";
4115 case kTagged:
return "t";
4116 case kSmi:
return "s";
4117 case kDouble:
return "d";
4118 case kInteger32:
return "i";
4119 case kHeapObject:
return "h";
4120 case kExternal:
return "x";
4126 bool Map::TransitionRemovesTaggedField(Map target)
const {
4127 int inobject = NumberOfFields();
4128 int target_inobject = target->NumberOfFields();
4129 for (
int i = target_inobject;
i < inobject;
i++) {
4130 FieldIndex index = FieldIndex::ForPropertyIndex(*
this,
i);
4131 if (!IsUnboxedDoubleField(index))
return true;
4136 bool Map::TransitionChangesTaggedFieldToUntaggedField(Map target)
const {
4137 int inobject = NumberOfFields();
4138 int target_inobject = target->NumberOfFields();
4139 int limit = Min(inobject, target_inobject);
4140 for (
int i = 0;
i < limit;
i++) {
4141 FieldIndex index = FieldIndex::ForPropertyIndex(target,
i);
4142 if (!IsUnboxedDoubleField(index) && target->IsUnboxedDoubleField(index)) {
4149 bool Map::TransitionRequiresSynchronizationWithGC(Map target)
const {
4150 return TransitionRemovesTaggedField(target) ||
4151 TransitionChangesTaggedFieldToUntaggedField(target);
4154 bool Map::InstancesNeedRewriting(Map target)
const {
4155 int target_number_of_fields = target->NumberOfFields();
4156 int target_inobject = target->GetInObjectProperties();
4157 int target_unused = target->UnusedPropertyFields();
4158 int old_number_of_fields;
4160 return InstancesNeedRewriting(target, target_number_of_fields,
4161 target_inobject, target_unused,
4162 &old_number_of_fields);
4165 bool Map::InstancesNeedRewriting(Map target,
int target_number_of_fields,
4166 int target_inobject,
int target_unused,
4167 int* old_number_of_fields)
const {
4169 *old_number_of_fields = NumberOfFields();
4170 DCHECK(target_number_of_fields >= *old_number_of_fields);
4171 if (target_number_of_fields != *old_number_of_fields)
return true;
4174 DescriptorArray* old_desc = instance_descriptors();
4175 DescriptorArray* new_desc = target->instance_descriptors();
4176 int limit = NumberOfOwnDescriptors();
4177 for (
int i = 0;
i < limit;
i++) {
4178 if (new_desc->GetDetails(
i).representation().IsDouble() !=
4179 old_desc->GetDetails(
i).representation().IsDouble()) {
4186 if (target_inobject == GetInObjectProperties())
return false;
4190 DCHECK(target_inobject < GetInObjectProperties());
4191 if (target_number_of_fields <= target_inobject) {
4192 DCHECK(target_number_of_fields + target_unused == target_inobject);
4201 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
4202 Handle<Map> new_map,
4204 DCHECK(old_map->is_prototype_map());
4205 DCHECK(new_map->is_prototype_map());
4206 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
4207 new_map->set_prototype_info(old_map->prototype_info());
4208 old_map->set_prototype_info(Smi::kZero);
4209 if (FLAG_trace_prototype_users) {
4210 PrintF(
"Moving prototype_info %p from map %p to map %p.\n",
4211 reinterpret_cast<void*>(new_map->prototype_info()),
4212 reinterpret_cast<void*>(old_map->ptr()),
4213 reinterpret_cast<void*>(new_map->ptr()));
4215 if (was_registered) {
4216 if (new_map->prototype_info()->IsPrototypeInfo()) {
4219 PrototypeInfo::cast(new_map->prototype_info())
4220 ->set_registry_slot(PrototypeInfo::UNREGISTERED);
4222 JSObject::LazyRegisterPrototypeUser(new_map, isolate);
4242 void MigrateFastToFast(Handle<JSObject>
object, Handle<Map> new_map) {
4243 Isolate* isolate =
object->GetIsolate();
4244 Handle<Map> old_map(object->map(), isolate);
4246 if (new_map->GetBackPointer() == *old_map) {
4248 if (old_map->NumberOfOwnDescriptors() ==
4249 new_map->NumberOfOwnDescriptors()) {
4250 object->synchronized_set_map(*new_map);
4254 PropertyDetails details = new_map->GetLastDescriptorDetails();
4255 int target_index = details.field_index() - new_map->GetInObjectProperties();
4256 int property_array_length =
object->property_array()->length();
4257 bool have_space = old_map->UnusedPropertyFields() > 0 ||
4258 (details.location() == kField && target_index >= 0 &&
4259 property_array_length > target_index);
4263 if (details.location() == kDescriptor ||
4264 (have_space && ((FLAG_unbox_double_fields && target_index < 0) ||
4265 !details.representation().IsDouble()))) {
4266 object->synchronized_set_map(*new_map);
4274 FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
4275 DCHECK(details.representation().IsDouble());
4276 DCHECK(!new_map->IsUnboxedDoubleField(index));
4277 auto value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4278 object->RawFastPropertyAtPut(index, *value);
4279 object->synchronized_set_map(*new_map);
4285 int grow_by = new_map->UnusedPropertyFields() + 1;
4286 Handle<PropertyArray> old_storage(object->property_array(), isolate);
4287 Handle<PropertyArray> new_storage =
4288 isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by);
4291 Handle<Object> value;
4292 if (details.representation().IsDouble()) {
4293 value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4295 value = isolate->factory()->uninitialized_value();
4297 DCHECK_EQ(kField, details.location());
4298 DCHECK_EQ(kData, details.kind());
4299 DCHECK_GE(target_index, 0);
4300 new_storage->set(target_index, *value);
4303 DisallowHeapAllocation no_allocation;
4306 object->SetProperties(*new_storage);
4307 object->synchronized_set_map(*new_map);
4311 int old_number_of_fields;
4312 int number_of_fields = new_map->NumberOfFields();
4313 int inobject = new_map->GetInObjectProperties();
4314 int unused = new_map->UnusedPropertyFields();
4318 if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
4319 unused, &old_number_of_fields)) {
4320 object->synchronized_set_map(*new_map);
4324 int total_size = number_of_fields + unused;
4325 int external = total_size - inobject;
4326 Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external);
4329 Handle<FixedArray> inobject_props =
4330 isolate->factory()->NewFixedArray(inobject);
4332 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors(),
4334 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors(),
4336 int old_nof = old_map->NumberOfOwnDescriptors();
4337 int new_nof = new_map->NumberOfOwnDescriptors();
4341 DCHECK(old_nof <= new_nof);
4343 for (
int i = 0;
i < old_nof;
i++) {
4344 PropertyDetails details = new_descriptors->GetDetails(
i);
4345 if (details.location() != kField)
continue;
4346 DCHECK_EQ(kData, details.kind());
4347 PropertyDetails old_details = old_descriptors->GetDetails(
i);
4348 Representation old_representation = old_details.representation();
4349 Representation representation = details.representation();
4350 Handle<Object> value;
4351 if (old_details.location() == kDescriptor) {
4352 if (old_details.kind() == kAccessor) {
4355 DCHECK(!details.representation().IsNone());
4356 if (details.representation().IsDouble()) {
4357 value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4359 value = isolate->factory()->uninitialized_value();
4362 DCHECK_EQ(kData, old_details.kind());
4363 value = handle(old_descriptors->GetStrongValue(
i), isolate);
4364 DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
4367 DCHECK_EQ(kField, old_details.location());
4368 FieldIndex index = FieldIndex::ForDescriptor(*old_map,
i);
4369 if (object->IsUnboxedDoubleField(index)) {
4370 uint64_t old_bits =
object->RawFastDoublePropertyAsBitsAt(index);
4371 if (representation.IsDouble()) {
4372 value = isolate->factory()->NewMutableHeapNumberFromBits(old_bits);
4374 value = isolate->factory()->NewHeapNumberFromBits(old_bits);
4377 value = handle(object->RawFastPropertyAt(index), isolate);
4378 if (!old_representation.IsDouble() && representation.IsDouble()) {
4379 DCHECK_IMPLIES(old_representation.IsNone(),
4380 value->IsUninitialized(isolate));
4381 value = Object::NewStorageFor(isolate, value, representation);
4382 }
else if (old_representation.IsDouble() &&
4383 !representation.IsDouble()) {
4384 value = Object::WrapForRead(isolate, value, old_representation);
4388 DCHECK(!(representation.IsDouble() && value->IsSmi()));
4389 int target_index = new_descriptors->GetFieldIndex(
i);
4390 if (target_index < inobject) {
4391 inobject_props->set(target_index, *value);
4393 array->set(target_index - inobject, *value);
4397 for (
int i = old_nof;
i < new_nof;
i++) {
4398 PropertyDetails details = new_descriptors->GetDetails(
i);
4399 if (details.location() != kField)
continue;
4400 DCHECK_EQ(kData, details.kind());
4401 Handle<Object> value;
4402 if (details.representation().IsDouble()) {
4403 value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4405 value = isolate->factory()->uninitialized_value();
4407 int target_index = new_descriptors->GetFieldIndex(
i);
4408 if (target_index < inobject) {
4409 inobject_props->set(target_index, *value);
4411 array->set(target_index - inobject, *value);
4416 DisallowHeapAllocation no_allocation;
4418 Heap* heap = isolate->heap();
4420 int old_instance_size = old_map->instance_size();
4422 heap->NotifyObjectLayoutChange(*
object, old_instance_size, no_allocation);
4426 int limit = Min(inobject, number_of_fields);
4427 for (
int i = 0;
i < limit;
i++) {
4428 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map,
i);
4429 Object* value = inobject_props->get(
i);
4432 if (new_map->IsUnboxedDoubleField(index)) {
4433 DCHECK(value->IsMutableHeapNumber());
4435 object->RawFastDoublePropertyAsBitsAtPut(
4436 index, MutableHeapNumber::cast(value)->value_as_bits());
4437 if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
4439 heap->ClearRecordedSlot(*
object,
4440 HeapObject::RawField(*
object, index.offset()));
4443 heap->VerifyClearedSlot(*
object,
4444 HeapObject::RawField(*
object, index.offset()));
4448 object->RawFastPropertyAtPut(index, value);
4452 object->SetProperties(*array);
4455 int new_instance_size = new_map->instance_size();
4456 int instance_size_delta = old_instance_size - new_instance_size;
4457 DCHECK_GE(instance_size_delta, 0);
4459 if (instance_size_delta > 0) {
4460 Address address =
object->address();
4461 heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
4462 ClearRecordedSlots::kYes);
4467 object->synchronized_set_map(*new_map);
4470 void MigrateFastToSlow(Handle<JSObject>
object, Handle<Map> new_map,
4471 int expected_additional_properties) {
4473 DCHECK(!object->IsJSGlobalObject());
4475 DCHECK(!object->IsJSGlobalProxy());
4477 DCHECK_IMPLIES(new_map->is_prototype_map(),
4478 Map::IsPrototypeChainInvalidated(*new_map));
4480 Isolate* isolate =
object->GetIsolate();
4481 HandleScope scope(isolate);
4482 Handle<Map> map(object->map(), isolate);
4485 int real_size = map->NumberOfOwnDescriptors();
4486 int property_count = real_size;
4487 if (expected_additional_properties > 0) {
4488 property_count += expected_additional_properties;
4491 property_count += NameDictionary::kInitialCapacity;
4493 Handle<NameDictionary> dictionary =
4494 NameDictionary::New(isolate, property_count);
4496 Handle<DescriptorArray> descs(map->instance_descriptors(), isolate);
4497 for (
int i = 0;
i < real_size;
i++) {
4498 PropertyDetails details = descs->GetDetails(
i);
4499 Handle<Name> key(descs->GetKey(
i), isolate);
4500 Handle<Object> value;
4501 if (details.location() == kField) {
4502 FieldIndex index = FieldIndex::ForDescriptor(*map,
i);
4503 if (details.kind() == kData) {
4504 if (object->IsUnboxedDoubleField(index)) {
4505 double old_value =
object->RawFastDoublePropertyAt(index);
4506 value = isolate->factory()->NewHeapNumber(old_value);
4508 value = handle(object->RawFastPropertyAt(index), isolate);
4509 if (details.representation().IsDouble()) {
4510 DCHECK(value->IsMutableHeapNumber());
4511 double old_value = Handle<MutableHeapNumber>::cast(value)->value();
4512 value = isolate->factory()->NewHeapNumber(old_value);
4516 DCHECK_EQ(kAccessor, details.kind());
4517 value = handle(object->RawFastPropertyAt(index), isolate);
4521 DCHECK_EQ(kDescriptor, details.location());
4522 value = handle(descs->GetStrongValue(
i), isolate);
4524 DCHECK(!value.is_null());
4525 PropertyDetails d(details.kind(), details.attributes(),
4526 PropertyCellType::kNoCell);
4527 dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
4531 dictionary->SetNextEnumerationIndex(real_size + 1);
4534 DisallowHeapAllocation no_allocation;
4536 Heap* heap = isolate->heap();
4537 int old_instance_size = map->instance_size();
4538 heap->NotifyObjectLayoutChange(*
object, old_instance_size, no_allocation);
4541 int new_instance_size = new_map->instance_size();
4542 int instance_size_delta = old_instance_size - new_instance_size;
4543 DCHECK_GE(instance_size_delta, 0);
4545 if (instance_size_delta > 0) {
4546 heap->CreateFillerObjectAt(object->address() + new_instance_size,
4547 instance_size_delta, ClearRecordedSlots::kYes);
4552 object->synchronized_set_map(*new_map);
4554 object->SetProperties(*dictionary);
4558 int inobject_properties = new_map->GetInObjectProperties();
4559 if (inobject_properties) {
4560 Heap* heap = isolate->heap();
4561 heap->ClearRecordedSlotRange(
4562 object->address() + map->GetInObjectPropertyOffset(0),
4563 object->address() + new_instance_size);
4565 for (
int i = 0;
i < inobject_properties;
i++) {
4566 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map,
i);
4567 object->RawFastPropertyAtPut(index, Smi::kZero);
4571 isolate->counters()->props_to_dictionary()->Increment();
4574 if (FLAG_trace_normalization) {
4576 os <<
"Object properties have been normalized:\n";
4585 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
4587 if (!old_map->is_prototype_map())
return;
4589 InvalidatePrototypeChains(*old_map);
4596 UpdatePrototypeUserRegistration(old_map, new_map, isolate);
4599 void JSObject::MigrateToMap(Handle<JSObject>
object, Handle<Map> new_map,
4600 int expected_additional_properties) {
4601 if (object->map() == *new_map)
return;
4602 Handle<Map> old_map(object->map(),
object->GetIsolate());
4603 NotifyMapChange(old_map, new_map, object->GetIsolate());
4605 if (old_map->is_dictionary_map()) {
4608 CHECK(new_map->is_dictionary_map());
4611 object->synchronized_set_map(*new_map);
4612 }
else if (!new_map->is_dictionary_map()) {
4613 MigrateFastToFast(
object, new_map);
4614 if (old_map->is_prototype_map()) {
4615 DCHECK(!old_map->is_stable());
4616 DCHECK(new_map->is_stable());
4617 DCHECK(new_map->owns_descriptors());
4618 DCHECK(old_map->owns_descriptors());
4622 old_map->set_owns_descriptors(
false);
4623 DCHECK(old_map->is_abandoned_prototype_map());
4625 DCHECK_EQ(0, TransitionsAccessor(object->GetIsolate(), old_map)
4626 .NumberOfTransitions());
4627 DCHECK(new_map->GetBackPointer()->IsUndefined());
4628 DCHECK(object->map() != *old_map);
4631 MigrateFastToSlow(
object, new_map, expected_additional_properties);
4642 void JSObject::ForceSetPrototype(Handle<JSObject>
object,
4643 Handle<Object> proto) {
4645 Handle<Map> old_map = Handle<Map>(
object->map(),
object->GetIsolate());
4646 Handle<Map> new_map =
4647 Map::Copy(object->GetIsolate(), old_map,
"ForceSetPrototype");
4648 Map::SetPrototype(object->GetIsolate(), new_map, proto);
4649 JSObject::MigrateToMap(
object, new_map);
4652 int Map::NumberOfFields()
const {
4653 DescriptorArray* descriptors = instance_descriptors();
4655 for (
int i = 0;
i < NumberOfOwnDescriptors();
i++) {
4656 if (descriptors->GetDetails(
i).location() == kField) result++;
4661 Map::FieldCounts Map::GetFieldCounts()
const {
4662 DescriptorArray* descriptors = instance_descriptors();
4663 int mutable_count = 0;
4664 int const_count = 0;
4665 for (
int i = 0;
i < NumberOfOwnDescriptors();
i++) {
4666 PropertyDetails details = descriptors->GetDetails(
i);
4667 if (details.location() == kField) {
4668 switch (details.constness()) {
4669 case PropertyConstness::kMutable:
4672 case PropertyConstness::kConst:
4678 return FieldCounts(mutable_count, const_count);
4681 bool Map::HasOutOfObjectProperties()
const {
4682 return GetInObjectProperties() < NumberOfFields();
4685 void DescriptorArray::GeneralizeAllFields() {
4686 int length = number_of_descriptors();
4687 for (
int i = 0;
i < length;
i++) {
4688 PropertyDetails details = GetDetails(
i);
4689 details = details.CopyWithRepresentation(Representation::Tagged());
4690 if (details.location() == kField) {
4691 DCHECK_EQ(kData, details.kind());
4692 details = details.CopyWithConstness(PropertyConstness::kMutable);
4693 SetValue(
i, FieldType::Any());
4695 set(ToDetailsIndex(
i), MaybeObject::FromObject(details.AsSmi()));
4699 Handle<Map> Map::CopyGeneralizeAllFields(Isolate* isolate, Handle<Map> map,
4700 ElementsKind elements_kind,
4701 int modify_index, PropertyKind kind,
4702 PropertyAttributes attributes,
4703 const char* reason) {
4704 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
4705 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
4706 Handle<DescriptorArray> descriptors = DescriptorArray::CopyUpTo(
4707 isolate, old_descriptors, number_of_own_descriptors);
4708 descriptors->GeneralizeAllFields();
4710 Handle<LayoutDescriptor> new_layout_descriptor(
4711 LayoutDescriptor::FastPointerLayout(), isolate);
4712 Handle<Map> new_map = CopyReplaceDescriptors(
4713 isolate, map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
4714 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
4717 if (modify_index >= 0) {
4718 PropertyDetails details = descriptors->GetDetails(modify_index);
4719 if (details.constness() != PropertyConstness::kMutable ||
4720 details.location() != kField || details.attributes() != attributes) {
4721 int field_index = details.location() == kField
4722 ? details.field_index()
4723 : new_map->NumberOfFields();
4724 Descriptor d = Descriptor::DataField(
4725 isolate, handle(descriptors->GetKey(modify_index), isolate),
4726 field_index, attributes, Representation::Tagged());
4727 descriptors->Replace(modify_index, &d);
4728 if (details.location() != kField) {
4729 new_map->AccountAddedPropertyField();
4732 DCHECK(details.attributes() == attributes);
4735 if (FLAG_trace_generalization) {
4736 MaybeHandle<FieldType> field_type = FieldType::None(isolate);
4737 if (details.location() == kField) {
4738 field_type = handle(
4739 map->instance_descriptors()->GetFieldType(modify_index), isolate);
4741 map->PrintGeneralization(
4742 isolate, stdout, reason, modify_index,
4743 new_map->NumberOfOwnDescriptors(), new_map->NumberOfOwnDescriptors(),
4744 details.location() == kDescriptor, details.representation(),
4745 Representation::Tagged(), field_type, MaybeHandle<Object>(),
4746 FieldType::Any(isolate), MaybeHandle<Object>());
4749 new_map->set_elements_kind(elements_kind);
4753 void Map::DeprecateTransitionTree(Isolate* isolate) {
4754 if (is_deprecated())
return;
4755 DisallowHeapAllocation no_gc;
4756 TransitionsAccessor transitions(isolate, *
this, &no_gc);
4757 int num_transitions = transitions.NumberOfTransitions();
4758 for (
int i = 0;
i < num_transitions; ++
i) {
4759 transitions.GetTarget(
i)->DeprecateTransitionTree(isolate);
4761 DCHECK(!constructor_or_backpointer()->IsFunctionTemplateInfo());
4762 set_is_deprecated(
true);
4763 if (FLAG_trace_maps) {
4764 LOG(isolate, MapEvent(
"Deprecate", *
this, Map()));
4766 dependent_code()->DeoptimizeDependentCodeGroup(
4767 isolate, DependentCode::kTransitionGroup);
4768 NotifyLeafMapLayoutChange(isolate);
4774 void Map::ReplaceDescriptors(Isolate* isolate, DescriptorArray* new_descriptors,
4775 LayoutDescriptor new_layout_descriptor) {
4777 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
4781 DescriptorArray* to_replace = instance_descriptors();
4785 MarkingBarrierForElements(isolate->heap(), to_replace);
4786 Map current = *
this;
4787 while (current->instance_descriptors() == to_replace) {
4788 Object* next = current->GetBackPointer();
4789 if (next->IsUndefined(isolate))
break;
4790 current->SetEnumLength(kInvalidEnumCacheSentinel);
4791 current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
4792 current = Map::cast(next);
4794 set_owns_descriptors(
false);
4797 Map Map::FindRootMap(Isolate* isolate)
const {
4800 Object* back = result->GetBackPointer();
4801 if (back->IsUndefined(isolate)) {
4804 DCHECK(result->owns_descriptors());
4805 DCHECK_EQ(result->NumberOfOwnDescriptors(),
4806 result->instance_descriptors()->number_of_descriptors());
4809 result = Map::cast(back);
4813 Map Map::FindFieldOwner(Isolate* isolate,
int descriptor)
const {
4814 DisallowHeapAllocation no_allocation;
4815 DCHECK_EQ(kField, instance_descriptors()->GetDetails(descriptor).location());
4818 Object* back = result->GetBackPointer();
4819 if (back->IsUndefined(isolate))
break;
4820 const Map parent = Map::cast(back);
4821 if (parent->NumberOfOwnDescriptors() <= descriptor)
break;
4827 void Map::UpdateFieldType(Isolate* isolate,
int descriptor, Handle<Name> name,
4828 PropertyConstness new_constness,
4829 Representation new_representation,
4830 const MaybeObjectHandle& new_wrapped_type) {
4831 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeak());
4833 DisallowHeapAllocation no_allocation;
4834 PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
4835 if (details.location() != kField)
return;
4836 DCHECK_EQ(kData, details.kind());
4838 Zone zone(isolate->allocator(), ZONE_NAME);
4839 ZoneQueue<Map> backlog(&zone);
4840 backlog.push(*
this);
4842 while (!backlog.empty()) {
4843 Map current = backlog.front();
4846 TransitionsAccessor transitions(isolate, current, &no_allocation);
4847 int num_transitions = transitions.NumberOfTransitions();
4848 for (
int i = 0;
i < num_transitions; ++
i) {
4849 Map target = transitions.GetTarget(
i);
4850 backlog.push(target);
4852 DescriptorArray* descriptors = current->instance_descriptors();
4853 PropertyDetails details = descriptors->GetDetails(descriptor);
4856 DCHECK_IMPLIES(new_constness != details.constness(),
4857 FLAG_modify_map_inplace);
4860 DCHECK(details.representation().Equals(new_representation) ||
4861 details.representation().IsNone());
4864 if ((FLAG_modify_map_inplace && new_constness != details.constness()) ||
4865 descriptors->GetFieldType(descriptor) != *new_wrapped_type.object()) {
4866 DCHECK_IMPLIES(!FLAG_track_constant_fields,
4867 new_constness == PropertyConstness::kMutable);
4868 Descriptor d = Descriptor::DataField(
4869 name, descriptors->GetFieldIndex(descriptor), details.attributes(),
4870 new_constness, new_representation, new_wrapped_type);
4871 descriptors->Replace(descriptor, &d);
4876 bool FieldTypeIsCleared(Representation rep, FieldType type) {
4877 return type->IsNone() && rep.IsHeapObject();
4882 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
4883 Handle<FieldType> type1,
4884 Representation rep2,
4885 Handle<FieldType> type2,
4890 if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
4891 return FieldType::Any(isolate);
4893 if (type1->NowIs(type2))
return type2;
4894 if (type2->NowIs(type1))
return type1;
4895 return FieldType::Any(isolate);
4899 void Map::GeneralizeField(Isolate* isolate, Handle<Map> map,
int modify_index,
4900 PropertyConstness new_constness,
4901 Representation new_representation,
4902 Handle<FieldType> new_field_type) {
4904 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
4905 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4906 PropertyConstness old_constness = old_details.constness();
4907 Representation old_representation = old_details.representation();
4908 Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
4913 if (((FLAG_modify_map_inplace &&
4914 IsGeneralizableTo(new_constness, old_constness)) ||
4915 (!FLAG_modify_map_inplace && (old_constness == new_constness))) &&
4916 old_representation.Equals(new_representation) &&
4917 !FieldTypeIsCleared(new_representation, *new_field_type) &&
4920 new_field_type->NowIs(old_field_type)) {
4921 DCHECK(GeneralizeFieldType(old_representation, old_field_type,
4922 new_representation, new_field_type, isolate)
4923 ->NowIs(old_field_type));
4928 Handle<Map> field_owner(map->FindFieldOwner(isolate, modify_index), isolate);
4929 Handle<DescriptorArray> descriptors(field_owner->instance_descriptors(),
4931 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
4934 Map::GeneralizeFieldType(old_representation, old_field_type,
4935 new_representation, new_field_type, isolate);
4936 if (FLAG_modify_map_inplace) {
4937 new_constness = GeneralizeConstness(old_constness, new_constness);
4940 PropertyDetails details = descriptors->GetDetails(modify_index);
4941 Handle<Name> name(descriptors->GetKey(modify_index), isolate);
4943 MaybeObjectHandle wrapped_type(WrapFieldType(isolate, new_field_type));
4944 field_owner->UpdateFieldType(isolate, modify_index, name, new_constness,
4945 new_representation, wrapped_type);
4946 field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
4947 isolate, DependentCode::kFieldOwnerGroup);
4949 if (FLAG_trace_generalization) {
4950 map->PrintGeneralization(
4951 isolate, stdout,
"field type generalization", modify_index,
4952 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(),
false,
4953 details.representation(), details.representation(), old_field_type,
4954 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
4960 Handle<Map> Map::ReconfigureProperty(Isolate* isolate, Handle<Map> map,
4961 int modify_index, PropertyKind new_kind,
4962 PropertyAttributes new_attributes,
4963 Representation new_representation,
4964 Handle<FieldType> new_field_type) {
4965 DCHECK_EQ(kData, new_kind);
4966 MapUpdater mu(isolate, map);
4967 return mu.ReconfigureToDataField(modify_index, new_attributes,
4968 PropertyConstness::kConst,
4969 new_representation, new_field_type);
4974 Handle<Map> Map::ReconfigureElementsKind(Isolate* isolate, Handle<Map> map,
4975 ElementsKind new_elements_kind) {
4976 MapUpdater mu(isolate, map);
4977 return mu.ReconfigureElementsKind(new_elements_kind);
4982 Map SearchMigrationTarget(Isolate* isolate, Map old_map) {
4983 DisallowHeapAllocation no_allocation;
4984 DisallowDeoptimization no_deoptimization(isolate);
4986 Map target = old_map;
4988 target = TransitionsAccessor(isolate, target, &no_allocation)
4989 .GetMigrationTarget();
4990 }
while (!target.is_null() && target->is_deprecated());
4991 if (target.is_null())
return Map();
5001 int old_nof = old_map->NumberOfOwnDescriptors();
5002 DescriptorArray* old_descriptors = old_map->instance_descriptors();
5003 for (
int i = 0;
i < old_nof;
i++) {
5004 PropertyDetails old_details = old_descriptors->GetDetails(
i);
5005 if (old_details.location() == kField && old_details.kind() == kData) {
5006 FieldType old_type = old_descriptors->GetFieldType(
i);
5007 if (FieldTypeIsCleared(old_details.representation(), old_type)) {
5013 SLOW_DCHECK(Map::TryUpdateSlow(isolate, old_map) == target);
5020 MaybeHandle<Map> Map::TryUpdate(Isolate* isolate, Handle<Map> old_map) {
5021 DisallowHeapAllocation no_allocation;
5022 DisallowDeoptimization no_deoptimization(isolate);
5024 if (!old_map->is_deprecated())
return old_map;
5026 if (FLAG_fast_map_update) {
5027 Map target_map = SearchMigrationTarget(isolate, *old_map);
5028 if (!target_map.is_null()) {
5029 return handle(target_map, isolate);
5033 Map new_map = TryUpdateSlow(isolate, *old_map);
5034 if (new_map.is_null())
return MaybeHandle<Map>();
5035 if (FLAG_fast_map_update) {
5036 TransitionsAccessor(isolate, *old_map, &no_allocation)
5037 .SetMigrationTarget(new_map);
5039 return handle(new_map, isolate);
5042 Map Map::TryUpdateSlow(Isolate* isolate, Map old_map) {
5043 DisallowHeapAllocation no_allocation;
5044 DisallowDeoptimization no_deoptimization(isolate);
5047 Map root_map = old_map->FindRootMap(isolate);
5048 if (root_map->is_deprecated()) {
5049 JSFunction* constructor = JSFunction::cast(root_map->GetConstructor());
5050 DCHECK(constructor->has_initial_map());
5051 DCHECK(constructor->initial_map()->is_dictionary_map());
5052 if (constructor->initial_map()->elements_kind() !=
5053 old_map->elements_kind()) {
5056 return constructor->initial_map();
5058 if (!old_map->EquivalentToForTransition(root_map))
return Map();
5060 ElementsKind from_kind = root_map->elements_kind();
5061 ElementsKind to_kind = old_map->elements_kind();
5062 if (from_kind != to_kind) {
5064 root_map = root_map->LookupElementsTransitionMap(isolate, to_kind);
5065 if (root_map.is_null())
return Map();
5068 return root_map->TryReplayPropertyTransitions(isolate, old_map);
5071 Map Map::TryReplayPropertyTransitions(Isolate* isolate, Map old_map) {
5072 DisallowHeapAllocation no_allocation;
5073 DisallowDeoptimization no_deoptimization(isolate);
5075 int root_nof = NumberOfOwnDescriptors();
5077 int old_nof = old_map->NumberOfOwnDescriptors();
5078 DescriptorArray* old_descriptors = old_map->instance_descriptors();
5080 Map new_map = *
this;
5081 for (
int i = root_nof;
i < old_nof; ++
i) {
5082 PropertyDetails old_details = old_descriptors->GetDetails(
i);
5084 TransitionsAccessor(isolate, new_map, &no_allocation)
5085 .SearchTransition(old_descriptors->GetKey(
i), old_details.kind(),
5086 old_details.attributes());
5087 if (transition.is_null())
return Map();
5088 new_map = transition;
5089 DescriptorArray* new_descriptors = new_map->instance_descriptors();
5091 PropertyDetails new_details = new_descriptors->GetDetails(
i);
5092 DCHECK_EQ(old_details.kind(), new_details.kind());
5093 DCHECK_EQ(old_details.attributes(), new_details.attributes());
5094 if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
5097 DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
5098 if (!old_details.representation().fits_into(new_details.representation())) {
5101 if (new_details.location() == kField) {
5102 if (new_details.kind() == kData) {
5103 FieldType new_type = new_descriptors->GetFieldType(
i);
5106 if (FieldTypeIsCleared(new_details.representation(), new_type)) {
5109 DCHECK_EQ(kData, old_details.kind());
5110 if (old_details.location() == kField) {
5111 FieldType old_type = old_descriptors->GetFieldType(
i);
5112 if (FieldTypeIsCleared(old_details.representation(), old_type) ||
5113 !old_type->NowIs(new_type)) {
5117 DCHECK_EQ(kDescriptor, old_details.location());
5118 DCHECK(!FLAG_track_constant_fields);
5119 Object* old_value = old_descriptors->GetStrongValue(
i);
5120 if (!new_type->NowContains(old_value)) {
5126 DCHECK_EQ(kAccessor, new_details.kind());
5128 FieldType new_type = new_descriptors->GetFieldType(
i);
5129 DCHECK(new_type->IsAny());
5134 DCHECK_EQ(kDescriptor, new_details.location());
5135 if (old_details.location() == kField ||
5136 old_descriptors->GetStrongValue(
i) !=
5137 new_descriptors->GetStrongValue(
i)) {
5142 if (new_map->NumberOfOwnDescriptors() != old_nof)
return Map();
5148 Handle<Map> Map::Update(Isolate* isolate, Handle<Map> map) {
5149 if (!map->is_deprecated())
return map;
5150 if (FLAG_fast_map_update) {
5151 Map target_map = SearchMigrationTarget(isolate, *map);
5152 if (!target_map.is_null()) {
5153 return handle(target_map, isolate);
5156 MapUpdater mu(isolate, map);
5160 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
5161 ShouldThrow should_throw,
5162 Handle<Object> value) {
5163 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
5164 return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
5165 should_throw, value);
5168 MaybeHandle<Object> Object::SetProperty(Isolate* isolate, Handle<Object>
object,
5169 Handle<Name> name, Handle<Object> value,
5170 LanguageMode language_mode,
5171 StoreOrigin store_origin) {
5172 LookupIterator it(isolate,
object, name);
5173 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_origin));
5177 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
5178 Handle<Object> value,
5179 LanguageMode language_mode,
5180 StoreOrigin store_origin,
bool* found) {
5181 it->UpdateProtector();
5182 DCHECK(it->IsFound());
5183 ShouldThrow should_throw =
5184 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5188 AssertNoContextChange ncc(it->isolate());
5191 switch (it->state()) {
5192 case LookupIterator::NOT_FOUND:
5195 case LookupIterator::ACCESS_CHECK:
5196 if (it->HasAccess())
break;
5199 return JSObject::SetPropertyWithFailedAccessCheck(it, value,
5202 case LookupIterator::JSPROXY:
5203 return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
5204 value, it->GetReceiver(), language_mode);
5206 case LookupIterator::INTERCEPTOR: {
5207 if (it->HolderIsReceiverOrHiddenPrototype()) {
5208 Maybe<bool> result =
5209 JSObject::SetPropertyWithInterceptor(it, should_throw, value);
5210 if (result.IsNothing() || result.FromJust())
return result;
5212 Maybe<PropertyAttributes> maybe_attributes =
5213 JSObject::GetPropertyAttributesWithInterceptor(it);
5214 if (maybe_attributes.IsNothing())
return Nothing<bool>();
5215 if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
5216 return WriteToReadOnlyProperty(it, value, should_throw);
5218 if (maybe_attributes.FromJust() == ABSENT)
break;
5220 return Nothing<bool>();
5225 case LookupIterator::ACCESSOR: {
5226 if (it->IsReadOnly()) {
5227 return WriteToReadOnlyProperty(it, value, should_throw);
5229 Handle<Object> accessors = it->GetAccessors();
5230 if (accessors->IsAccessorInfo() &&
5231 !it->HolderIsReceiverOrHiddenPrototype() &&
5232 AccessorInfo::cast(*accessors)->is_special_data_property()) {
5234 return Nothing<bool>();
5236 return SetPropertyWithAccessor(it, value, should_throw);
5238 case LookupIterator::INTEGER_INDEXED_EXOTIC: {
5243 auto holder = it->GetHolder<JSTypedArray>();
5244 Handle<Object> throwaway_value;
5245 if (holder->type() == kExternalBigInt64Array ||
5246 holder->type() == kExternalBigUint64Array) {
5247 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5248 it->isolate(), throwaway_value,
5249 BigInt::FromObject(it->isolate(), value), Nothing<bool>());
5251 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5252 it->isolate(), throwaway_value,
5253 Object::ToNumber(it->isolate(), value), Nothing<bool>());
5266 case LookupIterator::DATA:
5267 if (it->IsReadOnly()) {
5268 return WriteToReadOnlyProperty(it, value, should_throw);
5270 if (it->HolderIsReceiverOrHiddenPrototype()) {
5271 return SetDataProperty(it, value);
5274 case LookupIterator::TRANSITION:
5276 return Nothing<bool>();
5279 }
while (it->IsFound());
5282 return Nothing<bool>();
5285 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
5286 LanguageMode language_mode,
5287 StoreOrigin store_origin) {
5288 if (it->IsFound()) {
5290 Maybe<bool> result =
5291 SetPropertyInternal(it, value, language_mode, store_origin, &found);
5292 if (found)
return result;
5298 if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
5299 it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
5300 MessageTemplate::kNotDefined, it->name()));
5301 return Nothing<bool>();
5304 ShouldThrow should_throw =
5305 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5306 return AddDataProperty(it, value, NONE, should_throw, store_origin);
5309 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
5310 LanguageMode language_mode,
5311 StoreOrigin store_origin) {
5312 Isolate* isolate = it->isolate();
5314 if (it->IsFound()) {
5316 Maybe<bool> result =
5317 SetPropertyInternal(it, value, language_mode, store_origin, &found);
5318 if (found)
return result;
5321 it->UpdateProtector();
5326 ShouldThrow should_throw =
5327 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5329 if (!it->GetReceiver()->IsJSReceiver()) {
5330 return WriteToReadOnlyProperty(it, value, should_throw);
5332 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
5334 LookupIterator::Configuration c = LookupIterator::OWN;
5335 LookupIterator own_lookup =
5336 it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
5337 : LookupIterator(isolate, receiver, it->name(), c);
5339 for (; own_lookup.IsFound(); own_lookup.Next()) {
5340 switch (own_lookup.state()) {
5341 case LookupIterator::ACCESS_CHECK:
5342 if (!own_lookup.HasAccess()) {
5343 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
5348 case LookupIterator::ACCESSOR:
5349 if (own_lookup.GetAccessors()->IsAccessorInfo()) {
5350 if (own_lookup.IsReadOnly()) {
5351 return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
5353 return JSObject::SetPropertyWithAccessor(&own_lookup, value,
5357 case LookupIterator::INTEGER_INDEXED_EXOTIC:
5358 return RedefineIncompatibleProperty(isolate, it->GetName(), value,
5361 case LookupIterator::DATA: {
5362 if (own_lookup.IsReadOnly()) {
5363 return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
5365 return SetDataProperty(&own_lookup, value);
5368 case LookupIterator::INTERCEPTOR:
5369 case LookupIterator::JSPROXY: {
5370 PropertyDescriptor desc;
5372 JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
5373 MAYBE_RETURN(owned, Nothing<bool>());
5374 if (!owned.FromJust()) {
5375 return JSReceiver::CreateDataProperty(&own_lookup, value,
5378 if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
5380 return RedefineIncompatibleProperty(isolate, it->GetName(), value,
5384 PropertyDescriptor value_desc;
5385 value_desc.set_value(value);
5386 return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
5387 &value_desc, should_throw);
5390 case LookupIterator::NOT_FOUND:
5391 case LookupIterator::TRANSITION:
5396 return AddDataProperty(&own_lookup, value, NONE, should_throw, store_origin);
5399 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
5400 Handle<Object> receiver,
5401 Handle<Object> name,
5402 Handle<Object> value,
5403 ShouldThrow should_throw) {
5405 isolate, should_throw,
5406 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
5407 Object::TypeOf(isolate, receiver), receiver));
5411 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
5412 Handle<Object> value,
5413 ShouldThrow should_throw) {
5414 if (it->IsFound() && !it->HolderIsReceiver()) {
5417 v8::Isolate::UseCounterFeature feature =
5418 should_throw == kThrowOnError
5419 ? v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeStrict
5420 : v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeSloppy;
5421 it->isolate()->CountUsage(feature);
5423 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
5424 it->GetName(), value, should_throw);
5428 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
5429 Handle<Object> receiver,
5430 Handle<Object> name,
5431 Handle<Object> value,
5432 ShouldThrow should_throw) {
5433 RETURN_FAILURE(isolate, should_throw,
5434 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
5435 Object::TypeOf(isolate, receiver), receiver));
5439 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
5440 Handle<Object> name,
5441 Handle<Object> value,
5442 ShouldThrow should_throw) {
5443 RETURN_FAILURE(isolate, should_throw,
5444 NewTypeError(MessageTemplate::kRedefineDisallowed, name));
5448 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
5449 DCHECK_IMPLIES(it->GetReceiver()->IsJSProxy(),
5450 it->GetName()->IsPrivateName());
5451 DCHECK_IMPLIES(!it->IsElement() && it->GetName()->IsPrivateName(),
5452 it->state() == LookupIterator::DATA);
5453 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
5456 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
5458 Handle<Object> to_assign = value;
5460 if (it->IsElement() && receiver->IsJSObject() &&
5461 JSObject::cast(*receiver)->HasFixedTypedArrayElements()) {
5462 ElementsKind elements_kind = JSObject::cast(*receiver)->GetElementsKind();
5463 if (elements_kind == BIGINT64_ELEMENTS ||
5464 elements_kind == BIGUINT64_ELEMENTS) {
5465 ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
5466 BigInt::FromObject(it->isolate(), value),
5470 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
5474 }
else if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
5475 ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
5476 Object::ToNumber(it->isolate(), value),
5480 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
5489 it->PrepareForDataProperty(to_assign);
5492 it->WriteDataValue(to_assign,
false);
5495 if (FLAG_verify_heap) {
5496 receiver->HeapObjectVerify(it->isolate());
5502 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
5503 PropertyAttributes attributes,
5504 ShouldThrow should_throw,
5505 StoreOrigin store_origin) {
5506 if (!it->GetReceiver()->IsJSReceiver()) {
5507 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
5508 value, should_throw);
5513 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate() &&
5514 !it->GetName()->IsPrivateName()) {
5515 RETURN_FAILURE(it->isolate(), should_throw,
5516 NewTypeError(MessageTemplate::kProxyPrivate));
5519 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
5521 Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
5522 DCHECK_IMPLIES(receiver->IsJSProxy(), it->GetName()->IsPrivateName());
5523 DCHECK_IMPLIES(receiver->IsJSProxy(),
5524 it->state() == LookupIterator::NOT_FOUND);
5528 if (receiver->IsJSGlobalProxy())
return Just(
true);
5530 Isolate* isolate = it->isolate();
5532 if (it->ExtendingNonExtensible(receiver)) {
5534 isolate, should_throw,
5535 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
5538 if (it->IsElement()) {
5539 if (receiver->IsJSArray()) {
5540 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
5541 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
5542 RETURN_FAILURE(isolate, should_throw,
5543 NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
5544 isolate->factory()->length_string(),
5545 Object::TypeOf(isolate, array), array));
5548 if (FLAG_trace_external_array_abuse &&
5549 array->HasFixedTypedArrayElements()) {
5550 CheckArrayAbuse(array,
"typed elements write", it->index(),
true);
5553 if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
5554 CheckArrayAbuse(array,
"elements write", it->index(),
false);
5558 Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
5559 JSObject::AddDataElement(receiver_obj, it->index(), value, attributes);
5560 JSObject::ValidateElements(*receiver_obj);
5563 it->UpdateProtector();
5566 it->PrepareTransitionToDataProperty(receiver, value, attributes,
5568 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
5569 it->ApplyTransitionToDataProperty(receiver);
5572 it->WriteDataValue(value,
true);
5575 if (FLAG_verify_heap) {
5576 receiver->HeapObjectVerify(isolate);
5584 void Map::EnsureDescriptorSlack(Isolate* isolate, Handle<Map> map,
int slack) {
5586 DCHECK(map->owns_descriptors());
5588 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
5589 int old_size = map->NumberOfOwnDescriptors();
5590 if (slack <= descriptors->number_of_slack_descriptors())
return;
5592 Handle<DescriptorArray> new_descriptors =
5593 DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
5595 DisallowHeapAllocation no_allocation;
5597 LayoutDescriptor layout_descriptor = map->GetLayoutDescriptor();
5599 if (old_size == 0) {
5600 map->UpdateDescriptors(*new_descriptors, layout_descriptor);
5609 new_descriptors->CopyEnumCacheFrom(*descriptors);
5614 MarkingBarrierForElements(isolate->heap(), *descriptors);
5617 while (current->instance_descriptors() == *descriptors) {
5618 Object* next = current->GetBackPointer();
5619 if (next->IsUndefined(isolate))
break;
5620 current->UpdateDescriptors(*new_descriptors, layout_descriptor);
5621 current = Map::cast(next);
5623 map->UpdateDescriptors(*new_descriptors, layout_descriptor);
5627 Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,
5628 Handle<HeapObject> prototype) {
5629 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
5631 if (map->prototype() == *prototype)
return map;
5632 if (prototype->IsNull(isolate)) {
5633 return isolate->slow_object_with_null_prototype_map();
5635 if (prototype->IsJSObject()) {
5636 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
5637 if (!js_prototype->map()->is_prototype_map()) {
5638 JSObject::OptimizeAsPrototype(js_prototype);
5640 Handle<PrototypeInfo> info =
5641 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
5643 if (info->HasObjectCreateMap()) {
5644 map = handle(info->ObjectCreateMap(), isolate);
5646 map = Map::CopyInitialMap(isolate, map);
5647 Map::SetPrototype(isolate, map, prototype);
5648 PrototypeInfo::SetObjectCreateMap(info, map);
5653 return Map::TransitionToPrototype(isolate, map, prototype);
5657 MaybeHandle<Map> Map::TryGetObjectCreateMap(Isolate* isolate,
5658 Handle<HeapObject> prototype) {
5659 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
5661 if (map->prototype() == *prototype)
return map;
5662 if (prototype->IsNull(isolate)) {
5663 return isolate->slow_object_with_null_prototype_map();
5665 if (!prototype->IsJSObject())
return MaybeHandle<Map>();
5666 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
5667 if (!js_prototype->map()->is_prototype_map())
return MaybeHandle<Map>();
5668 Handle<PrototypeInfo> info =
5669 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
5670 if (!info->HasObjectCreateMap())
return MaybeHandle<Map>();
5671 return handle(info->ObjectCreateMap(), isolate);
5675 static int AppendUniqueCallbacks(Isolate* isolate,
5676 Handle<TemplateList> callbacks,
5677 Handle<typename T::Array> array,
5678 int valid_descriptors) {
5679 int nof_callbacks = callbacks->length();
5684 for (
int i = nof_callbacks - 1;
i >= 0;
i--) {
5685 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(
i)), isolate);
5686 Handle<Name> key(Name::cast(entry->name()), isolate);
5687 DCHECK(key->IsUniqueName());
5689 if (!T::Contains(key, entry, valid_descriptors, array)) {
5690 T::Insert(key, entry, valid_descriptors, array);
5691 valid_descriptors++;
5695 return valid_descriptors;
5702 int valid_descriptors,
5704 for (
int i = 0;
i < valid_descriptors;
i++) {
5705 if (*key == AccessorInfo::cast(array->get(
i))->name())
return true;
5711 int valid_descriptors,
5714 array->set(valid_descriptors, *entry);
5720 int valid_descriptors) {
5722 DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
5723 return AppendUniqueCallbacks<FixedArrayAppender>(isolate, callbacks, array,
5727 static bool ContainsMap(MapHandles
const& maps,
Map map) {
5728 DCHECK(!map.is_null());
5730 if (!current.is_null() && *current == map)
return true;
5735 Map Map::FindElementsKindTransitionedMap(Isolate* isolate,
5736 MapHandles
const& candidates) {
5737 DisallowHeapAllocation no_allocation;
5738 DisallowDeoptimization no_deoptimization(isolate);
5740 if (is_prototype_map())
return Map();
5742 ElementsKind kind = elements_kind();
5743 bool packed = IsFastPackedElementsKind(kind);
5746 if (IsTransitionableFastElementsKind(kind)) {
5748 Map root_map = FindRootMap(isolate);
5749 if (!EquivalentToForElementsKindTransition(root_map))
return Map();
5750 root_map = root_map->LookupElementsTransitionMap(isolate, kind);
5751 DCHECK(!root_map.is_null());
5755 for (root_map = root_map->ElementsTransitionMap();
5756 !root_map.is_null() && root_map->has_fast_elements();
5757 root_map = root_map->ElementsTransitionMap()) {
5758 Map current = root_map->TryReplayPropertyTransitions(isolate, *
this);
5759 if (current.is_null())
continue;
5760 if (InstancesNeedRewriting(current))
continue;
5762 if (ContainsMap(candidates, current) &&
5763 (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
5764 transition = current;
5765 packed = packed && IsFastPackedElementsKind(current->elements_kind());
5772 static Map FindClosestElementsTransition(Isolate* isolate, Map map,
5773 ElementsKind to_kind) {
5775 DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
5776 map->NumberOfOwnDescriptors());
5777 Map current_map = map;
5779 ElementsKind kind = map->elements_kind();
5780 while (kind != to_kind) {
5781 Map next_map = current_map->ElementsTransitionMap();
5782 if (next_map.is_null())
return current_map;
5783 kind = next_map->elements_kind();
5784 current_map = next_map;
5787 DCHECK_EQ(to_kind, current_map->elements_kind());
5791 Map Map::LookupElementsTransitionMap(Isolate* isolate, ElementsKind to_kind) {
5792 Map to_map = FindClosestElementsTransition(isolate, *
this, to_kind);
5793 if (to_map->elements_kind() == to_kind)
return to_map;
5797 bool Map::IsMapInArrayPrototypeChain(Isolate* isolate)
const {
5798 if (isolate->initial_array_prototype()->map() == *
this) {
5802 if (isolate->initial_object_prototype()->map() == *
this) {
5809 static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
5811 ElementsKind to_kind) {
5812 DCHECK(IsTransitionElementsKind(map->elements_kind()));
5814 Handle<Map> current_map = map;
5816 ElementsKind kind = map->elements_kind();
5817 TransitionFlag flag;
5818 if (map->is_prototype_map()) {
5819 flag = OMIT_TRANSITION;
5821 flag = INSERT_TRANSITION;
5822 if (IsFastElementsKind(kind)) {
5823 while (kind != to_kind && !IsTerminalElementsKind(kind)) {
5824 kind = GetNextTransitionElementsKind(kind);
5825 current_map = Map::CopyAsElementsKind(isolate, current_map, kind, flag);
5832 if (kind != to_kind) {
5833 current_map = Map::CopyAsElementsKind(isolate, current_map, to_kind, flag);
5836 DCHECK(current_map->elements_kind() == to_kind);
5840 Handle<Map> Map::TransitionElementsTo(Isolate* isolate, Handle<Map> map,
5841 ElementsKind to_kind) {
5842 ElementsKind from_kind = map->elements_kind();
5843 if (from_kind == to_kind)
return map;
5845 Context native_context = isolate->context()->native_context();
5846 if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
5847 if (*map == native_context->fast_aliased_arguments_map()) {
5848 DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5849 return handle(native_context->slow_aliased_arguments_map(), isolate);
5851 }
else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
5852 if (*map == native_context->slow_aliased_arguments_map()) {
5853 DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5854 return handle(native_context->fast_aliased_arguments_map(), isolate);
5856 }
else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
5858 DisallowHeapAllocation no_gc;
5859 if (native_context->GetInitialJSArrayMap(from_kind) == *map) {
5860 Object* maybe_transitioned_map =
5861 native_context->get(Context::ArrayMapIndex(to_kind));
5862 if (maybe_transitioned_map->IsMap()) {
5863 return handle(Map::cast(maybe_transitioned_map), isolate);
5868 DCHECK(!map->IsUndefined(isolate));
5870 if (IsHoleyElementsKind(from_kind) &&
5871 to_kind == GetPackedElementsKind(from_kind) &&
5872 map->GetBackPointer()->IsMap() &&
5873 Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
5874 return handle(Map::cast(map->GetBackPointer()), isolate);
5877 bool allow_store_transition = IsTransitionElementsKind(from_kind);
5879 if (IsFastElementsKind(to_kind)) {
5880 allow_store_transition =
5881 allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
5882 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
5885 if (!allow_store_transition) {
5886 return Map::CopyAsElementsKind(isolate, map, to_kind, OMIT_TRANSITION);
5889 return Map::ReconfigureElementsKind(isolate, map, to_kind);
5894 Handle<Map> Map::AsElementsKind(Isolate* isolate, Handle<Map> map,
5895 ElementsKind kind) {
5896 Handle<Map> closest_map(FindClosestElementsTransition(isolate, *map, kind),
5899 if (closest_map->elements_kind() == kind) {
5903 return AddMissingElementsTransitions(isolate, closest_map, kind);
5907 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject>
object,
5908 ElementsKind to_kind) {
5909 Handle<Map> map(object->map(),
object->GetIsolate());
5910 return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind);
5914 void JSProxy::Revoke(Handle<JSProxy> proxy) {
5915 Isolate* isolate = proxy->GetIsolate();
5917 if (!proxy->IsRevoked()) {
5919 proxy->set_target(ReadOnlyRoots(isolate).null_value());
5921 proxy->set_handler(ReadOnlyRoots(isolate).null_value());
5923 DCHECK(proxy->IsRevoked());
5927 Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) {
5928 Isolate* isolate = proxy->GetIsolate();
5929 Handle<JSReceiver>
object = Handle<JSReceiver>::cast(proxy);
5930 for (
int i = 0;
i < JSProxy::kMaxIterationLimit;
i++) {
5931 Handle<JSProxy> proxy = Handle<JSProxy>::cast(
object);
5932 if (proxy->IsRevoked()) {
5933 isolate->Throw(*isolate->factory()->NewTypeError(
5934 MessageTemplate::kProxyRevoked,
5935 isolate->factory()->NewStringFromAsciiChecked(
"IsArray")));
5936 return Nothing<bool>();
5938 object = handle(JSReceiver::cast(proxy->target()), isolate);
5939 if (object->IsJSArray())
return Just(
true);
5940 if (!object->IsJSProxy())
return Just(
false);
5944 isolate->StackOverflow();
5945 return Nothing<bool>();
5948 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
5949 Handle<Name> name) {
5950 DCHECK(!name->IsPrivate());
5951 STACK_CHECK(isolate, Nothing<bool>());
5954 Handle<Object> handler(proxy->handler(), isolate);
5957 if (proxy->IsRevoked()) {
5958 isolate->Throw(*isolate->factory()->NewTypeError(
5959 MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
5960 return Nothing<bool>();
5963 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
5965 Handle<Object> trap;
5966 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5967 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
5968 isolate->factory()->has_string()),
5971 if (trap->IsUndefined(isolate)) {
5973 return JSReceiver::HasProperty(target, name);
5976 Handle<Object> trap_result_obj;
5977 Handle<Object> args[] = {target, name};
5978 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5979 isolate, trap_result_obj,
5980 Execution::Call(isolate, trap, handler, arraysize(args), args),
5982 bool boolean_trap_result = trap_result_obj->BooleanValue(isolate);
5984 if (!boolean_trap_result) {
5985 MAYBE_RETURN(JSProxy::CheckHasTrap(isolate, name, target), Nothing<bool>());
5988 return Just(boolean_trap_result);
5991 Maybe<bool> JSProxy::CheckHasTrap(Isolate* isolate, Handle<Name> name,
5992 Handle<JSReceiver> target) {
5994 PropertyDescriptor target_desc;
5995 Maybe<bool> target_found =
5996 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
5997 MAYBE_RETURN(target_found, Nothing<bool>());
5999 if (target_found.FromJust()) {
6002 if (!target_desc.configurable()) {
6003 isolate->Throw(*isolate->factory()->NewTypeError(
6004 MessageTemplate::kProxyHasNonConfigurable, name));
6005 return Nothing<bool>();
6008 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
6009 MAYBE_RETURN(extensible_target, Nothing<bool>());
6011 if (!extensible_target.FromJust()) {
6012 isolate->Throw(*isolate->factory()->NewTypeError(
6013 MessageTemplate::kProxyHasNonExtensible, name));
6014 return Nothing<bool>();
6020 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
6021 Handle<Object> value, Handle<Object> receiver,
6022 LanguageMode language_mode) {
6023 DCHECK(!name->IsPrivate());
6024 Isolate* isolate = proxy->GetIsolate();
6025 STACK_CHECK(isolate, Nothing<bool>());
6026 Factory* factory = isolate->factory();
6027 Handle<String> trap_name = factory->set_string();
6028 ShouldThrow should_throw =
6029 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
6031 if (proxy->IsRevoked()) {
6033 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
6034 return Nothing<bool>();
6036 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
6037 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
6039 Handle<Object> trap;
6040 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6041 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
6042 if (trap->IsUndefined(isolate)) {
6044 LookupIterator::PropertyOrElement(isolate, receiver, name, target);
6045 return Object::SetSuperProperty(&it, value, language_mode,
6046 StoreOrigin::kMaybeKeyed);
6049 Handle<Object> trap_result;
6050 Handle<Object> args[] = {target, name, value, receiver};
6051 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6052 isolate, trap_result,
6053 Execution::Call(isolate, trap, handler, arraysize(args), args),
6055 if (!trap_result->BooleanValue(isolate)) {
6056 RETURN_FAILURE(isolate, should_throw,
6057 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
6061 MaybeHandle<Object> result =
6062 JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet);
6064 if (result.is_null()) {
6065 return Nothing<bool>();
6071 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
6073 LanguageMode language_mode) {
6074 DCHECK(!name->IsPrivate());
6075 ShouldThrow should_throw =
6076 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
6077 Isolate* isolate = proxy->GetIsolate();
6078 STACK_CHECK(isolate, Nothing<bool>());
6079 Factory* factory = isolate->factory();
6080 Handle<String> trap_name = factory->deleteProperty_string();
6082 if (proxy->IsRevoked()) {
6084 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
6085 return Nothing<bool>();
6087 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
6088 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
6090 Handle<Object> trap;
6091 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6092 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
6093 if (trap->IsUndefined(isolate)) {
6094 return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
6097 Handle<Object> trap_result;
6098 Handle<Object> args[] = {target, name};
6099 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6100 isolate, trap_result,
6101 Execution::Call(isolate, trap, handler, arraysize(args), args),
6103 if (!trap_result->BooleanValue(isolate)) {
6104 RETURN_FAILURE(isolate, should_throw,
6105 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
6110 PropertyDescriptor target_desc;
6112 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
6113 MAYBE_RETURN(owned, Nothing<bool>());
6114 if (owned.FromJust() && !target_desc.configurable()) {
6115 isolate->Throw(*factory->NewTypeError(
6116 MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
6117 return Nothing<bool>();
6124 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
6125 Handle<Object> handler) {
6126 if (!target->IsJSReceiver()) {
6127 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
6130 if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
6131 THROW_NEW_ERROR(isolate,
6132 NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
6135 if (!handler->IsJSReceiver()) {
6136 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
6139 if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
6140 THROW_NEW_ERROR(isolate,
6141 NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
6144 return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
6145 Handle<JSReceiver>::cast(handler));
6150 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
6151 DCHECK(proxy->map()->is_constructor());
6152 if (proxy->IsRevoked()) {
6153 THROW_NEW_ERROR(proxy->GetIsolate(),
6154 NewTypeError(MessageTemplate::kProxyRevoked), Context);
6156 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()),
6157 proxy->GetIsolate());
6158 return JSReceiver::GetFunctionRealm(target);
6163 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
6164 Handle<JSBoundFunction>
function) {
6165 DCHECK(function->map()->is_constructor());
6166 return JSReceiver::GetFunctionRealm(
6167 handle(function->bound_target_function(),
function->GetIsolate()));
6171 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
6172 Handle<JSBoundFunction>
function) {
6173 Handle<String> prefix = isolate->factory()->bound__string();
6174 Handle<String> target_name = prefix;
6175 Factory* factory = isolate->factory();
6177 while (function->bound_target_function()->IsJSBoundFunction()) {
6178 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_name,
6179 factory->NewConsString(prefix, target_name),
6181 function = handle(JSBoundFunction::cast(function->bound_target_function()),
6184 if (function->bound_target_function()->IsJSFunction()) {
6185 Handle<JSFunction> target(
6186 JSFunction::cast(function->bound_target_function()), isolate);
6187 Handle<Object> name = JSFunction::GetName(isolate, target);
6188 if (!name->IsString())
return target_name;
6189 return factory->NewConsString(target_name, Handle<String>::cast(name));
6196 Maybe<int> JSBoundFunction::GetLength(Isolate* isolate,
6197 Handle<JSBoundFunction>
function) {
6198 int nof_bound_arguments =
function->bound_arguments()->length();
6199 while (function->bound_target_function()->IsJSBoundFunction()) {
6200 function = handle(JSBoundFunction::cast(function->bound_target_function()),
6205 int length =
function->bound_arguments()->length();
6206 if (V8_LIKELY(Smi::kMaxValue - nof_bound_arguments > length)) {
6207 nof_bound_arguments += length;
6209 nof_bound_arguments = Smi::kMaxValue;
6214 Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
6216 Maybe<int> target_length = JSFunction::GetLength(isolate, target);
6217 if (target_length.IsNothing())
return target_length;
6219 int length = Max(0, target_length.FromJust() - nof_bound_arguments);
6220 return Just(length);
6224 Handle<Object> JSFunction::GetName(Isolate* isolate,
6225 Handle<JSFunction>
function) {
6226 if (function->shared()->name_should_print_as_anonymous()) {
6227 return isolate->factory()->anonymous_string();
6229 return handle(function->shared()->Name(), isolate);
6233 Maybe<int> JSFunction::GetLength(Isolate* isolate,
6234 Handle<JSFunction>
function) {
6236 if (function->shared()->is_compiled()) {
6237 length =
function->shared()->GetLength();
6241 if (Compiler::Compile(
function, Compiler::KEEP_EXCEPTION)) {
6242 length =
function->shared()->GetLength();
6244 if (isolate->has_pending_exception())
return Nothing<int>();
6246 DCHECK_GE(length, 0);
6247 return Just(length);
6251 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction>
function) {
6252 DCHECK(function->map()->is_constructor());
6253 return handle(function->context()->native_context(),
function->GetIsolate());
6258 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject>
object) {
6259 DCHECK(object->map()->is_constructor());
6260 DCHECK(!object->IsJSFunction());
6261 return object->GetCreationContext();
6266 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
6267 if (receiver->IsJSProxy()) {
6268 return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
6271 if (receiver->IsJSFunction()) {
6272 return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
6275 if (receiver->IsJSBoundFunction()) {
6276 return JSBoundFunction::GetFunctionRealm(
6277 Handle<JSBoundFunction>::cast(receiver));
6280 return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
6284 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
6285 PropertyDescriptor desc;
6286 Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
6287 it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
6288 MAYBE_RETURN(found, Nothing<PropertyAttributes>());
6289 if (!found.FromJust())
return Just(ABSENT);
6290 return Just(desc.ToAttributes());
6294 void JSObject::AllocateStorageForMap(Handle<JSObject>
object, Handle<Map> map) {
6295 DCHECK(object->map()->GetInObjectProperties() ==
6296 map->GetInObjectProperties());
6297 ElementsKind obj_kind =
object->map()->elements_kind();
6298 ElementsKind map_kind = map->elements_kind();
6299 if (map_kind != obj_kind) {
6300 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
6301 if (IsDictionaryElementsKind(obj_kind)) {
6304 if (IsDictionaryElementsKind(to_kind)) {
6305 NormalizeElements(
object);
6307 TransitionElementsKind(
object, to_kind);
6309 map = Map::ReconfigureElementsKind(object->GetIsolate(), map, to_kind);
6311 int number_of_fields = map->NumberOfFields();
6312 int inobject = map->GetInObjectProperties();
6313 int unused = map->UnusedPropertyFields();
6314 int total_size = number_of_fields + unused;
6315 int external = total_size - inobject;
6319 if (!FLAG_unbox_double_fields || external > 0) {
6320 Isolate* isolate =
object->GetIsolate();
6322 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
6323 Handle<FixedArray> storage;
6324 if (!FLAG_unbox_double_fields) {
6325 storage = isolate->factory()->NewFixedArray(inobject);
6328 Handle<PropertyArray> array =
6329 isolate->factory()->NewPropertyArray(external);
6331 for (
int i = 0;
i < map->NumberOfOwnDescriptors();
i++) {
6332 PropertyDetails details = descriptors->GetDetails(
i);
6333 Representation representation = details.representation();
6334 if (!representation.IsDouble())
continue;
6335 FieldIndex index = FieldIndex::ForDescriptor(*map,
i);
6336 if (map->IsUnboxedDoubleField(index))
continue;
6337 auto box = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
6338 if (index.is_inobject()) {
6339 storage->set(index.property_index(), *box);
6341 array->set(index.outobject_array_index(), *box);
6345 object->SetProperties(*array);
6347 if (!FLAG_unbox_double_fields) {
6348 for (
int i = 0;
i < inobject;
i++) {
6349 FieldIndex index = FieldIndex::ForPropertyIndex(*map,
i);
6350 Object* value = storage->get(
i);
6351 object->RawFastPropertyAtPut(index, value);
6355 object->synchronized_set_map(*map);
6359 void JSObject::MigrateInstance(Handle<JSObject>
object) {
6360 Handle<Map> original_map(object->map(),
object->GetIsolate());
6361 Handle<Map> map = Map::Update(object->GetIsolate(), original_map);
6362 map->set_is_migration_target(
true);
6363 MigrateToMap(
object, map);
6364 if (FLAG_trace_migration) {
6365 object->PrintInstanceMigration(stdout, *original_map, *map);
6368 if (FLAG_verify_heap) {
6369 object->JSObjectVerify(object->GetIsolate());
6376 bool JSObject::TryMigrateInstance(Handle<JSObject>
object) {
6377 Isolate* isolate =
object->GetIsolate();
6378 DisallowDeoptimization no_deoptimization(isolate);
6379 Handle<Map> original_map(object->map(), isolate);
6380 Handle<Map> new_map;
6381 if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) {
6384 JSObject::MigrateToMap(
object, new_map);
6385 if (FLAG_trace_migration && *original_map != object->map()) {
6386 object->PrintInstanceMigration(stdout, *original_map, object->map());
6389 if (FLAG_verify_heap) {
6390 object->JSObjectVerify(isolate);
6396 void JSObject::AddProperty(Isolate* isolate, Handle<JSObject>
object,
6397 Handle<Name> name, Handle<Object> value,
6398 PropertyAttributes attributes) {
6399 LookupIterator it(isolate,
object, name,
object,
6400 LookupIterator::OWN_SKIP_INTERCEPTOR);
6401 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
6404 DCHECK(!object->IsJSProxy());
6405 DCHECK(!name->AsArrayIndex(&index));
6406 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
6407 DCHECK(maybe.IsJust());
6408 DCHECK(!it.IsFound());
6409 DCHECK(object->map()->is_extensible() || name->IsPrivate());
6411 CHECK(AddDataProperty(&it, value, attributes, kThrowOnError,
6412 StoreOrigin::kNamed)
6421 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
6422 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
6423 AccessorInfoHandling handling) {
6424 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(it, value, attributes,
6425 kThrowOnError, handling));
6430 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
6431 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
6432 ShouldThrow should_throw, AccessorInfoHandling handling) {
6433 it->UpdateProtector();
6434 Handle<JSObject>
object = Handle<JSObject>::cast(it->GetReceiver());
6436 for (; it->IsFound(); it->Next()) {
6437 switch (it->state()) {
6438 case LookupIterator::JSPROXY:
6439 case LookupIterator::NOT_FOUND:
6440 case LookupIterator::TRANSITION:
6443 case LookupIterator::ACCESS_CHECK:
6444 if (!it->HasAccess()) {
6445 it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
6446 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
6459 case LookupIterator::INTERCEPTOR:
6460 if (handling == DONT_FORCE_FIELD) {
6461 Maybe<bool> result =
6462 JSObject::SetPropertyWithInterceptor(it, should_throw, value);
6463 if (result.IsNothing() || result.FromJust())
return result;
6467 case LookupIterator::ACCESSOR: {
6468 Handle<Object> accessors = it->GetAccessors();
6472 if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
6473 PropertyAttributes current_attributes = it->property_attributes();
6475 AssertNoContextChange ncc(it->isolate());
6479 if (current_attributes != attributes) {
6480 it->TransitionToAccessorPair(accessors, attributes);
6483 return JSObject::SetPropertyWithAccessor(it, value, should_throw);
6486 it->ReconfigureDataProperty(value, attributes);
6489 case LookupIterator::INTEGER_INDEXED_EXOTIC:
6490 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
6493 case LookupIterator::DATA: {
6495 if (it->property_attributes() == attributes) {
6496 return SetDataProperty(it, value);
6501 if (it->IsElement() &&
object->HasFixedTypedArrayElements()) {
6502 return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
6503 value, should_throw);
6507 it->ReconfigureDataProperty(value, attributes);
6514 return AddDataProperty(it, value, attributes, should_throw,
6515 StoreOrigin::kNamed);
6518 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
6519 Handle<JSObject>
object, Handle<Name> name, Handle<Object> value,
6520 PropertyAttributes attributes) {
6521 DCHECK(!value->IsTheHole());
6522 LookupIterator it(
object, name,
object, LookupIterator::OWN);
6523 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6526 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
6527 Handle<JSObject>
object,
uint32_t index, Handle<Object> value,
6528 PropertyAttributes attributes) {
6529 Isolate* isolate =
object->GetIsolate();
6530 LookupIterator it(isolate,
object, index,
object, LookupIterator::OWN);
6531 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6534 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
6535 Handle<JSObject>
object, Handle<Name> name, Handle<Object> value,
6536 PropertyAttributes attributes) {
6537 Isolate* isolate =
object->GetIsolate();
6538 LookupIterator it = LookupIterator::PropertyOrElement(
6539 isolate,
object, name,
object, LookupIterator::OWN);
6540 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6543 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
6544 LookupIterator* it) {
6545 return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
6548 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
6549 LookupIterator* it) {
6550 for (; it->IsFound(); it->Next()) {
6551 switch (it->state()) {
6552 case LookupIterator::NOT_FOUND:
6553 case LookupIterator::TRANSITION:
6555 case LookupIterator::JSPROXY:
6556 return JSProxy::GetPropertyAttributes(it);
6557 case LookupIterator::INTERCEPTOR: {
6558 Maybe<PropertyAttributes> result =
6559 JSObject::GetPropertyAttributesWithInterceptor(it);
6560 if (result.IsNothing())
return result;
6561 if (result.FromJust() != ABSENT)
return result;
6564 case LookupIterator::ACCESS_CHECK:
6565 if (it->HasAccess())
break;
6566 return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
6567 case LookupIterator::INTEGER_INDEXED_EXOTIC:
6568 return Just(ABSENT);
6569 case LookupIterator::ACCESSOR:
6570 if (it->GetHolder<Object>()->IsJSModuleNamespace()) {
6571 return JSModuleNamespace::GetPropertyAttributes(it);
6573 return Just(it->property_attributes());
6575 case LookupIterator::DATA:
6576 return Just(it->property_attributes());
6579 return Just(ABSENT);
6583 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
6584 Handle<WeakFixedArray> array(
6585 isolate->factory()->NewWeakFixedArray(kEntries, TENURED));
6586 return Handle<NormalizedMapCache>::cast(array);
6590 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
6591 PropertyNormalizationMode mode) {
6592 DisallowHeapAllocation no_gc;
6593 MaybeObject value = WeakFixedArray::Get(GetIndex(fast_map));
6594 HeapObject* heap_object;
6595 if (!value->GetHeapObjectIfWeak(&heap_object)) {
6596 return MaybeHandle<Map>();
6599 Map normalized_map = Map::cast(heap_object);
6600 if (!normalized_map->EquivalentToForNormalization(*fast_map, mode)) {
6601 return MaybeHandle<Map>();
6603 return handle(normalized_map, GetIsolate());
6606 void NormalizedMapCache::Set(Handle<Map> fast_map, Handle<Map> normalized_map) {
6607 DisallowHeapAllocation no_gc;
6608 DCHECK(normalized_map->is_dictionary_map());
6609 WeakFixedArray::Set(GetIndex(fast_map),
6610 HeapObjectReference::Weak(*normalized_map));
6613 void JSObject::NormalizeProperties(Handle<JSObject>
object,
6614 PropertyNormalizationMode mode,
6615 int expected_additional_properties,
6616 const char* reason) {
6617 if (!object->HasFastProperties())
return;
6619 Handle<Map> map(object->map(),
object->GetIsolate());
6620 Handle<Map> new_map = Map::Normalize(object->GetIsolate(), map, mode, reason);
6622 MigrateToMap(
object, new_map, expected_additional_properties);
6626 void JSObject::MigrateSlowToFast(Handle<JSObject>
object,
6627 int unused_property_fields,
6628 const char* reason) {
6629 if (object->HasFastProperties())
return;
6630 DCHECK(!object->IsJSGlobalObject());
6631 Isolate* isolate =
object->GetIsolate();
6632 Factory* factory = isolate->factory();
6633 Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
6637 int number_of_elements = dictionary->NumberOfElements();
6638 if (number_of_elements > kMaxNumberOfDescriptors)
return;
6640 Handle<FixedArray> iteration_order =
6641 NameDictionary::IterationIndices(isolate, dictionary);
6643 int instance_descriptor_length = iteration_order->length();
6644 int number_of_fields = 0;
6647 ReadOnlyRoots roots(isolate);
6648 for (
int i = 0;
i < instance_descriptor_length;
i++) {
6649 int index = Smi::ToInt(iteration_order->get(
i));
6650 DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(index)));
6652 PropertyKind kind = dictionary->DetailsAt(index).kind();
6653 if (kind == kData) {
6654 if (FLAG_track_constant_fields) {
6655 number_of_fields += 1;
6657 Object* value = dictionary->ValueAt(index);
6658 if (!value->IsJSFunction()) {
6659 number_of_fields += 1;
6665 Handle<Map> old_map(object->map(), isolate);
6667 int inobject_props = old_map->GetInObjectProperties();
6670 Handle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map);
6671 if (new_map->has_named_interceptor() || new_map->is_access_check_needed()) {
6674 new_map->set_may_have_interesting_symbols(
true);
6676 new_map->set_is_dictionary_map(
false);
6678 NotifyMapChange(old_map, new_map, isolate);
6681 if (instance_descriptor_length == 0) {
6682 DisallowHeapAllocation no_gc;
6683 DCHECK_LE(unused_property_fields, inobject_props);
6685 new_map->SetInObjectUnusedPropertyFields(inobject_props);
6686 object->synchronized_set_map(*new_map);
6687 object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
6689 DCHECK(object->HasFastProperties());
6690 if (FLAG_trace_maps) {
6691 LOG(isolate, MapEvent(
"SlowToFast", *old_map, *new_map, reason));
6697 Handle<DescriptorArray> descriptors =
6698 DescriptorArray::Allocate(isolate, instance_descriptor_length, 0);
6700 int number_of_allocated_fields =
6701 number_of_fields + unused_property_fields - inobject_props;
6702 if (number_of_allocated_fields < 0) {
6704 number_of_allocated_fields = 0;
6705 unused_property_fields = inobject_props - number_of_fields;
6709 Handle<PropertyArray> fields =
6710 factory->NewPropertyArray(number_of_allocated_fields);
6712 bool is_transitionable_elements_kind =
6713 IsTransitionableFastElementsKind(old_map->elements_kind());
6716 int current_offset = 0;
6717 for (
int i = 0;
i < instance_descriptor_length;
i++) {
6718 int index = Smi::ToInt(iteration_order->get(
i));
6719 Name k = dictionary->NameAt(index);
6722 CHECK(k->IsUniqueName());
6723 Handle<Name> key(k, isolate);
6726 if (key->IsInterestingSymbol()) {
6727 new_map->set_may_have_interesting_symbols(
true);
6730 Object* value = dictionary->ValueAt(index);
6732 PropertyDetails details = dictionary->DetailsAt(index);
6733 DCHECK_EQ(kField, details.location());
6734 DCHECK_EQ(PropertyConstness::kMutable, details.constness());
6737 if (details.kind() == kData) {
6738 if (!FLAG_track_constant_fields && value->IsJSFunction()) {
6739 d = Descriptor::DataConstant(key, handle(value, isolate),
6740 details.attributes());
6744 PropertyConstness constness =
6745 FLAG_track_constant_fields && !is_transitionable_elements_kind
6746 ? PropertyConstness::kConst
6747 : PropertyConstness::kMutable;
6748 d = Descriptor::DataField(
6749 key, current_offset, details.attributes(), constness,
6751 Representation::Tagged(),
6752 MaybeObjectHandle(FieldType::Any(isolate)));
6755 DCHECK_EQ(kAccessor, details.kind());
6756 d = Descriptor::AccessorConstant(key, handle(value, isolate),
6757 details.attributes());
6759 details = d.GetDetails();
6760 if (details.location() == kField) {
6761 if (current_offset < inobject_props) {
6762 object->InObjectPropertyAtPut(current_offset, value,
6763 UPDATE_WRITE_BARRIER);
6765 int offset = current_offset - inobject_props;
6766 fields->set(offset, value);
6768 current_offset += details.field_width_in_words();
6770 descriptors->Set(
i, &d);
6772 DCHECK(current_offset == number_of_fields);
6774 descriptors->Sort();
6776 Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
6777 isolate, new_map, descriptors, descriptors->number_of_descriptors());
6779 DisallowHeapAllocation no_gc;
6780 new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
6781 if (number_of_allocated_fields == 0) {
6782 new_map->SetInObjectUnusedPropertyFields(unused_property_fields);
6784 new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields);
6787 if (FLAG_trace_maps) {
6788 LOG(isolate, MapEvent(
"SlowToFast", *old_map, *new_map, reason));
6791 object->synchronized_set_map(*new_map);
6793 object->SetProperties(*fields);
6794 DCHECK(object->IsJSObject());
6797 DCHECK(object->HasFastProperties());
6800 void JSObject::RequireSlowElements(NumberDictionary dictionary) {
6801 if (dictionary->requires_slow_elements())
return;
6802 dictionary->set_requires_slow_elements();
6803 if (map()->is_prototype_map()) {
6806 InvalidatePrototypeChains(map());
6810 Handle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject>
object) {
6811 DCHECK(!object->HasFixedTypedArrayElements());
6812 Isolate* isolate =
object->GetIsolate();
6813 bool is_sloppy_arguments =
object->HasSloppyArgumentsElements();
6815 DisallowHeapAllocation no_gc;
6816 FixedArrayBase elements =
object->elements();
6818 if (is_sloppy_arguments) {
6819 elements = SloppyArgumentsElements::cast(elements)->arguments();
6822 if (elements->IsNumberDictionary()) {
6823 return handle(NumberDictionary::cast(elements), isolate);
6827 DCHECK(object->HasSmiOrObjectElements() ||
object->HasDoubleElements() ||
6828 object->HasFastArgumentsElements() ||
6829 object->HasFastStringWrapperElements());
6831 Handle<NumberDictionary> dictionary =
6832 object->GetElementsAccessor()->Normalize(
object);
6835 ElementsKind target_kind = is_sloppy_arguments
6836 ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
6837 :
object->HasFastStringWrapperElements()
6838 ? SLOW_STRING_WRAPPER_ELEMENTS
6839 : DICTIONARY_ELEMENTS;
6840 Handle<Map> new_map = JSObject::GetElementsTransitionMap(
object, target_kind);
6842 JSObject::MigrateToMap(
object, new_map);
6844 if (is_sloppy_arguments) {
6845 SloppyArgumentsElements::cast(object->elements())
6846 ->set_arguments(*dictionary);
6848 object->set_elements(*dictionary);
6851 isolate->counters()->elements_to_dictionary()->Increment();
6854 if (FLAG_trace_normalization) {
6856 os <<
"Object elements have been normalized:\n";
6861 DCHECK(object->HasDictionaryElements() ||
6862 object->HasSlowArgumentsElements() ||
6863 object->HasSlowStringWrapperElements());
6869 Object* SetHashAndUpdateProperties(HeapObject* properties,
int hash) {
6870 DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6871 DCHECK(PropertyArray::HashField::is_valid(hash));
6873 ReadOnlyRoots roots = properties->GetReadOnlyRoots();
6874 if (properties == roots.empty_fixed_array() ||
6875 properties == roots.empty_property_array() ||
6876 properties == roots.empty_property_dictionary()) {
6877 return Smi::FromInt(hash);
6880 if (properties->IsPropertyArray()) {
6881 PropertyArray::cast(properties)->SetHash(hash);
6882 DCHECK_LT(0, PropertyArray::cast(properties)->length());
6886 if (properties->IsGlobalDictionary()) {
6887 GlobalDictionary::cast(properties)->SetHash(hash);
6891 DCHECK(properties->IsNameDictionary());
6892 NameDictionary::cast(properties)->SetHash(hash);
6896 int GetIdentityHashHelper(JSReceiver*
object) {
6897 DisallowHeapAllocation no_gc;
6898 Object* properties =
object->raw_properties_or_hash();
6899 if (properties->IsSmi()) {
6900 return Smi::ToInt(properties);
6903 if (properties->IsPropertyArray()) {
6904 return PropertyArray::cast(properties)->Hash();
6907 if (properties->IsNameDictionary()) {
6908 return NameDictionary::cast(properties)->Hash();
6911 if (properties->IsGlobalDictionary()) {
6912 return GlobalDictionary::cast(properties)->Hash();
6916 ReadOnlyRoots roots =
object->GetReadOnlyRoots();
6917 DCHECK(properties == roots.empty_fixed_array() ||
6918 properties == roots.empty_property_dictionary());
6921 return PropertyArray::kNoHashSentinel;
6925 void JSReceiver::SetIdentityHash(
int hash) {
6926 DisallowHeapAllocation no_gc;
6927 DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6928 DCHECK(PropertyArray::HashField::is_valid(hash));
6930 HeapObject* existing_properties = HeapObject::cast(raw_properties_or_hash());
6931 Object* new_properties =
6932 SetHashAndUpdateProperties(existing_properties, hash);
6933 set_raw_properties_or_hash(new_properties);
6936 void JSReceiver::SetProperties(HeapObject* properties) {
6937 DCHECK_IMPLIES(properties->IsPropertyArray() &&
6938 PropertyArray::cast(properties)->length() == 0,
6939 properties == GetReadOnlyRoots().empty_property_array());
6940 DisallowHeapAllocation no_gc;
6941 int hash = GetIdentityHashHelper(
this);
6942 Object* new_properties = properties;
6946 if (hash != PropertyArray::kNoHashSentinel) {
6947 new_properties = SetHashAndUpdateProperties(properties, hash);
6950 set_raw_properties_or_hash(new_properties);
6953 Object* JSReceiver::GetIdentityHash() {
6954 DisallowHeapAllocation no_gc;
6956 int hash = GetIdentityHashHelper(
this);
6957 if (hash == PropertyArray::kNoHashSentinel) {
6958 return GetReadOnlyRoots().undefined_value();
6961 return Smi::FromInt(hash);
6965 Smi JSReceiver::CreateIdentityHash(Isolate* isolate, JSReceiver* key) {
6966 DisallowHeapAllocation no_gc;
6967 int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax);
6968 DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6970 key->SetIdentityHash(hash);
6971 return Smi::FromInt(hash);
6974 Smi JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) {
6975 DisallowHeapAllocation no_gc;
6977 int hash = GetIdentityHashHelper(
this);
6978 if (hash != PropertyArray::kNoHashSentinel) {
6979 return Smi::FromInt(hash);
6982 return JSReceiver::CreateIdentityHash(isolate,
this);
6985 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
6986 ShouldThrow should_throw) {
6987 Isolate* isolate = it->isolate();
6990 AssertNoContextChange ncc(isolate);
6992 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
6993 Handle<InterceptorInfo> interceptor(it->GetInterceptor());
6994 if (interceptor->deleter()->IsUndefined(isolate))
return Nothing<bool>();
6996 Handle<JSObject> holder = it->GetHolder<JSObject>();
6997 Handle<Object> receiver = it->GetReceiver();
6998 if (!receiver->IsJSReceiver()) {
6999 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
7000 Object::ConvertReceiver(isolate, receiver),
7004 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
7005 *holder, should_throw);
7006 Handle<Object> result;
7007 if (it->IsElement()) {
7008 result = args.CallIndexedDeleter(interceptor, it->index());
7010 result = args.CallNamedDeleter(interceptor, it->name());
7013 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7014 if (result.is_null())
return Nothing<bool>();
7016 DCHECK(result->IsBoolean());
7018 return Just(result->IsTrue(isolate));
7021 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver>
object,
7023 DCHECK(!object->HasFastProperties());
7024 Isolate* isolate =
object->GetIsolate();
7026 if (object->IsJSGlobalObject()) {
7028 Handle<GlobalDictionary> dictionary(
7029 JSGlobalObject::cast(*object)->global_dictionary(), isolate);
7030 DCHECK_NE(GlobalDictionary::kNotFound, entry);
7032 auto cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
7033 cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
7034 cell->set_property_details(
7035 PropertyDetails::Empty(PropertyCellType::kUninitialized));
7037 Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
7038 DCHECK_NE(NameDictionary::kNotFound, entry);
7040 dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
7041 object->SetProperties(*dictionary);
7043 if (object->map()->is_prototype_map()) {
7046 JSObject::InvalidatePrototypeChains(object->map());
7051 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
7052 LanguageMode language_mode) {
7053 it->UpdateProtector();
7055 Isolate* isolate = it->isolate();
7057 if (it->state() == LookupIterator::JSPROXY) {
7058 return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
7059 it->GetName(), language_mode);
7062 if (it->GetReceiver()->IsJSProxy()) {
7063 if (it->state() != LookupIterator::NOT_FOUND) {
7064 DCHECK_EQ(LookupIterator::DATA, it->state());
7065 DCHECK(it->name()->IsPrivate());
7070 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
7072 for (; it->IsFound(); it->Next()) {
7073 switch (it->state()) {
7074 case LookupIterator::JSPROXY:
7075 case LookupIterator::NOT_FOUND:
7076 case LookupIterator::TRANSITION:
7078 case LookupIterator::ACCESS_CHECK:
7079 if (it->HasAccess())
break;
7080 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
7081 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7083 case LookupIterator::INTERCEPTOR: {
7084 ShouldThrow should_throw =
7085 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
7086 Maybe<bool> result =
7087 JSObject::DeletePropertyWithInterceptor(it, should_throw);
7089 if (isolate->has_pending_exception())
return Nothing<bool>();
7093 if (result.IsJust())
return result;
7096 case LookupIterator::INTEGER_INDEXED_EXOTIC:
7098 case LookupIterator::DATA:
7099 case LookupIterator::ACCESSOR: {
7100 if (!it->IsConfigurable()) {
7102 if (is_strict(language_mode)) {
7103 isolate->Throw(*isolate->factory()->NewTypeError(
7104 MessageTemplate::kStrictDeleteProperty, it->GetName(),
7106 return Nothing<bool>();
7122 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver>
object,
uint32_t index,
7123 LanguageMode language_mode) {
7124 LookupIterator it(object->GetIsolate(), object, index, object,
7125 LookupIterator::OWN);
7126 return DeleteProperty(&it, language_mode);
7130 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver>
object,
7132 LanguageMode language_mode) {
7133 LookupIterator it(
object, name,
object, LookupIterator::OWN);
7134 return DeleteProperty(&it, language_mode);
7138 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver>
object,
7140 LanguageMode language_mode) {
7141 LookupIterator it = LookupIterator::PropertyOrElement(
7142 object->GetIsolate(), object, name, object, LookupIterator::OWN);
7143 return DeleteProperty(&it, language_mode);
7148 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object>
object,
7150 Handle<Object> attributes) {
7152 if (!object->IsJSReceiver()) {
7153 Handle<String> fun_name =
7154 isolate->factory()->InternalizeUtf8String(
"Object.defineProperty");
7155 THROW_NEW_ERROR_RETURN_FAILURE(
7156 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
7160 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
7163 PropertyDescriptor desc;
7164 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
7165 return ReadOnlyRoots(isolate).exception();
7168 Maybe<bool> success = DefineOwnProperty(
7169 isolate, Handle<JSReceiver>::cast(
object), key, &desc, kThrowOnError);
7171 MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
7172 CHECK(success.FromJust());
7180 MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
7181 Handle<Object>
object,
7182 Handle<Object> properties) {
7184 if (!object->IsJSReceiver()) {
7185 Handle<String> fun_name =
7186 isolate->factory()->InternalizeUtf8String(
"Object.defineProperties");
7187 THROW_NEW_ERROR(isolate,
7188 NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
7193 Handle<JSReceiver> props;
7194 ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
7195 Object::ToObject(isolate, properties), Object);
7199 Handle<FixedArray> keys;
7200 ASSIGN_RETURN_ON_EXCEPTION(
7201 isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
7205 int capacity = keys->length();
7206 std::vector<PropertyDescriptor> descriptors(capacity);
7207 size_t descriptors_index = 0;
7209 for (
int i = 0;
i < keys->length(); ++
i) {
7210 Handle<Object> next_key(keys->get(
i), isolate);
7213 bool success =
false;
7214 LookupIterator it = LookupIterator::PropertyOrElement(
7215 isolate, props, next_key, &success, LookupIterator::OWN);
7217 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
7218 if (maybe.IsNothing())
return MaybeHandle<Object>();
7219 PropertyAttributes attrs = maybe.FromJust();
7221 if (attrs == ABSENT)
continue;
7222 if (attrs & DONT_ENUM)
continue;
7225 Handle<Object> desc_obj;
7226 ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
7229 success = PropertyDescriptor::ToPropertyDescriptor(
7230 isolate, desc_obj, &descriptors[descriptors_index]);
7232 if (!success)
return MaybeHandle<Object>();
7235 descriptors[descriptors_index].set_name(next_key);
7236 descriptors_index++;
7239 for (
size_t i = 0;
i < descriptors_index; ++
i) {
7240 PropertyDescriptor* desc = &descriptors[
i];
7244 Maybe<bool> status =
7245 DefineOwnProperty(isolate, Handle<JSReceiver>::cast(
object),
7246 desc->name(), desc, kThrowOnError);
7248 if (status.IsNothing())
return MaybeHandle<Object>();
7249 CHECK(status.FromJust());
7256 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
7257 Handle<JSReceiver>
object,
7259 PropertyDescriptor* desc,
7260 ShouldThrow should_throw) {
7261 if (object->IsJSArray()) {
7262 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(
object),
7263 key, desc, should_throw);
7265 if (object->IsJSProxy()) {
7266 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(
object),
7267 key, desc, should_throw);
7269 if (object->IsJSTypedArray()) {
7270 return JSTypedArray::DefineOwnProperty(
7271 isolate, Handle<JSTypedArray>::cast(
object), key, desc, should_throw);
7277 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(
object), key,
7278 desc, should_throw);
7283 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
7284 Handle<JSObject>
object,
7286 PropertyDescriptor* desc,
7287 ShouldThrow should_throw) {
7288 bool success =
false;
7289 DCHECK(key->IsName() || key->IsNumber());
7290 LookupIterator it = LookupIterator::PropertyOrElement(
7291 isolate,
object, key, &success, LookupIterator::OWN);
7295 if (it.state() == LookupIterator::ACCESS_CHECK) {
7296 if (!it.HasAccess()) {
7297 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
7298 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7304 return OrdinaryDefineOwnProperty(&it, desc, should_throw);
7310 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
7311 PropertyDescriptor* desc,
7312 ShouldThrow should_throw) {
7313 Isolate* isolate = it->isolate();
7316 PropertyDescriptor current;
7317 MAYBE_RETURN(GetOwnPropertyDescriptor(it, ¤t), Nothing<bool>());
7321 for (; it->IsFound(); it->Next()) {
7322 if (it->state() == LookupIterator::INTERCEPTOR) {
7323 if (it->HolderIsReceiverOrHiddenPrototype()) {
7324 Maybe<bool> result = DefinePropertyWithInterceptorInternal(
7325 it, it->GetInterceptor(), should_throw, *desc);
7326 if (result.IsNothing() || result.FromJust()) {
7339 Handle<JSObject>
object = Handle<JSObject>::cast(it->GetReceiver());
7340 bool extensible = JSObject::IsExtensible(
object);
7342 return ValidateAndApplyPropertyDescriptor(
7343 isolate, it, extensible, desc, ¤t, should_throw, Handle<Name>());
7349 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
7350 Isolate* isolate,
bool extensible, PropertyDescriptor* desc,
7351 PropertyDescriptor* current, Handle<Name> property_name,
7352 ShouldThrow should_throw) {
7355 return ValidateAndApplyPropertyDescriptor(
7356 isolate,
nullptr, extensible, desc, current, should_throw, property_name);
7362 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
7363 Isolate* isolate, LookupIterator* it,
bool extensible,
7364 PropertyDescriptor* desc, PropertyDescriptor* current,
7365 ShouldThrow should_throw, Handle<Name> property_name) {
7367 DCHECK((it ==
nullptr) != property_name.is_null());
7368 Handle<JSObject> object;
7369 if (it !=
nullptr)
object = Handle<JSObject>::cast(it->GetReceiver());
7370 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
7371 bool desc_is_accessor_descriptor =
7372 PropertyDescriptor::IsAccessorDescriptor(desc);
7373 bool desc_is_generic_descriptor =
7374 PropertyDescriptor::IsGenericDescriptor(desc);
7377 if (current->is_empty()) {
7381 isolate, should_throw,
7382 NewTypeError(MessageTemplate::kDefineDisallowed,
7383 it !=
nullptr ? it->GetName() : property_name));
7387 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
7388 !desc_is_accessor_descriptor);
7389 if (!desc_is_accessor_descriptor) {
7395 if (it !=
nullptr) {
7396 if (!desc->has_writable()) desc->set_writable(
false);
7397 if (!desc->has_enumerable()) desc->set_enumerable(
false);
7398 if (!desc->has_configurable()) desc->set_configurable(
false);
7399 Handle<Object> value(
7402 : Handle<Object>::cast(isolate->factory()->undefined_value()));
7403 MaybeHandle<Object> result =
7404 JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
7405 desc->ToAttributes());
7406 if (result.is_null())
return Nothing<bool>();
7410 DCHECK(desc_is_accessor_descriptor);
7416 if (it !=
nullptr) {
7417 if (!desc->has_enumerable()) desc->set_enumerable(
false);
7418 if (!desc->has_configurable()) desc->set_configurable(
false);
7419 Handle<Object> getter(
7422 : Handle<Object>::cast(isolate->factory()->null_value()));
7423 Handle<Object> setter(
7426 : Handle<Object>::cast(isolate->factory()->null_value()));
7427 MaybeHandle<Object> result =
7428 JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
7429 if (result.is_null())
return Nothing<bool>();
7439 if ((!desc->has_enumerable() ||
7440 desc->enumerable() == current->enumerable()) &&
7441 (!desc->has_configurable() ||
7442 desc->configurable() == current->configurable()) &&
7443 (!desc->has_value() ||
7444 (current->has_value() && current->value()->SameValue(*desc->value()))) &&
7445 (!desc->has_writable() ||
7446 (current->has_writable() && current->writable() == desc->writable())) &&
7447 (!desc->has_get() ||
7448 (current->has_get() && current->get()->SameValue(*desc->get()))) &&
7449 (!desc->has_set() ||
7450 (current->has_set() && current->set()->SameValue(*desc->set())))) {
7454 if (!current->configurable()) {
7456 if (desc->has_configurable() && desc->configurable()) {
7458 isolate, should_throw,
7459 NewTypeError(MessageTemplate::kRedefineDisallowed,
7460 it !=
nullptr ? it->GetName() : property_name));
7465 if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
7467 isolate, should_throw,
7468 NewTypeError(MessageTemplate::kRedefineDisallowed,
7469 it !=
nullptr ? it->GetName() : property_name));
7473 bool current_is_data_descriptor =
7474 PropertyDescriptor::IsDataDescriptor(current);
7476 if (desc_is_generic_descriptor) {
7481 }
else if (current_is_data_descriptor != desc_is_data_descriptor) {
7483 if (!current->configurable()) {
7485 isolate, should_throw,
7486 NewTypeError(MessageTemplate::kRedefineDisallowed,
7487 it !=
nullptr ? it->GetName() : property_name));
7490 if (current_is_data_descriptor) {
7508 }
else if (current_is_data_descriptor && desc_is_data_descriptor) {
7510 if (!current->configurable()) {
7513 if (!current->writable() && desc->has_writable() && desc->writable()) {
7515 isolate, should_throw,
7516 NewTypeError(MessageTemplate::kRedefineDisallowed,
7517 it !=
nullptr ? it->GetName() : property_name));
7520 if (!current->writable()) {
7523 if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
7525 isolate, should_throw,
7526 NewTypeError(MessageTemplate::kRedefineDisallowed,
7527 it !=
nullptr ? it->GetName() : property_name));
7534 DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
7535 desc_is_accessor_descriptor);
7537 if (!current->configurable()) {
7540 if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
7542 isolate, should_throw,
7543 NewTypeError(MessageTemplate::kRedefineDisallowed,
7544 it !=
nullptr ? it->GetName() : property_name));
7548 if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
7550 isolate, should_throw,
7551 NewTypeError(MessageTemplate::kRedefineDisallowed,
7552 it !=
nullptr ? it->GetName() : property_name));
7558 if (it !=
nullptr) {
7561 PropertyAttributes attrs = NONE;
7563 if (desc->has_enumerable()) {
7564 attrs =
static_cast<PropertyAttributes
>(
7565 attrs | (desc->enumerable() ? NONE : DONT_ENUM));
7567 attrs =
static_cast<PropertyAttributes
>(
7568 attrs | (current->enumerable() ? NONE : DONT_ENUM));
7570 if (desc->has_configurable()) {
7571 attrs =
static_cast<PropertyAttributes
>(
7572 attrs | (desc->configurable() ? NONE : DONT_DELETE));
7574 attrs =
static_cast<PropertyAttributes
>(
7575 attrs | (current->configurable() ? NONE : DONT_DELETE));
7577 if (desc_is_data_descriptor ||
7578 (desc_is_generic_descriptor && current_is_data_descriptor)) {
7579 if (desc->has_writable()) {
7580 attrs =
static_cast<PropertyAttributes
>(
7581 attrs | (desc->writable() ? NONE : READ_ONLY));
7583 attrs =
static_cast<PropertyAttributes
>(
7584 attrs | (current->writable() ? NONE : READ_ONLY));
7586 Handle<Object> value(
7587 desc->has_value() ? desc->value()
7588 : current->has_value()
7590 : Handle<Object>::cast(
7591 isolate->factory()->undefined_value()));
7592 return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs,
7595 DCHECK(desc_is_accessor_descriptor ||
7596 (desc_is_generic_descriptor &&
7597 PropertyDescriptor::IsAccessorDescriptor(current)));
7598 Handle<Object> getter(
7601 : current->has_get()
7603 : Handle<Object>::cast(isolate->factory()->null_value()));
7604 Handle<Object> setter(
7607 : current->has_set()
7609 : Handle<Object>::cast(isolate->factory()->null_value()));
7610 MaybeHandle<Object> result =
7611 JSObject::DefineAccessor(it, getter, setter, attrs);
7612 if (result.is_null())
return Nothing<bool>();
7621 Maybe<bool> JSReceiver::CreateDataProperty(Isolate* isolate,
7622 Handle<JSReceiver>
object,
7624 Handle<Object> value,
7625 ShouldThrow should_throw) {
7626 LookupIterator it = LookupIterator::PropertyOrElement(isolate,
object, key,
7627 LookupIterator::OWN);
7628 return CreateDataProperty(&it, value, should_throw);
7632 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
7633 Handle<Object> value,
7634 ShouldThrow should_throw) {
7635 DCHECK(!it->check_prototype_chain());
7636 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
7637 Isolate* isolate = receiver->GetIsolate();
7639 if (receiver->IsJSObject()) {
7640 return JSObject::CreateDataProperty(it, value, should_throw);
7643 PropertyDescriptor new_desc;
7644 new_desc.set_value(value);
7645 new_desc.set_writable(
true);
7646 new_desc.set_enumerable(
true);
7647 new_desc.set_configurable(
true);
7649 return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
7650 &new_desc, should_throw);
7653 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
7654 Handle<Object> value,
7655 ShouldThrow should_throw) {
7656 DCHECK(it->GetReceiver()->IsJSObject());
7657 MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
7658 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
7659 Isolate* isolate = receiver->GetIsolate();
7661 if (it->IsFound()) {
7662 Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
7663 MAYBE_RETURN(attributes, Nothing<bool>());
7664 if ((attributes.FromJust() & DONT_DELETE) != 0) {
7666 isolate, should_throw,
7667 NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
7670 if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
7672 isolate, should_throw,
7673 NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
7677 RETURN_ON_EXCEPTION_VALUE(it->isolate(),
7678 DefineOwnPropertyIgnoreAttributes(it, value, NONE),
7686 bool PropertyKeyToArrayLength(Handle<Object> value,
uint32_t* length) {
7687 DCHECK(value->IsNumber() || value->IsName());
7688 if (value->ToArrayLength(length))
return true;
7689 if (value->IsString())
return String::cast(*value)->AsArrayIndex(length);
7693 bool PropertyKeyToArrayIndex(Handle<Object> index_obj,
uint32_t* output) {
7694 return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
7700 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
7701 Handle<Object> name,
7702 PropertyDescriptor* desc,
7703 ShouldThrow should_throw) {
7707 if (*name == ReadOnlyRoots(isolate).length_string()) {
7709 return ArraySetLength(isolate, o, desc, should_throw);
7713 if (PropertyKeyToArrayIndex(name, &index)) {
7715 PropertyDescriptor old_len_desc;
7716 Maybe<bool> success = GetOwnPropertyDescriptor(
7717 isolate, o, isolate->factory()->length_string(), &old_len_desc);
7719 DCHECK(success.FromJust());
7723 CHECK(old_len_desc.value()->ToArrayLength(&old_len));
7729 if (index >= old_len && old_len_desc.has_writable() &&
7730 !old_len_desc.writable()) {
7731 RETURN_FAILURE(isolate, should_throw,
7732 NewTypeError(MessageTemplate::kDefineDisallowed, name));
7735 Maybe<bool> succeeded =
7736 OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
7740 if (succeeded.IsNothing() || !succeeded.FromJust())
return succeeded;
7742 if (index >= old_len) {
7744 old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
7747 succeeded = OrdinaryDefineOwnProperty(isolate, o,
7748 isolate->factory()->length_string(),
7749 &old_len_desc, should_throw);
7751 DCHECK(succeeded.FromJust());
7759 return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
7765 bool JSArray::AnythingToArrayLength(Isolate* isolate,
7766 Handle<Object> length_object,
7770 if (length_object->ToArrayLength(output))
return true;
7771 if (length_object->IsString() &&
7772 Handle<String>::cast(length_object)->AsArrayIndex(output)) {
7777 Handle<Object> uint32_v;
7778 if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
7783 Handle<Object> number_v;
7784 if (!Object::ToNumber(isolate, length_object).ToHandle(&number_v)) {
7789 if (uint32_v->Number() != number_v->Number()) {
7790 Handle<Object> exception =
7791 isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
7792 isolate->Throw(*exception);
7795 CHECK(uint32_v->ToArrayLength(output));
7802 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
7803 PropertyDescriptor* desc,
7804 ShouldThrow should_throw) {
7806 if (!desc->has_value()) {
7808 return OrdinaryDefineOwnProperty(
7809 isolate, a, isolate->factory()->length_string(), desc, should_throw);
7813 PropertyDescriptor* new_len_desc = desc;
7816 if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
7817 DCHECK(isolate->has_pending_exception());
7818 return Nothing<bool>();
7823 PropertyDescriptor old_len_desc;
7824 Maybe<bool> success = GetOwnPropertyDescriptor(
7825 isolate, a, isolate->factory()->length_string(), &old_len_desc);
7827 DCHECK(success.FromJust());
7831 CHECK(old_len_desc.value()->ToArrayLength(&old_len));
7833 if (new_len >= old_len) {
7836 new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
7837 return OrdinaryDefineOwnProperty(isolate, a,
7838 isolate->factory()->length_string(),
7839 new_len_desc, should_throw);
7842 if (!old_len_desc.writable()) {
7843 RETURN_FAILURE(isolate, should_throw,
7844 NewTypeError(MessageTemplate::kRedefineDisallowed,
7845 isolate->factory()->length_string()));
7849 bool new_writable =
false;
7850 if (!new_len_desc->has_writable() || new_len_desc->writable()) {
7851 new_writable =
true;
7861 JSArray::SetLength(a, new_len);
7863 if (!new_writable) {
7864 PropertyDescriptor readonly;
7865 readonly.set_writable(
false);
7866 Maybe<bool> success = OrdinaryDefineOwnProperty(
7867 isolate, a, isolate->factory()->length_string(), &readonly,
7869 DCHECK(success.FromJust());
7873 CHECK(a->length()->ToArrayLength(&actual_new_len));
7875 bool result = actual_new_len == new_len;
7878 isolate, should_throw,
7879 NewTypeError(MessageTemplate::kStrictDeleteProperty,
7880 isolate->factory()->NewNumberFromUint(actual_new_len - 1),
7883 return Just(result);
7889 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
7891 PropertyDescriptor* desc,
7892 ShouldThrow should_throw) {
7893 STACK_CHECK(isolate, Nothing<bool>());
7894 if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
7895 DCHECK(!Handle<Symbol>::cast(key)->IsPrivateName());
7896 return JSProxy::SetPrivateSymbol(isolate, proxy, Handle<Symbol>::cast(key),
7897 desc, should_throw);
7899 Handle<String> trap_name = isolate->factory()->defineProperty_string();
7901 DCHECK(key->IsName() || key->IsNumber());
7903 Handle<Object> handler(proxy->handler(), isolate);
7906 if (proxy->IsRevoked()) {
7907 isolate->Throw(*isolate->factory()->NewTypeError(
7908 MessageTemplate::kProxyRevoked, trap_name));
7909 return Nothing<bool>();
7912 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
7914 Handle<Object> trap;
7915 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7917 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
7920 if (trap->IsUndefined(isolate)) {
7922 return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
7926 Handle<Object> desc_obj = desc->ToObject(isolate);
7929 Handle<Name> property_name =
7931 ? Handle<Name>::cast(key)
7932 : Handle<Name>::cast(isolate->factory()->NumberToString(key));
7934 DCHECK(!property_name->IsPrivate());
7935 Handle<Object> trap_result_obj;
7936 Handle<Object> args[] = {target, property_name, desc_obj};
7937 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7938 isolate, trap_result_obj,
7939 Execution::Call(isolate, trap, handler, arraysize(args), args),
7942 if (!trap_result_obj->BooleanValue(isolate)) {
7943 RETURN_FAILURE(isolate, should_throw,
7944 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
7945 trap_name, property_name));
7948 PropertyDescriptor target_desc;
7949 Maybe<bool> target_found =
7950 JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
7951 MAYBE_RETURN(target_found, Nothing<bool>());
7953 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
7954 MAYBE_RETURN(maybe_extensible, Nothing<bool>());
7955 bool extensible_target = maybe_extensible.FromJust();
7960 bool setting_config_false = desc->has_configurable() && !desc->configurable();
7962 if (!target_found.FromJust()) {
7964 if (!extensible_target) {
7965 isolate->Throw(*isolate->factory()->NewTypeError(
7966 MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
7967 return Nothing<bool>();
7970 if (setting_config_false) {
7971 isolate->Throw(*isolate->factory()->NewTypeError(
7972 MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7973 return Nothing<bool>();
7980 IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
7981 &target_desc, property_name, kDontThrow);
7982 MAYBE_RETURN(valid, Nothing<bool>());
7983 if (!valid.FromJust()) {
7984 isolate->Throw(*isolate->factory()->NewTypeError(
7985 MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
7986 return Nothing<bool>();
7990 if (setting_config_false && target_desc.configurable()) {
7991 isolate->Throw(*isolate->factory()->NewTypeError(
7992 MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7993 return Nothing<bool>();
8001 Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
8002 Handle<Symbol> private_name,
8003 PropertyDescriptor* desc,
8004 ShouldThrow should_throw) {
8005 DCHECK(!private_name->IsPrivateName());
8007 if (!PropertyDescriptor::IsDataDescriptor(desc) ||
8008 desc->ToAttributes() != DONT_ENUM) {
8009 RETURN_FAILURE(isolate, should_throw,
8010 NewTypeError(MessageTemplate::kProxyPrivate));
8012 DCHECK(proxy->map()->is_dictionary_map());
8013 Handle<Object> value =
8016 : Handle<Object>::cast(isolate->factory()->undefined_value());
8018 LookupIterator it(proxy, private_name, proxy);
8021 DCHECK_EQ(LookupIterator::DATA, it.state());
8022 DCHECK_EQ(DONT_ENUM, it.property_attributes());
8023 it.WriteDataValue(value,
false);
8027 Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
8028 PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell);
8029 Handle<NameDictionary> result =
8030 NameDictionary::Add(isolate, dict, private_name, value, details);
8031 if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
8036 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
8037 Handle<JSReceiver>
object,
8039 PropertyDescriptor* desc) {
8040 bool success =
false;
8041 DCHECK(key->IsName() || key->IsNumber());
8042 LookupIterator it = LookupIterator::PropertyOrElement(
8043 isolate,
object, key, &success, LookupIterator::OWN);
8045 return GetOwnPropertyDescriptor(&it, desc);
8050 Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
8051 PropertyDescriptor* desc) {
8052 if (it->state() == LookupIterator::ACCESS_CHECK) {
8053 if (it->HasAccess()) {
8055 }
else if (!JSObject::AllCanRead(it) ||
8056 it->state() != LookupIterator::INTERCEPTOR) {
8062 if (it->state() != LookupIterator::INTERCEPTOR)
return Just(
false);
8064 Isolate* isolate = it->isolate();
8065 Handle<InterceptorInfo> interceptor = it->GetInterceptor();
8066 if (interceptor->descriptor()->IsUndefined(isolate))
return Just(
false);
8068 Handle<Object> result;
8069 Handle<JSObject> holder = it->GetHolder<JSObject>();
8071 Handle<Object> receiver = it->GetReceiver();
8072 if (!receiver->IsJSReceiver()) {
8073 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
8074 Object::ConvertReceiver(isolate, receiver),
8078 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
8079 *holder, kDontThrow);
8080 if (it->IsElement()) {
8081 result = args.CallIndexedDescriptor(interceptor, it->index());
8083 result = args.CallNamedDescriptor(interceptor, it->name());
8085 if (!result.is_null()) {
8089 PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
8090 it->IsElement() ?
"v8::IndexedPropertyDescriptorCallback" 8091 :
"v8::NamedPropertyDescriptorCallback",
8092 "Invalid property descriptor.");
8106 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
8107 PropertyDescriptor* desc) {
8108 Isolate* isolate = it->isolate();
8110 if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
8111 return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
8112 it->GetName(), desc);
8115 Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
8116 MAYBE_RETURN(intercepted, Nothing<bool>());
8117 if (intercepted.FromJust()) {
8124 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
8125 MAYBE_RETURN(maybe, Nothing<bool>());
8126 PropertyAttributes attrs = maybe.FromJust();
8127 if (attrs == ABSENT)
return Just(
false);
8128 DCHECK(!isolate->has_pending_exception());
8131 DCHECK(desc->is_empty());
8134 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
8135 it->GetAccessors()->IsAccessorPair();
8136 if (!is_accessor_pair) {
8138 Handle<Object> value;
8139 if (!Object::GetProperty(it).ToHandle(&value)) {
8140 DCHECK(isolate->has_pending_exception());
8141 return Nothing<bool>();
8143 desc->set_value(value);
8145 desc->set_writable((attrs & READ_ONLY) == 0);
8148 Handle<AccessorPair> accessors =
8149 Handle<AccessorPair>::cast(it->GetAccessors());
8152 AccessorPair::GetComponent(isolate, accessors, ACCESSOR_GETTER));
8155 AccessorPair::GetComponent(isolate, accessors, ACCESSOR_SETTER));
8159 desc->set_enumerable((attrs & DONT_ENUM) == 0);
8161 desc->set_configurable((attrs & DONT_DELETE) == 0);
8163 DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
8164 PropertyDescriptor::IsDataDescriptor(desc));
8171 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
8172 Handle<JSProxy> proxy,
8174 PropertyDescriptor* desc) {
8175 DCHECK(!name->IsPrivate());
8176 STACK_CHECK(isolate, Nothing<bool>());
8178 Handle<String> trap_name =
8179 isolate->factory()->getOwnPropertyDescriptor_string();
8182 Handle<Object> handler(proxy->handler(), isolate);
8185 if (proxy->IsRevoked()) {
8186 isolate->Throw(*isolate->factory()->NewTypeError(
8187 MessageTemplate::kProxyRevoked, trap_name));
8188 return Nothing<bool>();
8191 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8193 Handle<Object> trap;
8194 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8196 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
8199 if (trap->IsUndefined(isolate)) {
8201 return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
8204 Handle<Object> trap_result_obj;
8205 Handle<Object> args[] = {target, name};
8206 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8207 isolate, trap_result_obj,
8208 Execution::Call(isolate, trap, handler, arraysize(args), args),
8212 if (!trap_result_obj->IsJSReceiver() &&
8213 !trap_result_obj->IsUndefined(isolate)) {
8214 isolate->Throw(*isolate->factory()->NewTypeError(
8215 MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
8216 return Nothing<bool>();
8219 PropertyDescriptor target_desc;
8221 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
8222 MAYBE_RETURN(found, Nothing<bool>());
8224 if (trap_result_obj->IsUndefined(isolate)) {
8226 if (!found.FromJust())
return Just(
false);
8229 if (!target_desc.configurable()) {
8230 isolate->Throw(*isolate->factory()->NewTypeError(
8231 MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
8232 return Nothing<bool>();
8235 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
8236 MAYBE_RETURN(extensible_target, Nothing<bool>());
8239 if (!extensible_target.FromJust()) {
8240 isolate->Throw(*isolate->factory()->NewTypeError(
8241 MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
8242 return Nothing<bool>();
8248 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
8249 MAYBE_RETURN(extensible_target, Nothing<bool>());
8251 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
8253 DCHECK(isolate->has_pending_exception());
8254 return Nothing<bool>();
8257 PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
8261 IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
8262 desc, &target_desc, name, kDontThrow);
8263 MAYBE_RETURN(valid, Nothing<bool>());
8265 if (!valid.FromJust()) {
8266 isolate->Throw(*isolate->factory()->NewTypeError(
8267 MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
8268 return Nothing<bool>();
8271 if (!desc->configurable()) {
8273 if (target_desc.is_empty() || target_desc.configurable()) {
8275 isolate->Throw(*isolate->factory()->NewTypeError(
8276 MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
8278 return Nothing<bool>();
8286 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
8288 ShouldThrow should_throw) {
8289 DCHECK(level == SEALED || level == FROZEN);
8291 if (receiver->IsJSObject()) {
8292 Handle<JSObject>
object = Handle<JSObject>::cast(receiver);
8294 if (!object->HasSloppyArgumentsElements() &&
8295 !
object->IsJSModuleNamespace()) {
8297 Maybe<bool> test = JSObject::TestIntegrityLevel(
object, level);
8298 MAYBE_RETURN(test, Nothing<bool>());
8299 if (test.FromJust())
return test;
8301 if (level == SEALED) {
8302 return JSObject::PreventExtensionsWithTransition<SEALED>(object,
8305 return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
8311 Isolate* isolate = receiver->GetIsolate();
8313 MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
8316 Handle<FixedArray> keys;
8317 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8318 isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
8320 PropertyDescriptor no_conf;
8321 no_conf.set_configurable(
false);
8323 PropertyDescriptor no_conf_no_write;
8324 no_conf_no_write.set_configurable(
false);
8325 no_conf_no_write.set_writable(
false);
8327 if (level == SEALED) {
8328 for (
int i = 0;
i < keys->length(); ++
i) {
8329 Handle<Object> key(keys->get(
i), isolate);
8331 DefineOwnProperty(isolate, receiver, key, &no_conf, kThrowOnError),
8337 for (
int i = 0;
i < keys->length(); ++
i) {
8338 Handle<Object> key(keys->get(
i), isolate);
8339 PropertyDescriptor current_desc;
8340 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
8341 isolate, receiver, key, ¤t_desc);
8342 MAYBE_RETURN(owned, Nothing<bool>());
8343 if (owned.FromJust()) {
8344 PropertyDescriptor desc =
8345 PropertyDescriptor::IsAccessorDescriptor(¤t_desc)
8349 DefineOwnProperty(isolate, receiver, key, &desc, kThrowOnError),
8358 template <
typename Dictionary>
8359 bool TestDictionaryPropertiesIntegrityLevel(Dictionary dict,
8360 ReadOnlyRoots roots,
8361 PropertyAttributes level) {
8362 DCHECK(level == SEALED || level == FROZEN);
8364 uint32_t capacity = dict->Capacity();
8367 if (!dict->ToKey(roots,
i, &key))
continue;
8368 if (key->FilterKey(ALL_PROPERTIES))
continue;
8369 PropertyDetails details = dict->DetailsAt(
i);
8370 if (details.IsConfigurable())
return false;
8371 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
8378 bool TestFastPropertiesIntegrityLevel(Map map, PropertyAttributes level) {
8379 DCHECK(level == SEALED || level == FROZEN);
8380 DCHECK(!map->IsCustomElementsReceiverMap());
8381 DCHECK(!map->is_dictionary_map());
8383 DescriptorArray* descriptors = map->instance_descriptors();
8384 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
8385 for (
int i = 0;
i < number_of_own_descriptors;
i++) {
8386 if (descriptors->GetKey(
i)->IsPrivate())
continue;
8387 PropertyDetails details = descriptors->GetDetails(
i);
8388 if (details.IsConfigurable())
return false;
8389 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
8396 bool TestPropertiesIntegrityLevel(JSObject*
object, PropertyAttributes level) {
8397 DCHECK(!object->map()->IsCustomElementsReceiverMap());
8399 if (object->HasFastProperties()) {
8400 return TestFastPropertiesIntegrityLevel(object->map(), level);
8403 return TestDictionaryPropertiesIntegrityLevel(
8404 object->property_dictionary(),
object->GetReadOnlyRoots(), level);
8407 bool TestElementsIntegrityLevel(JSObject*
object, PropertyAttributes level) {
8408 DCHECK(!object->HasSloppyArgumentsElements());
8410 ElementsKind kind =
object->GetElementsKind();
8412 if (IsDictionaryElementsKind(kind)) {
8413 return TestDictionaryPropertiesIntegrityLevel(
8414 NumberDictionary::cast(object->elements()), object->GetReadOnlyRoots(),
8418 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
8421 return accessor->NumberOfElements(
object) == 0;
8424 bool FastTestIntegrityLevel(JSObject*
object, PropertyAttributes level) {
8425 DCHECK(!object->map()->IsCustomElementsReceiverMap());
8427 return !
object->map()->is_extensible() &&
8428 TestElementsIntegrityLevel(
object, level) &&
8429 TestPropertiesIntegrityLevel(
object, level);
8432 Maybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver,
8433 PropertyAttributes level) {
8434 DCHECK(level == SEALED || level == FROZEN);
8436 Maybe<bool> extensible = JSReceiver::IsExtensible(receiver);
8437 MAYBE_RETURN(extensible, Nothing<bool>());
8438 if (extensible.FromJust())
return Just(
false);
8440 Isolate* isolate = receiver->GetIsolate();
8442 Handle<FixedArray> keys;
8443 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8444 isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
8446 for (
int i = 0;
i < keys->length(); ++
i) {
8447 Handle<Object> key(keys->get(
i), isolate);
8448 PropertyDescriptor current_desc;
8449 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
8450 isolate, receiver, key, ¤t_desc);
8451 MAYBE_RETURN(owned, Nothing<bool>());
8452 if (owned.FromJust()) {
8453 if (current_desc.configurable())
return Just(
false);
8454 if (level == FROZEN &&
8455 PropertyDescriptor::IsDataDescriptor(¤t_desc) &&
8456 current_desc.writable()) {
8466 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver,
8468 if (!receiver->map()->IsCustomElementsReceiverMap()) {
8469 return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver),
8472 return GenericTestIntegrityLevel(receiver, level);
8475 Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject>
object,
8477 if (!object->map()->IsCustomElementsReceiverMap() &&
8478 !
object->HasSloppyArgumentsElements()) {
8479 return Just(FastTestIntegrityLevel(*
object, level));
8481 return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(
object), level);
8484 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver>
object,
8485 ShouldThrow should_throw) {
8486 if (object->IsJSProxy()) {
8487 return JSProxy::PreventExtensions(Handle<JSProxy>::cast(
object),
8490 DCHECK(object->IsJSObject());
8491 return JSObject::PreventExtensions(Handle<JSObject>::cast(
object),
8496 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
8497 ShouldThrow should_throw) {
8498 Isolate* isolate = proxy->GetIsolate();
8499 STACK_CHECK(isolate, Nothing<bool>());
8500 Factory* factory = isolate->factory();
8501 Handle<String> trap_name = factory->preventExtensions_string();
8503 if (proxy->IsRevoked()) {
8505 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
8506 return Nothing<bool>();
8508 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8509 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
8511 Handle<Object> trap;
8512 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8513 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
8514 if (trap->IsUndefined(isolate)) {
8515 return JSReceiver::PreventExtensions(target, should_throw);
8518 Handle<Object> trap_result;
8519 Handle<Object> args[] = {target};
8520 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8521 isolate, trap_result,
8522 Execution::Call(isolate, trap, handler, arraysize(args), args),
8524 if (!trap_result->BooleanValue(isolate)) {
8526 isolate, should_throw,
8527 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
8531 Maybe<bool> target_result = JSReceiver::IsExtensible(target);
8532 MAYBE_RETURN(target_result, Nothing<bool>());
8533 if (target_result.FromJust()) {
8534 isolate->Throw(*factory->NewTypeError(
8535 MessageTemplate::kProxyPreventExtensionsExtensible));
8536 return Nothing<bool>();
8542 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject>
object,
8543 ShouldThrow should_throw) {
8544 Isolate* isolate =
object->GetIsolate();
8546 if (!object->HasSloppyArgumentsElements()) {
8547 return PreventExtensionsWithTransition<NONE>(object, should_throw);
8550 if (object->IsAccessCheckNeeded() &&
8551 !isolate->MayAccess(handle(isolate->context(), isolate),
object)) {
8552 isolate->ReportFailedAccessCheck(
object);
8553 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
8554 RETURN_FAILURE(isolate, should_throw,
8555 NewTypeError(MessageTemplate::kNoAccess));
8558 if (!object->map()->is_extensible())
return Just(
true);
8560 if (object->IsJSGlobalProxy()) {
8561 PrototypeIterator iter(isolate,
object);
8562 if (iter.IsAtEnd())
return Just(
true);
8563 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
8564 return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
8568 if (object->map()->has_named_interceptor() ||
8569 object->map()->has_indexed_interceptor()) {
8570 RETURN_FAILURE(isolate, should_throw,
8571 NewTypeError(MessageTemplate::kCannotPreventExt));
8574 if (!object->HasFixedTypedArrayElements()) {
8576 Handle<NumberDictionary> dictionary = NormalizeElements(
object);
8577 DCHECK(object->HasDictionaryElements() ||
8578 object->HasSlowArgumentsElements());
8581 object->RequireSlowElements(*dictionary);
8587 Handle<Map> new_map =
8588 Map::Copy(isolate, handle(object->map(), isolate),
"PreventExtensions");
8590 new_map->set_is_extensible(
false);
8591 JSObject::MigrateToMap(
object, new_map);
8592 DCHECK(!object->map()->is_extensible());
8598 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver>
object) {
8599 if (object->IsJSProxy()) {
8600 return JSProxy::IsExtensible(Handle<JSProxy>::cast(
object));
8602 return Just(JSObject::IsExtensible(Handle<JSObject>::cast(
object)));
8606 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
8607 Isolate* isolate = proxy->GetIsolate();
8608 STACK_CHECK(isolate, Nothing<bool>());
8609 Factory* factory = isolate->factory();
8610 Handle<String> trap_name = factory->isExtensible_string();
8612 if (proxy->IsRevoked()) {
8614 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
8615 return Nothing<bool>();
8617 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8618 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
8620 Handle<Object> trap;
8621 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8622 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
8623 if (trap->IsUndefined(isolate)) {
8624 return JSReceiver::IsExtensible(target);
8627 Handle<Object> trap_result;
8628 Handle<Object> args[] = {target};
8629 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8630 isolate, trap_result,
8631 Execution::Call(isolate, trap, handler, arraysize(args), args),
8635 Maybe<bool> target_result = JSReceiver::IsExtensible(target);
8636 MAYBE_RETURN(target_result, Nothing<bool>());
8637 if (target_result.FromJust() != trap_result->BooleanValue(isolate)) {
8639 *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
8640 factory->ToBoolean(target_result.FromJust())));
8641 return Nothing<bool>();
8643 return target_result;
8647 bool JSObject::IsExtensible(Handle<JSObject>
object) {
8648 Isolate* isolate =
object->GetIsolate();
8649 if (object->IsAccessCheckNeeded() &&
8650 !isolate->MayAccess(handle(isolate->context(), isolate),
object)) {
8653 if (object->IsJSGlobalProxy()) {
8654 PrototypeIterator iter(isolate, *
object);
8655 if (iter.IsAtEnd())
return false;
8656 DCHECK(iter.GetCurrent()->IsJSGlobalObject());
8657 return iter.GetCurrent<JSObject>()->map()->is_extensible();
8659 return object->map()->is_extensible();
8664 template <
typename Dictionary>
8665 void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
8666 Handle<Dictionary> dictionary,
8667 const PropertyAttributes attributes) {
8668 int capacity = dictionary->Capacity();
8669 for (
int i = 0;
i < capacity;
i++) {
8671 if (!dictionary->ToKey(roots,
i, &k))
continue;
8672 if (k->FilterKey(ALL_PROPERTIES))
continue;
8673 PropertyDetails details = dictionary->DetailsAt(
i);
8674 int attrs = attributes;
8676 if ((attributes & READ_ONLY) && details.kind() == kAccessor) {
8677 Object* v = dictionary->ValueAt(
i);
8678 if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
8680 details = details.CopyAddAttributes(static_cast<PropertyAttributes>(attrs));
8681 dictionary->DetailsAtPut(isolate,
i, details);
8687 template <PropertyAttributes attrs>
8688 Maybe<bool> JSObject::PreventExtensionsWithTransition(
8689 Handle<JSObject>
object, ShouldThrow should_throw) {
8690 STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
8694 DCHECK(!object->HasSloppyArgumentsElements());
8695 DCHECK_IMPLIES(object->IsJSModuleNamespace(), attrs == NONE);
8697 Isolate* isolate =
object->GetIsolate();
8698 if (object->IsAccessCheckNeeded() &&
8699 !isolate->MayAccess(handle(isolate->context(), isolate),
object)) {
8700 isolate->ReportFailedAccessCheck(
object);
8701 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
8702 RETURN_FAILURE(isolate, should_throw,
8703 NewTypeError(MessageTemplate::kNoAccess));
8706 if (attrs == NONE && !object->map()->is_extensible())
return Just(
true);
8708 if (object->IsJSGlobalProxy()) {
8709 PrototypeIterator iter(isolate,
object);
8710 if (iter.IsAtEnd())
return Just(
true);
8711 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
8712 return PreventExtensionsWithTransition<attrs>(
8713 PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
8716 if (object->map()->has_named_interceptor() ||
8717 object->map()->has_indexed_interceptor()) {
8718 MessageTemplate message = MessageTemplate::kNone;
8721 message = MessageTemplate::kCannotPreventExt;
8725 message = MessageTemplate::kCannotSeal;
8729 message = MessageTemplate::kCannotFreeze;
8732 RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
8735 Handle<NumberDictionary> new_element_dictionary;
8736 if (!object->HasFixedTypedArrayElements() &&
8737 !
object->HasDictionaryElements() &&
8738 !
object->HasSlowStringWrapperElements()) {
8739 int length =
object->IsJSArray()
8740 ? Smi::ToInt(Handle<JSArray>::cast(
object)->length())
8741 : object->elements()->length();
8742 new_element_dictionary =
8743 length == 0 ? isolate->factory()->empty_slow_element_dictionary()
8744 :
object->GetElementsAccessor()->Normalize(
object);
8747 Handle<Symbol> transition_marker;
8748 if (attrs == NONE) {
8749 transition_marker = isolate->factory()->nonextensible_symbol();
8750 }
else if (attrs == SEALED) {
8751 transition_marker = isolate->factory()->sealed_symbol();
8753 DCHECK(attrs == FROZEN);
8754 transition_marker = isolate->factory()->frozen_symbol();
8757 Handle<Map> old_map(object->map(), isolate);
8758 TransitionsAccessor transitions(isolate, old_map);
8759 Map transition = transitions.SearchSpecial(*transition_marker);
8760 if (!transition.is_null()) {
8761 Handle<Map> transition_map(transition, isolate);
8762 DCHECK(transition_map->has_dictionary_elements() ||
8763 transition_map->has_fixed_typed_array_elements() ||
8764 transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
8765 DCHECK(!transition_map->is_extensible());
8766 JSObject::MigrateToMap(
object, transition_map);
8767 }
else if (transitions.CanHaveMoreTransitions()) {
8769 Handle<Map> new_map = Map::CopyForPreventExtensions(
8770 isolate, old_map, attrs, transition_marker,
"CopyForPreventExtensions");
8771 JSObject::MigrateToMap(
object, new_map);
8773 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
8775 NormalizeProperties(
object, CLEAR_INOBJECT_PROPERTIES, 0,
8776 "SlowPreventExtensions");
8780 Handle<Map> new_map = Map::Copy(isolate, handle(object->map(), isolate),
8781 "SlowCopyForPreventExtensions");
8782 new_map->set_is_extensible(
false);
8783 if (!new_element_dictionary.is_null()) {
8784 ElementsKind new_kind =
8785 IsStringWrapperElementsKind(old_map->elements_kind())
8786 ? SLOW_STRING_WRAPPER_ELEMENTS
8787 : DICTIONARY_ELEMENTS;
8788 new_map->set_elements_kind(new_kind);
8790 JSObject::MigrateToMap(
object, new_map);
8792 if (attrs != NONE) {
8793 ReadOnlyRoots roots(isolate);
8794 if (object->IsJSGlobalObject()) {
8795 Handle<GlobalDictionary> dictionary(
8796 JSGlobalObject::cast(*object)->global_dictionary(), isolate);
8797 ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
8799 Handle<NameDictionary> dictionary(object->property_dictionary(),
8801 ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
8808 if (object->HasFixedTypedArrayElements()) {
8809 if (attrs == FROZEN &&
8810 JSArrayBufferView::cast(*object)->byte_length() > 0) {
8811 isolate->Throw(*isolate->factory()->NewTypeError(
8812 MessageTemplate::kCannotFreezeArrayBufferView));
8813 return Nothing<bool>();
8818 DCHECK(object->map()->has_dictionary_elements() ||
8819 object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
8820 if (!new_element_dictionary.is_null()) {
8821 object->set_elements(*new_element_dictionary);
8824 if (object->elements() !=
8825 ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
8826 Handle<NumberDictionary> dictionary(object->element_dictionary(), isolate);
8828 object->RequireSlowElements(*dictionary);
8829 if (attrs != NONE) {
8830 ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate), dictionary,
8839 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject>
object,
8840 Representation representation,
8842 Isolate* isolate =
object->GetIsolate();
8843 if (object->IsUnboxedDoubleField(index)) {
8844 double value =
object->RawFastDoublePropertyAt(index);
8845 return isolate->factory()->NewHeapNumber(value);
8847 Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
8848 return Object::WrapForRead(isolate, raw_value, representation);
8852 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
8853 ToPrimitiveHint hint) {
8854 Isolate*
const isolate = receiver->GetIsolate();
8855 Handle<Object> exotic_to_prim;
8856 ASSIGN_RETURN_ON_EXCEPTION(
8857 isolate, exotic_to_prim,
8858 GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
8859 if (!exotic_to_prim->IsUndefined(isolate)) {
8860 Handle<Object> hint_string =
8861 isolate->factory()->ToPrimitiveHintString(hint);
8862 Handle<Object> result;
8863 ASSIGN_RETURN_ON_EXCEPTION(
8865 Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
8867 if (result->IsPrimitive())
return result;
8868 THROW_NEW_ERROR(isolate,
8869 NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8872 return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
8873 ? OrdinaryToPrimitiveHint::kString
8874 : OrdinaryToPrimitiveHint::kNumber);
8879 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
8880 Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
8881 Isolate*
const isolate = receiver->GetIsolate();
8882 Handle<String> method_names[2];
8884 case OrdinaryToPrimitiveHint::kNumber:
8885 method_names[0] = isolate->factory()->valueOf_string();
8886 method_names[1] = isolate->factory()->toString_string();
8888 case OrdinaryToPrimitiveHint::kString:
8889 method_names[0] = isolate->factory()->toString_string();
8890 method_names[1] = isolate->factory()->valueOf_string();
8893 for (Handle<String> name : method_names) {
8894 Handle<Object> method;
8895 ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
8896 JSReceiver::GetProperty(isolate, receiver, name),
8898 if (method->IsCallable()) {
8899 Handle<Object> result;
8900 ASSIGN_RETURN_ON_EXCEPTION(
8902 Execution::Call(isolate, method, receiver, 0,
nullptr), Object);
8903 if (result->IsPrimitive())
return result;
8906 THROW_NEW_ERROR(isolate,
8907 NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8913 bool JSObject::HasEnumerableElements() {
8915 JSObject*
object =
this;
8916 switch (object->GetElementsKind()) {
8917 case PACKED_SMI_ELEMENTS:
8918 case PACKED_ELEMENTS:
8919 case PACKED_DOUBLE_ELEMENTS: {
8920 int length =
object->IsJSArray()
8921 ? Smi::ToInt(JSArray::cast(
object)->length())
8922 : object->elements()->length();
8925 case HOLEY_SMI_ELEMENTS:
8926 case HOLEY_ELEMENTS: {
8927 FixedArray elements = FixedArray::cast(object->elements());
8928 int length =
object->IsJSArray()
8929 ? Smi::ToInt(JSArray::cast(
object)->length())
8930 : elements->length();
8931 Isolate* isolate = GetIsolate();
8932 for (
int i = 0;
i < length;
i++) {
8933 if (!elements->is_the_hole(isolate,
i))
return true;
8937 case HOLEY_DOUBLE_ELEMENTS: {
8938 int length =
object->IsJSArray()
8939 ? Smi::ToInt(JSArray::cast(
object)->length())
8940 : object->elements()->length();
8942 if (length == 0)
return false;
8944 FixedDoubleArray elements = FixedDoubleArray::cast(object->elements());
8945 for (
int i = 0;
i < length;
i++) {
8946 if (!elements->is_the_hole(
i))
return true;
8950 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS: 8952 TYPED_ARRAYS(TYPED_ARRAY_CASE)
8953 #undef TYPED_ARRAY_CASE 8955 int length =
object->elements()->length();
8958 case DICTIONARY_ELEMENTS: {
8959 NumberDictionary elements = NumberDictionary::cast(object->elements());
8960 return elements->NumberOfEnumerableProperties() > 0;
8962 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8963 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8966 case FAST_STRING_WRAPPER_ELEMENTS:
8967 case SLOW_STRING_WRAPPER_ELEMENTS:
8968 if (String::cast(JSValue::cast(
object)->value())->length() > 0) {
8971 return object->elements()->length() > 0;
8978 int Map::NumberOfEnumerableProperties()
const {
8980 DescriptorArray* descs = instance_descriptors();
8981 int limit = NumberOfOwnDescriptors();
8982 for (
int i = 0;
i < limit;
i++) {
8983 if ((descs->GetDetails(
i).attributes() & ONLY_ENUMERABLE) == 0 &&
8984 !descs->GetKey(
i)->FilterKey(ENUMERABLE_STRINGS)) {
8991 int Map::NextFreePropertyIndex()
const {
8993 int number_of_own_descriptors = NumberOfOwnDescriptors();
8994 DescriptorArray* descs = instance_descriptors();
8995 for (
int i = 0;
i < number_of_own_descriptors;
i++) {
8996 PropertyDetails details = descs->GetDetails(
i);
8997 if (details.location() == kField) {
8998 int candidate = details.field_index() + details.field_width_in_words();
8999 if (candidate > free_index) free_index = candidate;
9005 bool Map::OnlyHasSimpleProperties()
const {
9008 return !IsStringWrapperElementsKind(elements_kind()) &&
9009 !IsSpecialReceiverMap() && !has_hidden_prototype() &&
9010 !is_dictionary_map();
9013 V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
9014 Isolate* isolate, Handle<JSReceiver> receiver,
bool get_entries,
9015 Handle<FixedArray>* result) {
9016 Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
9018 if (!map->IsJSObjectMap())
return Just(
false);
9019 if (!map->OnlyHasSimpleProperties())
return Just(
false);
9021 Handle<JSObject> object(JSObject::cast(*receiver), isolate);
9023 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9024 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9025 int number_of_own_elements =
9026 object->GetElementsAccessor()->GetCapacity(*
object, object->elements());
9027 Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
9028 number_of_own_descriptors + number_of_own_elements);
9031 if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
9032 MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
9033 isolate,
object, values_or_entries, get_entries, &count,
9034 ENUMERABLE_STRINGS),
9038 bool stable =
object->map() == *map;
9040 for (
int index = 0; index < number_of_own_descriptors; index++) {
9041 Handle<Name> next_key(descriptors->GetKey(index), isolate);
9042 if (!next_key->IsString())
continue;
9043 Handle<Object> prop_value;
9047 PropertyDetails details = descriptors->GetDetails(index);
9048 if (!details.IsEnumerable())
continue;
9049 if (details.kind() == kData) {
9050 if (details.location() == kDescriptor) {
9051 prop_value = handle(descriptors->GetStrongValue(index), isolate);
9053 Representation representation = details.representation();
9054 FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
9056 JSObject::FastPropertyAt(
object, representation, field_index);
9059 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9060 isolate, prop_value,
9061 JSReceiver::GetProperty(isolate,
object, next_key),
9063 stable =
object->map() == *map;
9068 LookupIterator it(isolate,
object, next_key,
9069 LookupIterator::OWN_SKIP_INTERCEPTOR);
9070 if (!it.IsFound())
continue;
9071 DCHECK(it.state() == LookupIterator::DATA ||
9072 it.state() == LookupIterator::ACCESSOR);
9073 if (!it.IsEnumerable())
continue;
9074 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9075 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
9079 prop_value = MakeEntryPair(isolate, next_key, prop_value);
9082 values_or_entries->set(count, *prop_value);
9086 DCHECK_LE(count, values_or_entries->length());
9087 *result = FixedArray::ShrinkOrEmpty(isolate, values_or_entries, count);
9091 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
9092 Handle<JSReceiver>
object,
9096 Handle<FixedArray> values_or_entries;
9097 if (try_fast_path && filter == ENUMERABLE_STRINGS) {
9098 Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
9099 isolate,
object, get_entries, &values_or_entries);
9100 if (fast_values_or_entries.IsNothing())
return MaybeHandle<FixedArray>();
9101 if (fast_values_or_entries.FromJust())
return values_or_entries;
9107 Handle<FixedArray> keys;
9108 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9110 KeyAccumulator::GetKeys(
object, KeyCollectionMode::kOwnOnly, key_filter,
9111 GetKeysConversion::kConvertToString),
9112 MaybeHandle<FixedArray>());
9114 values_or_entries = isolate->factory()->NewFixedArray(keys->length());
9117 for (
int i = 0;
i < keys->length(); ++
i) {
9118 Handle<Name> key = Handle<Name>::cast(handle(keys->get(
i), isolate));
9120 if (filter & ONLY_ENUMERABLE) {
9121 PropertyDescriptor descriptor;
9122 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
9123 isolate,
object, key, &descriptor);
9124 MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
9125 if (!did_get_descriptor.FromJust() || !descriptor.enumerable())
continue;
9128 Handle<Object> value;
9129 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9130 isolate, value, JSReceiver::GetPropertyOrElement(isolate,
object, key),
9131 MaybeHandle<FixedArray>());
9134 Handle<FixedArray> entry_storage =
9135 isolate->factory()->NewUninitializedFixedArray(2);
9136 entry_storage->set(0, *key);
9137 entry_storage->set(1, *value);
9138 value = isolate->factory()->NewJSArrayWithElements(entry_storage,
9139 PACKED_ELEMENTS, 2);
9142 values_or_entries->set(length, *value);
9145 DCHECK_LE(length, values_or_entries->length());
9146 return FixedArray::ShrinkOrEmpty(isolate, values_or_entries, length);
9149 MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver>
object,
9151 bool try_fast_path) {
9152 return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
9153 try_fast_path,
false);
9156 MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver>
object,
9158 bool try_fast_path) {
9159 return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
9160 try_fast_path,
true);
9163 Handle<FixedArray> JSReceiver::GetOwnElementIndices(Isolate* isolate,
9164 Handle<JSReceiver> receiver,
9165 Handle<JSObject>
object) {
9166 KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
9168 accumulator.CollectOwnElementIndices(receiver,
object);
9169 Handle<FixedArray> keys =
9170 accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
9171 DCHECK(keys->ContainsSortedNumbers());
9175 bool Map::DictionaryElementsInPrototypeChainOnly(Isolate* isolate) {
9176 if (IsDictionaryElementsKind(elements_kind())) {
9180 for (PrototypeIterator iter(isolate, *
this); !iter.IsAtEnd();
9183 if (iter.GetCurrent()->IsJSProxy())
return true;
9185 if (iter.GetCurrent()->IsStringWrapper())
return true;
9186 JSObject* current = iter.GetCurrent<JSObject>();
9188 if (current->HasDictionaryElements() &&
9189 current->element_dictionary()->requires_slow_elements()) {
9193 if (current->HasSlowArgumentsElements()) {
9194 FixedArray parameter_map = FixedArray::cast(current->elements());
9195 Object* arguments = parameter_map->get(1);
9196 if (NumberDictionary::cast(arguments)->requires_slow_elements()) {
9206 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject>
object,
9208 Handle<Object> getter,
9209 Handle<Object> setter,
9210 PropertyAttributes attributes) {
9211 Isolate* isolate =
object->GetIsolate();
9213 LookupIterator it = LookupIterator::PropertyOrElement(
9214 isolate,
object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
9215 return DefineAccessor(&it, getter, setter, attributes);
9219 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
9220 Handle<Object> getter,
9221 Handle<Object> setter,
9222 PropertyAttributes attributes) {
9223 Isolate* isolate = it->isolate();
9225 it->UpdateProtector();
9227 if (it->state() == LookupIterator::ACCESS_CHECK) {
9228 if (!it->HasAccess()) {
9229 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
9230 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9231 return isolate->factory()->undefined_value();
9236 Handle<JSObject>
object = Handle<JSObject>::cast(it->GetReceiver());
9238 if (it->IsElement() &&
object->HasFixedTypedArrayElements()) {
9239 return it->factory()->undefined_value();
9242 DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
9243 getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
9244 DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
9245 setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
9246 it->TransitionToAccessorProperty(getter, setter, attributes);
9248 return isolate->factory()->undefined_value();
9251 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject>
object,
9253 Handle<AccessorInfo> info,
9254 PropertyAttributes attributes) {
9255 Isolate* isolate =
object->GetIsolate();
9257 LookupIterator it = LookupIterator::PropertyOrElement(
9258 isolate,
object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
9265 if (it.state() == LookupIterator::ACCESS_CHECK) {
9266 if (!it.HasAccess()) {
9267 isolate->ReportFailedAccessCheck(
object);
9268 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9269 return it.factory()->undefined_value();
9275 if (it.IsElement() &&
object->HasFixedTypedArrayElements()) {
9276 return it.factory()->undefined_value();
9279 CHECK(GetPropertyAttributes(&it).IsJust());
9283 if (it.IsFound() && !it.IsConfigurable()) {
9284 return it.factory()->undefined_value();
9287 it.TransitionToAccessorPair(info, attributes);
9292 Object* JSObject::SlowReverseLookup(Object* value) {
9293 if (HasFastProperties()) {
9294 int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
9295 DescriptorArray* descs = map()->instance_descriptors();
9296 bool value_is_number = value->IsNumber();
9297 for (
int i = 0;
i < number_of_own_descriptors;
i++) {
9298 PropertyDetails details = descs->GetDetails(
i);
9299 if (details.location() == kField) {
9300 DCHECK_EQ(kData, details.kind());
9301 FieldIndex field_index = FieldIndex::ForDescriptor(map(),
i);
9302 if (IsUnboxedDoubleField(field_index)) {
9303 if (value_is_number) {
9304 double property = RawFastDoublePropertyAt(field_index);
9305 if (property == value->Number()) {
9306 return descs->GetKey(
i);
9310 Object*
property = RawFastPropertyAt(field_index);
9311 if (field_index.is_double()) {
9312 DCHECK(property->IsMutableHeapNumber());
9313 if (value_is_number && property->Number() == value->Number()) {
9314 return descs->GetKey(
i);
9316 }
else if (property == value) {
9317 return descs->GetKey(
i);
9321 DCHECK_EQ(kDescriptor, details.location());
9322 if (details.kind() == kData) {
9323 if (descs->GetStrongValue(
i) == value) {
9324 return descs->GetKey(
i);
9329 return GetReadOnlyRoots().undefined_value();
9330 }
else if (IsJSGlobalObject()) {
9331 return JSGlobalObject::cast(
this)->global_dictionary()->SlowReverseLookup(
9334 return property_dictionary()->SlowReverseLookup(value);
9338 Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map,
int instance_size,
9339 int inobject_properties) {
9340 Handle<Map> result = isolate->factory()->NewMap(
9341 map->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND,
9342 inobject_properties);
9343 Handle<Object> prototype(map->prototype(), isolate);
9344 Map::SetPrototype(isolate, result, prototype);
9345 result->set_constructor_or_backpointer(map->GetConstructor());
9346 result->set_bit_field(map->bit_field());
9347 result->set_bit_field2(map->bit_field2());
9348 int new_bit_field3 = map->bit_field3();
9349 new_bit_field3 = OwnsDescriptorsBit::update(new_bit_field3,
true);
9350 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
9351 new_bit_field3 = EnumLengthBits::update(new_bit_field3,
9352 kInvalidEnumCacheSentinel);
9353 new_bit_field3 = IsDeprecatedBit::update(new_bit_field3,
false);
9354 if (!map->is_dictionary_map()) {
9355 new_bit_field3 = IsUnstableBit::update(new_bit_field3,
false);
9357 result->set_bit_field3(new_bit_field3);
9361 Handle<Map> Map::Normalize(Isolate* isolate, Handle<Map> fast_map,
9362 PropertyNormalizationMode mode,
const char* reason) {
9363 DCHECK(!fast_map->is_dictionary_map());
9365 Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
9368 !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
9369 Handle<NormalizedMapCache> cache;
9370 if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
9372 Handle<Map> new_map;
9373 if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
9375 if (FLAG_verify_heap) new_map->DictionaryMapVerify(isolate);
9377 #ifdef ENABLE_SLOW_DCHECKS 9378 if (FLAG_enable_slow_asserts) {
9382 Handle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);
9384 if (new_map->is_prototype_map()) {
9386 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
9387 reinterpret_cast<void*>(new_map->address()),
9388 kTransitionsOrPrototypeInfoOffset));
9389 DCHECK_EQ(fresh->raw_transitions(),
9390 MaybeObject::FromObject(Smi::kZero));
9391 STATIC_ASSERT(kDescriptorsOffset ==
9392 kTransitionsOrPrototypeInfoOffset + kPointerSize);
9396 HeapObject::RawField(*fresh, kDescriptorsOffset).ToVoidPtr(),
9397 HeapObject::RawField(*new_map, kDescriptorsOffset).ToVoidPtr(),
9398 kDependentCodeOffset - kDescriptorsOffset));
9400 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
9401 reinterpret_cast<void*>(new_map->address()),
9402 Map::kDependentCodeOffset));
9404 STATIC_ASSERT(Map::kPrototypeValidityCellOffset ==
9405 Map::kDependentCodeOffset + kPointerSize);
9406 int offset = Map::kPrototypeValidityCellOffset + kPointerSize;
9407 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
9408 reinterpret_cast<void*>(new_map->address() + offset),
9409 Map::kSize - offset));
9413 new_map = Map::CopyNormalized(isolate, fast_map, mode);
9415 cache->Set(fast_map, new_map);
9416 isolate->counters()->maps_normalized()->Increment();
9418 if (FLAG_trace_maps) {
9419 LOG(isolate, MapEvent(
"Normalize", *fast_map, *new_map, reason));
9422 fast_map->NotifyLeafMapLayoutChange(isolate);
9426 Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,
9427 PropertyNormalizationMode mode) {
9428 int new_instance_size = map->instance_size();
9429 if (mode == CLEAR_INOBJECT_PROPERTIES) {
9430 new_instance_size -= map->GetInObjectProperties() * kPointerSize;
9433 Handle<Map> result = RawCopy(
9434 isolate, map, new_instance_size,
9435 mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
9438 result->SetInObjectUnusedPropertyFields(0);
9439 result->set_is_dictionary_map(
true);
9440 result->set_is_migration_target(
false);
9441 result->set_may_have_interesting_symbols(
true);
9442 result->set_construction_counter(kNoSlackTracking);
9445 if (FLAG_verify_heap) result->DictionaryMapVerify(isolate);
9457 Handle<Map> Map::TransitionToImmutableProto(Isolate* isolate, Handle<Map> map) {
9458 Handle<Map> new_map = Map::Copy(isolate, map,
"ImmutablePrototype");
9459 new_map->set_is_immutable_proto(
true);
9464 void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
9469 Object* constructor = map->GetConstructor();
9470 DCHECK(constructor->IsJSFunction());
9471 DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
9472 *map == *isolate->strict_function_map() ||
9473 *map == *isolate->strict_function_with_name_map() ||
9474 *map == *isolate->generator_function_map() ||
9475 *map == *isolate->generator_function_with_name_map() ||
9476 *map == *isolate->generator_function_with_home_object_map() ||
9477 *map == *isolate->generator_function_with_name_and_home_object_map() ||
9478 *map == *isolate->async_function_map() ||
9479 *map == *isolate->async_function_with_name_map() ||
9480 *map == *isolate->async_function_with_home_object_map() ||
9481 *map == *isolate->async_function_with_name_and_home_object_map());
9485 DCHECK(map->owns_descriptors());
9486 DCHECK_EQ(map->NumberOfOwnDescriptors(),
9487 map->instance_descriptors()->number_of_descriptors());
9492 Handle<Map> Map::CopyInitialMapNormalized(Isolate* isolate, Handle<Map> map,
9493 PropertyNormalizationMode mode) {
9494 EnsureInitialMap(isolate, map);
9495 return CopyNormalized(isolate, map, mode);
9499 Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
9500 int instance_size,
int inobject_properties,
9501 int unused_property_fields) {
9502 EnsureInitialMap(isolate, map);
9503 Handle<Map> result =
9504 RawCopy(isolate, map, instance_size, inobject_properties);
9507 result->SetInObjectUnusedPropertyFields(unused_property_fields);
9509 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9510 if (number_of_own_descriptors > 0) {
9512 result->UpdateDescriptors(map->instance_descriptors(),
9513 map->GetLayoutDescriptor());
9514 result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
9516 DCHECK_EQ(result->NumberOfFields(),
9517 result->GetInObjectProperties() - result->UnusedPropertyFields());
9523 Handle<Map> Map::CopyDropDescriptors(Isolate* isolate, Handle<Map> map) {
9524 Handle<Map> result =
9525 RawCopy(isolate, map, map->instance_size(),
9526 map->IsJSObjectMap() ? map->GetInObjectProperties() : 0);
9529 if (map->IsJSObjectMap()) {
9530 result->CopyUnusedPropertyFields(*map);
9532 map->NotifyLeafMapLayoutChange(isolate);
9536 Handle<Map> Map::ShareDescriptor(Isolate* isolate, Handle<Map> map,
9537 Handle<DescriptorArray> descriptors,
9538 Descriptor* descriptor) {
9542 DCHECK_EQ(map->NumberOfOwnDescriptors(),
9543 map->instance_descriptors()->number_of_descriptors());
9545 Handle<Map> result = CopyDropDescriptors(isolate, map);
9546 Handle<Name> name = descriptor->GetKey();
9549 if (name->IsInterestingSymbol()) {
9550 result->set_may_have_interesting_symbols(
true);
9554 if (descriptors->number_of_slack_descriptors() == 0) {
9555 int old_size = descriptors->number_of_descriptors();
9556 if (old_size == 0) {
9557 descriptors = DescriptorArray::Allocate(isolate, 0, 1);
9559 int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
9560 EnsureDescriptorSlack(isolate, map, slack);
9561 descriptors = handle(map->instance_descriptors(), isolate);
9565 Handle<LayoutDescriptor> layout_descriptor =
9566 FLAG_unbox_double_fields
9567 ? LayoutDescriptor::ShareAppend(isolate, map,
9568 descriptor->GetDetails())
9569 : handle(LayoutDescriptor::FastPointerLayout(), isolate);
9572 DisallowHeapAllocation no_gc;
9573 descriptors->Append(descriptor);
9574 result->InitializeDescriptors(*descriptors, *layout_descriptor);
9577 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
9578 ConnectTransition(isolate, map, result, name, SIMPLE_PROPERTY_TRANSITION);
9583 void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
9584 Handle<Map> child, Handle<Name> name,
9585 SimpleTransitionFlag flag) {
9586 DCHECK_IMPLIES(name->IsInterestingSymbol(),
9587 child->may_have_interesting_symbols());
9588 DCHECK_IMPLIES(parent->may_have_interesting_symbols(),
9589 child->may_have_interesting_symbols());
9591 if (isolate->bootstrapper()->IsActive() &&
9592 !name.is_identical_to(isolate->factory()->elements_transition_symbol())) {
9593 if (FLAG_trace_maps) {
9595 MapEvent(
"Transition", *parent, *child,
9596 child->is_prototype_map() ?
"prototype" :
"", *name));
9600 if (!parent->GetBackPointer()->IsUndefined(isolate)) {
9601 parent->set_owns_descriptors(
false);
9605 DCHECK(parent->owns_descriptors());
9606 DCHECK_EQ(parent->NumberOfOwnDescriptors(),
9607 parent->instance_descriptors()->number_of_descriptors());
9609 if (parent->is_prototype_map()) {
9610 DCHECK(child->is_prototype_map());
9611 if (FLAG_trace_maps) {
9612 LOG(isolate, MapEvent(
"Transition", *parent, *child,
"prototype", *name));
9615 TransitionsAccessor(isolate, parent).Insert(name, child, flag);
9616 if (FLAG_trace_maps) {
9617 LOG(isolate, MapEvent(
"Transition", *parent, *child,
"", *name));
9622 Handle<Map> Map::CopyReplaceDescriptors(
9623 Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
9624 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
9625 MaybeHandle<Name> maybe_name,
const char* reason,
9626 SimpleTransitionFlag simple_flag) {
9627 DCHECK(descriptors->IsSortedNoDuplicates());
9629 Handle<Map> result = CopyDropDescriptors(isolate, map);
9633 if (maybe_name.ToHandle(&name) && name->IsInterestingSymbol()) {
9634 result->set_may_have_interesting_symbols(
true);
9637 if (!map->is_prototype_map()) {
9638 if (flag == INSERT_TRANSITION &&
9639 TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
9640 result->InitializeDescriptors(*descriptors, *layout_descriptor);
9642 DCHECK(!maybe_name.is_null());
9643 ConnectTransition(isolate, map, result, name, simple_flag);
9645 descriptors->GeneralizeAllFields();
9646 result->InitializeDescriptors(*descriptors,
9647 LayoutDescriptor::FastPointerLayout());
9650 result->InitializeDescriptors(*descriptors, *layout_descriptor);
9652 if (FLAG_trace_maps &&
9654 (map->is_prototype_map() ||
9655 !(flag == INSERT_TRANSITION &&
9656 TransitionsAccessor(isolate, map).CanHaveMoreTransitions()))) {
9657 LOG(isolate, MapEvent(
"ReplaceDescriptors", *map, *result, reason,
9658 maybe_name.is_null() ? Name() : *name));
9668 Handle<Map> Map::AddMissingTransitions(
9669 Isolate* isolate, Handle<Map> split_map,
9670 Handle<DescriptorArray> descriptors,
9671 Handle<LayoutDescriptor> full_layout_descriptor) {
9672 DCHECK(descriptors->IsSortedNoDuplicates());
9673 int split_nof = split_map->NumberOfOwnDescriptors();
9674 int nof_descriptors = descriptors->number_of_descriptors();
9675 DCHECK_LT(split_nof, nof_descriptors);
9686 Handle<Map> last_map = CopyDropDescriptors(isolate, split_map);
9687 last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
9688 last_map->SetInObjectUnusedPropertyFields(0);
9689 last_map->set_may_have_interesting_symbols(
true);
9696 Handle<Map> map = split_map;
9697 for (
int i = split_nof;
i < nof_descriptors - 1; ++
i) {
9698 Handle<Map> new_map = CopyDropDescriptors(isolate, map);
9699 InstallDescriptors(isolate, map, new_map,
i, descriptors,
9700 full_layout_descriptor);
9704 map->NotifyLeafMapLayoutChange(isolate);
9705 last_map->set_may_have_interesting_symbols(
false);
9706 InstallDescriptors(isolate, map, last_map, nof_descriptors - 1, descriptors,
9707 full_layout_descriptor);
9714 void Map::InstallDescriptors(Isolate* isolate, Handle<Map> parent,
9715 Handle<Map> child,
int new_descriptor,
9716 Handle<DescriptorArray> descriptors,
9717 Handle<LayoutDescriptor> full_layout_descriptor) {
9718 DCHECK(descriptors->IsSortedNoDuplicates());
9720 child->set_instance_descriptors(*descriptors);
9721 child->SetNumberOfOwnDescriptors(new_descriptor + 1);
9722 child->CopyUnusedPropertyFields(*parent);
9723 PropertyDetails details = descriptors->GetDetails(new_descriptor);
9724 if (details.location() == kField) {
9725 child->AccountAddedPropertyField();
9728 if (FLAG_unbox_double_fields) {
9729 Handle<LayoutDescriptor> layout_descriptor =
9730 LayoutDescriptor::AppendIfFastOrUseFull(isolate, parent, details,
9731 full_layout_descriptor);
9732 child->set_layout_descriptor(*layout_descriptor);
9735 if (FLAG_verify_heap) {
9736 CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9739 SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9741 child->set_visitor_id(Map::GetVisitorId(*child));
9744 Handle<Name> name = handle(descriptors->GetKey(new_descriptor), isolate);
9745 if (parent->may_have_interesting_symbols() || name->IsInterestingSymbol()) {
9746 child->set_may_have_interesting_symbols(
true);
9748 ConnectTransition(isolate, parent, child, name, SIMPLE_PROPERTY_TRANSITION);
9751 Handle<Map> Map::CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
9752 ElementsKind kind, TransitionFlag flag) {
9755 DCHECK(map->IsJSObjectMap());
9757 !map->CanHaveFastTransitionableElementsKind(),
9758 IsDictionaryElementsKind(kind) || IsTerminalElementsKind(kind));
9760 Map maybe_elements_transition_map;
9761 if (flag == INSERT_TRANSITION) {
9763 DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
9764 map->NumberOfOwnDescriptors());
9766 maybe_elements_transition_map = map->ElementsTransitionMap();
9767 DCHECK(maybe_elements_transition_map.is_null() ||
9768 (maybe_elements_transition_map->elements_kind() ==
9769 DICTIONARY_ELEMENTS &&
9770 kind == DICTIONARY_ELEMENTS));
9771 DCHECK(!IsFastElementsKind(kind) ||
9772 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
9773 DCHECK(kind != map->elements_kind());
9776 bool insert_transition =
9777 flag == INSERT_TRANSITION &&
9778 TransitionsAccessor(isolate, map).CanHaveMoreTransitions() &&
9779 maybe_elements_transition_map.is_null();
9781 if (insert_transition) {
9782 Handle<Map> new_map = CopyForElementsTransition(isolate, map);
9783 new_map->set_elements_kind(kind);
9785 Handle<Name> name = isolate->factory()->elements_transition_symbol();
9786 ConnectTransition(isolate, map, new_map, name, SPECIAL_TRANSITION);
9791 Handle<Map> new_map = Copy(isolate, map,
"CopyAsElementsKind");
9792 new_map->set_elements_kind(kind);
9796 Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
9797 Handle<SharedFunctionInfo> shared_info) {
9798 DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
9802 if (is_sloppy(shared_info->language_mode()))
return initial_map;
9804 Handle<Map> function_map(Map::cast(isolate->native_context()->get(
9805 shared_info->function_map_index())),
9808 STATIC_ASSERT(LanguageModeSize == 2);
9809 DCHECK_EQ(LanguageMode::kStrict, shared_info->language_mode());
9810 Handle<Symbol> transition_symbol =
9811 isolate->factory()->strict_function_transition_symbol();
9812 Map maybe_transition = TransitionsAccessor(isolate, initial_map)
9813 .SearchSpecial(*transition_symbol);
9814 if (!maybe_transition.is_null()) {
9815 return handle(maybe_transition, isolate);
9817 initial_map->NotifyLeafMapLayoutChange(isolate);
9822 Map::CopyInitialMap(isolate, function_map, initial_map->instance_size(),
9823 initial_map->GetInObjectProperties(),
9824 initial_map->UnusedPropertyFields());
9825 map->SetConstructor(initial_map->GetConstructor());
9826 map->set_prototype(initial_map->prototype());
9827 map->set_construction_counter(initial_map->construction_counter());
9829 if (TransitionsAccessor(isolate, initial_map).CanHaveMoreTransitions()) {
9830 Map::ConnectTransition(isolate, initial_map, map, transition_symbol,
9831 SPECIAL_TRANSITION);
9836 Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
9837 DCHECK(!map->is_prototype_map());
9838 Handle<Map> new_map = CopyDropDescriptors(isolate, map);
9840 if (map->owns_descriptors()) {
9844 new_map->InitializeDescriptors(map->instance_descriptors(),
9845 map->GetLayoutDescriptor());
9849 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9850 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9851 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
9852 isolate, descriptors, number_of_own_descriptors);
9853 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9855 new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
9860 Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map,
const char* reason) {
9861 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9862 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9863 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
9864 isolate, descriptors, number_of_own_descriptors);
9865 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9867 return CopyReplaceDescriptors(
9868 isolate, map, new_descriptors, new_layout_descriptor, OMIT_TRANSITION,
9869 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
9873 Handle<Map> Map::Create(Isolate* isolate,
int inobject_properties) {
9875 Copy(isolate, handle(isolate->object_function()->initial_map(), isolate),
9881 if (inobject_properties > JSObject::kMaxInObjectProperties) {
9882 inobject_properties = JSObject::kMaxInObjectProperties;
9885 int new_instance_size =
9886 JSObject::kHeaderSize + kPointerSize * inobject_properties;
9889 copy->set_instance_size(new_instance_size);
9890 copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kPointerSize);
9891 DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties);
9892 copy->SetInObjectUnusedPropertyFields(inobject_properties);
9893 copy->set_visitor_id(Map::GetVisitorId(*copy));
9897 Handle<Map> Map::CopyForPreventExtensions(Isolate* isolate, Handle<Map> map,
9898 PropertyAttributes attrs_to_add,
9899 Handle<Symbol> transition_marker,
9900 const char* reason) {
9901 int num_descriptors = map->NumberOfOwnDescriptors();
9902 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
9903 isolate, handle(map->instance_descriptors(), isolate), num_descriptors,
9905 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9907 Handle<Map> new_map = CopyReplaceDescriptors(
9908 isolate, map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
9909 transition_marker, reason, SPECIAL_TRANSITION);
9910 new_map->set_is_extensible(
false);
9911 if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
9912 ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
9913 ? SLOW_STRING_WRAPPER_ELEMENTS
9914 : DICTIONARY_ELEMENTS;
9915 new_map->set_elements_kind(new_kind);
9922 bool CanHoldValue(DescriptorArray* descriptors,
int descriptor,
9923 PropertyConstness constness, Object* value) {
9924 PropertyDetails details = descriptors->GetDetails(descriptor);
9925 if (details.location() == kField) {
9926 if (details.kind() == kData) {
9927 return IsGeneralizableTo(constness, details.constness()) &&
9928 value->FitsRepresentation(details.representation()) &&
9929 descriptors->GetFieldType(descriptor)->NowContains(value);
9931 DCHECK_EQ(kAccessor, details.kind());
9936 DCHECK_EQ(kDescriptor, details.location());
9937 DCHECK_EQ(PropertyConstness::kConst, details.constness());
9938 if (details.kind() == kData) {
9939 DCHECK(!FLAG_track_constant_fields);
9940 DCHECK(descriptors->GetStrongValue(descriptor) != value ||
9941 value->FitsRepresentation(details.representation()));
9942 return descriptors->GetStrongValue(descriptor) == value;
9944 DCHECK_EQ(kAccessor, details.kind());
9951 Handle<Map> UpdateDescriptorForValue(Isolate* isolate, Handle<Map> map,
9953 PropertyConstness constness,
9954 Handle<Object> value) {
9955 if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
9960 PropertyAttributes attributes =
9961 map->instance_descriptors()->GetDetails(descriptor).attributes();
9962 Representation representation = value->OptimalRepresentation();
9963 Handle<FieldType> type = value->OptimalType(isolate, representation);
9965 MapUpdater mu(isolate, map);
9966 return mu.ReconfigureToDataField(descriptor, attributes, constness,
9967 representation, type);
9973 Handle<Map> Map::PrepareForDataProperty(Isolate* isolate, Handle<Map> map,
9975 PropertyConstness constness,
9976 Handle<Object> value) {
9978 DCHECK(!map->is_dictionary_map());
9980 return UpdateDescriptorForValue(isolate, Update(isolate, map), descriptor,
9984 Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
9986 Handle<Object> value,
9987 PropertyAttributes attributes,
9988 PropertyConstness constness,
9989 StoreOrigin store_origin) {
9990 RuntimeCallTimerScope stats_scope(
9992 map->is_prototype_map()
9993 ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
9994 : RuntimeCallCounterId::kMap_TransitionToDataProperty);
9996 DCHECK(name->IsUniqueName());
9997 DCHECK(!map->is_dictionary_map());
10000 map = Update(isolate, map);
10002 Map maybe_transition = TransitionsAccessor(isolate, map)
10003 .SearchTransition(*name, kData, attributes);
10004 if (!maybe_transition.is_null()) {
10005 Handle<Map> transition(maybe_transition, isolate);
10006 int descriptor = transition->LastAdded();
10008 DCHECK_EQ(attributes, transition->instance_descriptors()
10009 ->GetDetails(descriptor)
10012 return UpdateDescriptorForValue(isolate, transition, descriptor, constness,
10016 TransitionFlag flag = INSERT_TRANSITION;
10017 MaybeHandle<Map> maybe_map;
10018 if (!map->TooManyFastProperties(store_origin)) {
10019 if (!FLAG_track_constant_fields && value->IsJSFunction()) {
10021 Map::CopyWithConstant(isolate, map, name, value, attributes, flag);
10023 Representation representation = value->OptimalRepresentation();
10024 Handle<FieldType> type = value->OptimalType(isolate, representation);
10025 maybe_map = Map::CopyWithField(isolate, map, name, type, attributes,
10026 constness, representation, flag);
10030 Handle<Map> result;
10031 if (!maybe_map.ToHandle(&result)) {
10032 const char* reason =
"TooManyFastProperties";
10034 std::unique_ptr<ScopedVector<char>> buffer;
10035 if (FLAG_trace_maps) {
10036 ScopedVector<char> name_buffer(100);
10037 name->NameShortPrint(name_buffer);
10038 buffer.reset(
new ScopedVector<char>(128));
10039 SNPrintF(*buffer,
"TooManyFastProperties %s", name_buffer.start());
10040 reason = buffer->start();
10043 Handle<Object> maybe_constructor(map->GetConstructor(), isolate);
10044 if (FLAG_feedback_normalization && map->new_target_is_base() &&
10045 maybe_constructor->IsJSFunction() &&
10046 !JSFunction::cast(*maybe_constructor)->shared()->native()) {
10047 Handle<JSFunction> constructor =
10048 Handle<JSFunction>::cast(maybe_constructor);
10049 DCHECK_NE(*constructor,
10050 constructor->context()->native_context()->object_function());
10051 Handle<Map> initial_map(constructor->initial_map(), isolate);
10052 result = Map::Normalize(isolate, initial_map, CLEAR_INOBJECT_PROPERTIES,
10054 initial_map->DeprecateTransitionTree(isolate);
10055 Handle<Object> prototype(result->prototype(), isolate);
10056 JSFunction::SetInitialMap(constructor, result, prototype);
10059 initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
10060 isolate, DependentCode::kInitialMapChangedGroup);
10061 if (!result->EquivalentToForNormalization(*map,
10062 CLEAR_INOBJECT_PROPERTIES)) {
10064 Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
10067 result = Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
10074 Handle<Map> Map::ReconfigureExistingProperty(Isolate* isolate, Handle<Map> map,
10075 int descriptor, PropertyKind kind,
10076 PropertyAttributes attributes) {
10078 DCHECK(!map->is_dictionary_map());
10080 if (!map->GetBackPointer()->IsMap()) {
10083 return CopyGeneralizeAllFields(isolate, map, map->elements_kind(),
10084 descriptor, kind, attributes,
10085 "GenAll_AttributesMismatchProtoMap");
10088 if (FLAG_trace_generalization) {
10089 map->PrintReconfiguration(isolate, stdout, descriptor, kind, attributes);
10092 MapUpdater mu(isolate, map);
10093 DCHECK_EQ(kData, kind);
10094 Handle<Map> new_map = mu.ReconfigureToDataField(
10095 descriptor, attributes, kDefaultFieldConstness, Representation::None(),
10096 FieldType::None(isolate));
10100 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
10101 Handle<Name> name,
int descriptor,
10102 Handle<Object> getter,
10103 Handle<Object> setter,
10104 PropertyAttributes attributes) {
10105 RuntimeCallTimerScope stats_scope(
10107 map->is_prototype_map()
10108 ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
10109 : RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
10112 DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
10113 DCHECK(name->IsUniqueName());
10116 if (map->is_dictionary_map())
return map;
10119 map = Update(isolate, map);
10121 PropertyNormalizationMode mode = map->is_prototype_map()
10122 ? KEEP_INOBJECT_PROPERTIES
10123 : CLEAR_INOBJECT_PROPERTIES;
10125 Map maybe_transition = TransitionsAccessor(isolate, map)
10126 .SearchTransition(*name, kAccessor, attributes);
10127 if (!maybe_transition.is_null()) {
10128 Handle<Map> transition(maybe_transition, isolate);
10129 DescriptorArray* descriptors = transition->instance_descriptors();
10130 int descriptor = transition->LastAdded();
10131 DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
10133 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
10134 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
10136 Handle<Object> maybe_pair(descriptors->GetStrongValue(descriptor), isolate);
10137 if (!maybe_pair->IsAccessorPair()) {
10138 return Map::Normalize(isolate, map, mode,
10139 "TransitionToAccessorFromNonPair");
10142 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
10143 if (!pair->Equals(*getter, *setter)) {
10144 return Map::Normalize(isolate, map, mode,
10145 "TransitionToDifferentAccessor");
10151 Handle<AccessorPair> pair;
10152 DescriptorArray* old_descriptors = map->instance_descriptors();
10153 if (descriptor != DescriptorArray::kNotFound) {
10154 if (descriptor != map->LastAdded()) {
10155 return Map::Normalize(isolate, map, mode,
"AccessorsOverwritingNonLast");
10157 PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
10158 if (old_details.kind() != kAccessor) {
10159 return Map::Normalize(isolate, map, mode,
10160 "AccessorsOverwritingNonAccessors");
10163 if (old_details.attributes() != attributes) {
10164 return Map::Normalize(isolate, map, mode,
"AccessorsWithAttributes");
10167 Handle<Object> maybe_pair(old_descriptors->GetStrongValue(descriptor),
10169 if (!maybe_pair->IsAccessorPair()) {
10170 return Map::Normalize(isolate, map, mode,
"AccessorsOverwritingNonPair");
10173 Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
10174 if (current_pair->Equals(*getter, *setter))
return map;
10176 bool overwriting_accessor =
false;
10177 if (!getter->IsNull(isolate) &&
10178 !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
10179 current_pair->get(ACCESSOR_GETTER) != *getter) {
10180 overwriting_accessor =
true;
10182 if (!setter->IsNull(isolate) &&
10183 !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
10184 current_pair->get(ACCESSOR_SETTER) != *setter) {
10185 overwriting_accessor =
true;
10187 if (overwriting_accessor) {
10188 return Map::Normalize(isolate, map, mode,
10189 "AccessorsOverwritingAccessors");
10192 pair = AccessorPair::Copy(isolate, Handle<AccessorPair>::cast(maybe_pair));
10193 }
else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
10194 map->TooManyFastProperties(StoreOrigin::kNamed)) {
10195 return Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES,
10196 "TooManyAccessors");
10198 pair = isolate->factory()->NewAccessorPair();
10201 pair->SetComponents(*getter, *setter);
10203 TransitionFlag flag = INSERT_TRANSITION;
10204 Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
10205 return Map::CopyInsertDescriptor(isolate, map, &d, flag);
10208 Handle<Map> Map::CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
10209 Descriptor* descriptor,
10210 TransitionFlag flag) {
10211 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
10214 if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
10215 !map->GetBackPointer()->IsUndefined(isolate) &&
10216 TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
10217 return ShareDescriptor(isolate, map, descriptors, descriptor);
10220 int nof = map->NumberOfOwnDescriptors();
10221 Handle<DescriptorArray> new_descriptors =
10222 DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
10223 new_descriptors->Append(descriptor);
10225 Handle<LayoutDescriptor> new_layout_descriptor =
10226 FLAG_unbox_double_fields
10227 ? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
10228 : handle(LayoutDescriptor::FastPointerLayout(), isolate);
10230 return CopyReplaceDescriptors(
10231 isolate, map, new_descriptors, new_layout_descriptor, flag,
10232 descriptor->GetKey(),
"CopyAddDescriptor", SIMPLE_PROPERTY_TRANSITION);
10235 Handle<Map> Map::CopyInsertDescriptor(Isolate* isolate, Handle<Map> map,
10236 Descriptor* descriptor,
10237 TransitionFlag flag) {
10238 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
10242 old_descriptors->SearchWithCache(isolate, *descriptor->GetKey(), *map);
10243 if (index != DescriptorArray::kNotFound) {
10244 return CopyReplaceDescriptor(isolate, map, old_descriptors, descriptor,
10247 return CopyAddDescriptor(isolate, map, descriptor, flag);
10250 Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
10251 Handle<DescriptorArray> desc,
10252 int enumeration_index,
10254 return DescriptorArray::CopyUpToAddAttributes(isolate, desc,
10255 enumeration_index, NONE, slack);
10258 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
10259 Isolate* isolate, Handle<DescriptorArray> desc,
int enumeration_index,
10260 PropertyAttributes attributes,
int slack) {
10261 if (enumeration_index + slack == 0) {
10262 return isolate->factory()->empty_descriptor_array();
10265 int size = enumeration_index;
10267 Handle<DescriptorArray> descriptors =
10268 DescriptorArray::Allocate(isolate, size, slack);
10270 if (attributes != NONE) {
10271 for (
int i = 0;
i < size; ++
i) {
10272 MaybeObject value_or_field_type = desc->GetValue(
i);
10273 Name key = desc->GetKey(
i);
10274 PropertyDetails details = desc->GetDetails(
i);
10276 if (!key->IsPrivate()) {
10277 int mask = DONT_DELETE | DONT_ENUM;
10279 HeapObject* heap_object;
10280 if (details.kind() != kAccessor ||
10281 !(value_or_field_type->GetHeapObjectIfStrong(&heap_object) &&
10282 heap_object->IsAccessorPair())) {
10285 details = details.CopyAddAttributes(
10286 static_cast<PropertyAttributes>(attributes & mask));
10288 descriptors->Set(
i, key, value_or_field_type, details);
10291 for (
int i = 0;
i < size; ++
i) {
10292 descriptors->CopyFrom(
i, *desc);
10296 if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
10298 return descriptors;
10303 Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
10304 Isolate* isolate, Handle<DescriptorArray> src,
int enumeration_index,
10306 if (enumeration_index + slack == 0) {
10307 return isolate->factory()->empty_descriptor_array();
10310 int size = enumeration_index;
10311 Handle<DescriptorArray> descriptors =
10312 DescriptorArray::Allocate(isolate, size, slack);
10314 for (
int i = 0;
i < size; ++
i) {
10315 Name key = src->GetKey(
i);
10316 PropertyDetails details = src->GetDetails(
i);
10318 DCHECK(!key->IsPrivateName());
10319 DCHECK(details.IsEnumerable());
10320 DCHECK_EQ(details.kind(), kData);
10324 PropertyDetails new_details(kData, NONE, details.location(),
10325 details.constness(), details.representation(),
10326 details.field_index());
10329 MaybeObject type = src->GetValue(
i);
10330 if (details.location() == PropertyLocation::kField) {
10331 type = MaybeObject::FromObject(FieldType::Any());
10333 descriptors->Set(
i, key, type, new_details);
10336 descriptors->Sort();
10338 return descriptors;
10341 bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc,
int nof_descriptors) {
10342 for (
int i = 0;
i < nof_descriptors;
i++) {
10343 if (GetKey(
i) != desc->GetKey(
i) || GetValue(
i) != desc->GetValue(
i)) {
10346 PropertyDetails details = GetDetails(
i);
10347 PropertyDetails other_details = desc->GetDetails(
i);
10348 if (details.kind() != other_details.kind() ||
10349 details.location() != other_details.location() ||
10350 !details.representation().Equals(other_details.representation())) {
10357 Handle<Map> Map::CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
10358 Handle<DescriptorArray> descriptors,
10359 Descriptor* descriptor,
10360 int insertion_index,
10361 TransitionFlag flag) {
10362 Handle<Name> key = descriptor->GetKey();
10363 DCHECK_EQ(*key, descriptors->GetKey(insertion_index));
10366 DCHECK_NE(kField, descriptor->GetDetails().location());
10367 DCHECK_NE(kField, descriptors->GetDetails(insertion_index).location());
10369 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
10370 isolate, descriptors, map->NumberOfOwnDescriptors());
10372 new_descriptors->Replace(insertion_index, descriptor);
10373 Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
10374 isolate, map, new_descriptors, new_descriptors->number_of_descriptors());
10376 SimpleTransitionFlag simple_flag =
10377 (insertion_index == descriptors->number_of_descriptors() - 1)
10378 ? SIMPLE_PROPERTY_TRANSITION
10379 : PROPERTY_TRANSITION;
10380 return CopyReplaceDescriptors(isolate, map, new_descriptors,
10381 new_layout_descriptor, flag, key,
10382 "CopyReplaceDescriptor", simple_flag);
10385 Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
10386 Handle<FixedArray> array,
int index,
10387 Handle<Object> value,
10388 PretenureFlag pretenure) {
10389 if (index < array->length()) {
10390 array->set(index, *value);
10393 int capacity = array->length();
10395 capacity = JSObject::NewElementsCapacity(capacity);
10396 }
while (capacity <= index);
10397 Handle<FixedArray> new_array =
10398 isolate->factory()->NewUninitializedFixedArray(capacity, pretenure);
10399 array->CopyTo(0, *new_array, 0, array->length());
10400 new_array->FillWithHoles(array->length(), new_array->length());
10401 new_array->set(index, *value);
10405 bool FixedArray::ContainsSortedNumbers() {
10406 for (
int i = 1;
i < length(); ++
i) {
10407 Object* a_obj =
get(
i - 1);
10408 Object* b_obj =
get(
i);
10409 if (!a_obj->IsNumber() || !b_obj->IsNumber())
return false;
10411 uint32_t a = NumberToUint32(a_obj);
10412 uint32_t b = NumberToUint32(b_obj);
10414 if (a > b)
return false;
10419 Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
10420 Handle<FixedArray> array,
10422 if (new_length == 0) {
10423 return array->GetReadOnlyRoots().empty_fixed_array_handle();
10425 array->Shrink(isolate, new_length);
10430 void FixedArray::Shrink(Isolate* isolate,
int new_length) {
10431 DCHECK(0 < new_length && new_length <= length());
10432 if (new_length < length()) {
10433 isolate->heap()->RightTrimFixedArray(*
this, length() - new_length);
10437 void FixedArray::CopyTo(
int pos, FixedArray dest,
int dest_pos,
int len)
const {
10438 DisallowHeapAllocation no_gc;
10441 if (len == 0)
return;
10442 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
10443 for (
int index = 0; index < len; index++) {
10444 dest->set(dest_pos + index,
get(pos + index), mode);
10448 void JSObject::PrototypeRegistryCompactionCallback(HeapObject* value,
10451 DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
10452 Map map = Map::cast(value);
10453 DCHECK(map->prototype_info()->IsPrototypeInfo());
10454 PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
10455 DCHECK_EQ(old_index, proto_info->registry_slot());
10456 proto_info->set_registry_slot(new_index);
10460 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
10461 Handle<Object> obj) {
10462 int length = array->Length();
10463 array = EnsureSpace(isolate, array, length + 1);
10465 DCHECK_EQ(array->Length(), length);
10466 array->Set(length, *obj);
10467 array->SetLength(length + 1);
10472 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
10473 Handle<Object> obj1, Handle<Object> obj2) {
10474 int length = array->Length();
10475 array = EnsureSpace(isolate, array, length + 2);
10477 DCHECK_EQ(array->Length(), length);
10478 array->Set(length, *obj1);
10479 array->Set(length + 1, *obj2);
10480 array->SetLength(length + 2);
10485 Handle<ArrayList> ArrayList::New(Isolate* isolate,
int size) {
10486 Handle<FixedArray> fixed_array =
10487 isolate->factory()->NewFixedArray(size + kFirstIndex);
10488 fixed_array->set_map_no_write_barrier(
10489 ReadOnlyRoots(isolate).array_list_map());
10490 Handle<ArrayList> result = Handle<ArrayList>::cast(fixed_array);
10491 result->SetLength(0);
10495 Handle<FixedArray> ArrayList::Elements(Isolate* isolate,
10496 Handle<ArrayList> array) {
10497 int length = array->Length();
10498 Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
10500 array->CopyTo(kFirstIndex, *result, 0, length);
10506 Handle<FixedArray> EnsureSpaceInFixedArray(Isolate* isolate,
10507 Handle<FixedArray> array,
10509 int capacity = array->length();
10510 if (capacity < length) {
10511 int new_capacity = length;
10512 new_capacity = new_capacity + Max(new_capacity / 2, 2);
10513 int grow_by = new_capacity - capacity;
10514 array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
10522 Handle<ArrayList> ArrayList::EnsureSpace(Isolate* isolate,
10523 Handle<ArrayList> array,
int length) {
10524 const bool empty = (array->length() == 0);
10525 Handle<FixedArray> ret =
10526 EnsureSpaceInFixedArray(isolate, array, kFirstIndex + length);
10528 ret->set_map_no_write_barrier(array->GetReadOnlyRoots().array_list_map());
10530 Handle<ArrayList>::cast(ret)->SetLength(0);
10532 return Handle<ArrayList>::cast(ret);
10536 Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
10537 Handle<WeakArrayList> array,
10538 const MaybeObjectHandle& value) {
10539 int length = array->length();
10540 array = EnsureSpace(isolate, array, length + 1);
10542 length = array->length();
10543 array->Set(length, *value);
10544 array->set_length(length + 1);
10548 bool WeakArrayList::IsFull() {
return length() == capacity(); }
10551 Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
10552 Handle<WeakArrayList> array,
10554 PretenureFlag pretenure) {
10555 int capacity = array->capacity();
10556 if (capacity < length) {
10557 int new_capacity = length;
10558 new_capacity = new_capacity + Max(new_capacity / 2, 2);
10559 int grow_by = new_capacity - capacity;
10561 isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by, pretenure);
10566 int WeakArrayList::CountLiveWeakReferences()
const {
10567 int live_weak_references = 0;
10568 for (
int i = 0;
i < length();
i++) {
10569 if (Get(
i)->IsWeak()) {
10570 ++live_weak_references;
10573 return live_weak_references;
10576 bool WeakArrayList::RemoveOne(
const MaybeObjectHandle& value) {
10577 if (length() == 0)
return false;
10579 MaybeObject cleared_weak_ref =
10580 HeapObjectReference::ClearedValue(GetIsolate());
10581 int last_index = length() - 1;
10582 for (
int i = last_index;
i >= 0; --
i) {
10583 if (Get(
i) == *value) {
10586 Set(
i, Get(last_index));
10587 Set(last_index, cleared_weak_ref);
10588 set_length(last_index);
10596 Handle<WeakArrayList> PrototypeUsers::Add(Isolate* isolate,
10597 Handle<WeakArrayList> array,
10599 int* assigned_index) {
10600 int length = array->length();
10603 array = WeakArrayList::EnsureSpace(isolate, array, kFirstIndex + 1);
10604 set_empty_slot_index(*array, kNoEmptySlotsMarker);
10605 array->Set(kFirstIndex, HeapObjectReference::Weak(*value));
10606 array->set_length(kFirstIndex + 1);
10607 if (assigned_index !=
nullptr) *assigned_index = kFirstIndex;
10612 if (!array->IsFull()) {
10613 array->Set(length, HeapObjectReference::Weak(*value));
10614 array->set_length(length + 1);
10615 if (assigned_index !=
nullptr) *assigned_index = length;
10620 int empty_slot = Smi::ToInt(empty_slot_index(*array));
10621 if (empty_slot != kNoEmptySlotsMarker) {
10622 DCHECK_GE(empty_slot, kFirstIndex);
10623 CHECK_LT(empty_slot, array->length());
10624 int next_empty_slot = array->Get(empty_slot).ToSmi().value();
10626 array->Set(empty_slot, HeapObjectReference::Weak(*value));
10627 if (assigned_index !=
nullptr) *assigned_index = empty_slot;
10629 set_empty_slot_index(*array, next_empty_slot);
10632 DCHECK_EQ(empty_slot, kNoEmptySlotsMarker);
10636 array = WeakArrayList::EnsureSpace(isolate, array, length + 1);
10637 array->Set(length, HeapObjectReference::Weak(*value));
10638 array->set_length(length + 1);
10639 if (assigned_index !=
nullptr) *assigned_index = length;
10643 WeakArrayList* PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
10644 CompactionCallback callback,
10645 PretenureFlag pretenure) {
10646 if (array->length() == 0) {
10649 int new_length = kFirstIndex + array->CountLiveWeakReferences();
10650 if (new_length == array->length()) {
10654 Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
10656 handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
10657 new_length, pretenure);
10660 int copy_to = kFirstIndex;
10661 for (
int i = kFirstIndex;
i < array->length();
i++) {
10662 MaybeObject element = array->Get(
i);
10664 if (element->GetHeapObjectIfWeak(&value)) {
10665 callback(value,
i, copy_to);
10666 new_array->Set(copy_to++, element);
10668 DCHECK(element->IsCleared() || element->IsSmi());
10671 new_array->set_length(copy_to);
10672 set_empty_slot_index(*new_array, kNoEmptySlotsMarker);
10676 Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
10677 Isolate* isolate, Handle<RegExpMatchInfo> match_info,
int capture_count) {
10678 DCHECK_GE(match_info->length(), kLastMatchOverhead);
10679 const int required_length = kFirstCaptureIndex + capture_count;
10680 return Handle<RegExpMatchInfo>::cast(
10681 EnsureSpaceInFixedArray(isolate, match_info, required_length));
10685 Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
10686 Handle<Object> receiver,
10687 Handle<JSFunction>
function,
10688 Handle<AbstractCode> code,
10689 int offset,
int flags) {
10690 const int frame_count = in->FrameCount();
10691 const int new_length = LengthFor(frame_count + 1);
10692 Handle<FrameArray> array =
10693 EnsureSpace(function->GetIsolate(), in, new_length);
10694 array->SetReceiver(frame_count, *receiver);
10695 array->SetFunction(frame_count, *
function);
10696 array->SetCode(frame_count, *code);
10697 array->SetOffset(frame_count, Smi::FromInt(offset));
10698 array->SetFlags(frame_count, Smi::FromInt(flags));
10699 array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
10704 Handle<FrameArray> FrameArray::AppendWasmFrame(
10705 Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
10706 int wasm_function_index, wasm::WasmCode* code,
int offset,
int flags) {
10707 Isolate* isolate = wasm_instance->GetIsolate();
10708 const int frame_count = in->FrameCount();
10709 const int new_length = LengthFor(frame_count + 1);
10710 Handle<FrameArray> array = EnsureSpace(isolate, in, new_length);
10712 Handle<Foreign> code_foreign =
10713 isolate->factory()->NewForeign(reinterpret_cast<Address>(code));
10714 array->SetWasmInstance(frame_count, *wasm_instance);
10715 array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
10716 array->SetWasmCodeObject(frame_count, *code_foreign);
10717 array->SetOffset(frame_count, Smi::FromInt(offset));
10718 array->SetFlags(frame_count, Smi::FromInt(flags));
10719 array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
10723 void FrameArray::ShrinkToFit(Isolate* isolate) {
10724 Shrink(isolate, LengthFor(FrameCount()));
10728 Handle<FrameArray> FrameArray::EnsureSpace(Isolate* isolate,
10729 Handle<FrameArray> array,
10731 return Handle<FrameArray>::cast(
10732 EnsureSpaceInFixedArray(isolate, array, length));
10735 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
10736 int nof_descriptors,
10738 return nof_descriptors + slack == 0
10739 ? isolate->factory()->empty_descriptor_array()
10740 : isolate->factory()->NewDescriptorArray(nof_descriptors, slack);
10743 void DescriptorArray::Initialize(EnumCache* enum_cache,
10744 HeapObject* undefined_value,
10745 int nof_descriptors,
int slack) {
10746 DCHECK_GE(nof_descriptors, 0);
10747 DCHECK_GE(slack, 0);
10748 DCHECK_LE(nof_descriptors + slack, kMaxNumberOfDescriptors);
10749 set_number_of_all_descriptors(nof_descriptors + slack);
10750 set_number_of_descriptors(nof_descriptors);
10751 set_number_of_marked_descriptors(0);
10752 set_filler16bits(0);
10753 set_enum_cache(enum_cache);
10754 MemsetPointer(GetDescriptorSlot(0), undefined_value,
10755 number_of_all_descriptors() * kEntrySize);
10758 void DescriptorArray::ClearEnumCache() {
10759 set_enum_cache(GetReadOnlyRoots().empty_enum_cache());
10762 void DescriptorArray::Replace(
int index, Descriptor* descriptor) {
10763 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
10764 Set(index, descriptor);
10768 void DescriptorArray::InitializeOrChangeEnumCache(
10769 Handle<DescriptorArray> descriptors, Isolate* isolate,
10770 Handle<FixedArray> keys, Handle<FixedArray> indices) {
10771 EnumCache* enum_cache = descriptors->enum_cache();
10772 if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
10773 enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
10774 descriptors->set_enum_cache(enum_cache);
10776 enum_cache->set_keys(*keys);
10777 enum_cache->set_indices(*indices);
10781 void DescriptorArray::CopyFrom(
int index, DescriptorArray* src) {
10782 PropertyDetails details = src->GetDetails(index);
10783 Set(index, src->GetKey(index), src->GetValue(index), details);
10786 void DescriptorArray::Sort() {
10788 int len = number_of_descriptors();
10790 for (
int i = 0;
i < len; ++
i) SetSortedKey(
i,
i);
10793 const int max_parent_index = (len / 2) - 1;
10794 for (
int i = max_parent_index;
i >= 0; --
i) {
10795 int parent_index =
i;
10796 const uint32_t parent_hash = GetSortedKey(
i)->Hash();
10797 while (parent_index <= max_parent_index) {
10798 int child_index = 2 * parent_index + 1;
10799 uint32_t child_hash = GetSortedKey(child_index)->Hash();
10800 if (child_index + 1 < len) {
10801 uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10802 if (right_child_hash > child_hash) {
10804 child_hash = right_child_hash;
10807 if (child_hash <= parent_hash)
break;
10808 SwapSortedKeys(parent_index, child_index);
10810 parent_index = child_index;
10815 for (
int i = len - 1;
i > 0; --
i) {
10817 SwapSortedKeys(0,
i);
10819 int parent_index = 0;
10820 const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
10821 const int max_parent_index = (
i / 2) - 1;
10822 while (parent_index <= max_parent_index) {
10823 int child_index = parent_index * 2 + 1;
10824 uint32_t child_hash = GetSortedKey(child_index)->Hash();
10825 if (child_index + 1 <
i) {
10826 uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10827 if (right_child_hash > child_hash) {
10829 child_hash = right_child_hash;
10832 if (child_hash <= parent_hash)
break;
10833 SwapSortedKeys(parent_index, child_index);
10834 parent_index = child_index;
10837 DCHECK(IsSortedNoDuplicates());
10840 Handle<AccessorPair> AccessorPair::Copy(Isolate* isolate,
10841 Handle<AccessorPair> pair) {
10842 Handle<AccessorPair> copy = isolate->factory()->NewAccessorPair();
10843 copy->set_getter(pair->getter());
10844 copy->set_setter(pair->setter());
10848 Handle<Object> AccessorPair::GetComponent(Isolate* isolate,
10849 Handle<AccessorPair> accessor_pair,
10850 AccessorComponent component) {
10851 Object* accessor = accessor_pair->get(component);
10852 if (accessor->IsFunctionTemplateInfo()) {
10853 return ApiNatives::InstantiateFunction(
10854 handle(FunctionTemplateInfo::cast(accessor), isolate))
10855 .ToHandleChecked();
10857 if (accessor->IsNull(isolate)) {
10858 return isolate->factory()->undefined_value();
10860 return handle(accessor, isolate);
10863 Handle<DeoptimizationData> DeoptimizationData::New(Isolate* isolate,
10864 int deopt_entry_count,
10865 PretenureFlag pretenure) {
10866 return Handle<DeoptimizationData>::cast(isolate->factory()->NewFixedArray(
10867 LengthFor(deopt_entry_count), pretenure));
10870 Handle<DeoptimizationData> DeoptimizationData::Empty(Isolate* isolate) {
10871 return Handle<DeoptimizationData>::cast(
10872 isolate->factory()->empty_fixed_array());
10875 SharedFunctionInfo* DeoptimizationData::GetInlinedFunction(
int index) {
10877 return SharedFunctionInfo::cast(SharedFunctionInfo());
10879 return SharedFunctionInfo::cast(LiteralArray()->
get(index));
10884 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
10885 if (number_of_all_descriptors() != other->number_of_all_descriptors())
10887 for (
int i = 0;
i < number_of_all_descriptors(); ++
i) {
10888 if (
get(
i) != other->get(
i))
return false;
10895 Handle<String> String::Trim(Isolate* isolate, Handle<String>
string,
10897 string = String::Flatten(isolate,
string);
10898 int const length =
string->length();
10902 if (mode == kTrim || mode == kTrimStart) {
10903 while (left < length && IsWhiteSpaceOrLineTerminator(string->Get(left))) {
10909 int right = length;
10910 if (mode == kTrim || mode == kTrimEnd) {
10911 while (right > left &&
10912 IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
10917 return isolate->factory()->NewSubString(
string, left, right);
10920 bool String::LooksValid() {
10923 MemoryChunk* chunk = MemoryChunk::FromHeapObject(*
this);
10925 if (chunk->owner()->identity() == RO_SPACE)
return true;
10926 if (chunk->heap() ==
nullptr)
return false;
10927 return chunk->heap()->Contains(*
this);
10931 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
10932 if (name->IsString())
return Handle<String>::cast(name);
10934 Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
10935 if (description->IsUndefined(isolate)) {
10936 return isolate->factory()->empty_string();
10938 IncrementalStringBuilder builder(isolate);
10939 builder.AppendCharacter(
'[');
10940 builder.AppendString(Handle<String>::cast(description));
10941 builder.AppendCharacter(
']');
10942 return builder.Finish();
10946 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name,
10947 Handle<String> prefix) {
10948 Handle<String> name_string;
10949 ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string,
10950 ToFunctionName(isolate, name), String);
10951 IncrementalStringBuilder builder(isolate);
10952 builder.AppendString(prefix);
10953 builder.AppendCharacter(
' ');
10954 builder.AppendString(name_string);
10955 return builder.Finish();
10960 bool AreDigits(
const uint8_t* s,
int from,
int to) {
10961 for (
int i = from;
i < to;
i++) {
10962 if (s[
i] <
'0' || s[
i] >
'9')
return false;
10969 int ParseDecimalInteger(
const uint8_t* s,
int from,
int to) {
10970 DCHECK_LT(to - from, 10);
10972 int d = s[from] -
'0';
10974 for (
int i = from + 1;
i < to;
i++) {
10975 d = 10 * d + (s[
i] -
'0');
10984 Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) {
10986 subject = String::Flatten(isolate, subject);
10990 if (subject->AsArrayIndex(&index)) {
10991 return isolate->factory()->NewNumberFromUint(index);
10995 if (subject->IsSeqOneByteString()) {
10996 int len = subject->length();
10997 if (len == 0)
return handle(Smi::kZero, isolate);
10999 DisallowHeapAllocation no_gc;
11000 uint8_t
const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
11001 bool minus = (data[0] ==
'-');
11002 int start_pos = (minus ? 1 : 0);
11004 if (start_pos == len) {
11005 return isolate->factory()->nan_value();
11006 }
else if (data[start_pos] >
'9') {
11011 if (data[start_pos] !=
'I' && data[start_pos] != 0xA0) {
11012 return isolate->factory()->nan_value();
11014 }
else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
11017 int d = ParseDecimalInteger(data, start_pos, len);
11019 if (d == 0)
return isolate->factory()->minus_zero_value();
11021 }
else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
11022 (len == 1 || data[0] !=
'0')) {
11025 uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
11028 DCHECK_EQ(static_cast<int>(subject->hash_field()),
11029 static_cast<int>(hash));
11031 subject->set_hash_field(hash);
11033 return handle(Smi::FromInt(d), isolate);
11038 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
11039 return isolate->factory()->NewNumber(StringToDouble(isolate, subject, flags));
11043 String::FlatContent String::GetFlatContent() {
11044 DCHECK(!AllowHeapAllocation::IsAllowed());
11045 int length = this->length();
11046 StringShape shape(*
this);
11047 String
string = *
this;
11049 if (shape.representation_tag() == kConsStringTag) {
11050 ConsString cons = ConsString::cast(
string);
11051 if (cons->second()->length() != 0) {
11052 return FlatContent();
11054 string = cons->first();
11055 shape = StringShape(
string);
11056 }
else if (shape.representation_tag() == kSlicedStringTag) {
11057 SlicedString slice = SlicedString::cast(
string);
11058 offset = slice->offset();
11059 string = slice->parent();
11060 shape = StringShape(
string);
11061 DCHECK(shape.representation_tag() != kConsStringTag &&
11062 shape.representation_tag() != kSlicedStringTag);
11064 if (shape.representation_tag() == kThinStringTag) {
11065 ThinString thin = ThinString::cast(
string);
11066 string = thin->actual();
11067 shape = StringShape(
string);
11068 DCHECK(!shape.IsCons());
11069 DCHECK(!shape.IsSliced());
11071 if (shape.encoding_tag() == kOneByteStringTag) {
11072 const uint8_t* start;
11073 if (shape.representation_tag() == kSeqStringTag) {
11074 start = SeqOneByteString::cast(
string)->GetChars();
11076 start = ExternalOneByteString::cast(
string)->GetChars();
11078 return FlatContent(start + offset, length);
11080 DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag);
11082 if (shape.representation_tag() == kSeqStringTag) {
11083 start = SeqTwoByteString::cast(
string)->GetChars();
11085 start = ExternalTwoByteString::cast(
string)->GetChars();
11087 return FlatContent(start + offset, length);
11091 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
11092 RobustnessFlag robust_flag,
11093 int offset,
int length,
11094 int* length_return) {
11095 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
11096 return std::unique_ptr<char[]>();
11099 if (length < 0) length = kMaxInt - offset;
11102 StringCharacterStream stream(*
this, offset);
11103 int character_position = offset;
11104 int utf8_bytes = 0;
11105 int last = unibrow::Utf16::kNoPreviousCharacter;
11106 while (stream.HasMore() && character_position++ < offset + length) {
11107 uint16_t character = stream.GetNext();
11108 utf8_bytes += unibrow::Utf8::Length(character, last);
11112 if (length_return) {
11113 *length_return = utf8_bytes;
11116 char* result = NewArray<char>(utf8_bytes + 1);
11119 stream.Reset(*
this, offset);
11120 character_position = offset;
11121 int utf8_byte_position = 0;
11122 last = unibrow::Utf16::kNoPreviousCharacter;
11123 while (stream.HasMore() && character_position++ < offset + length) {
11124 uint16_t character = stream.GetNext();
11125 if (allow_nulls == DISALLOW_NULLS && character == 0) {
11128 utf8_byte_position +=
11129 unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
11132 result[utf8_byte_position] = 0;
11133 return std::unique_ptr<char[]>(result);
11136 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
11137 RobustnessFlag robust_flag,
11138 int* length_return) {
11139 return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
11143 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
11144 Relocatable* current = isolate->relocatable_top();
11145 while (current !=
nullptr) {
11146 current->PostGarbageCollection();
11147 current = current->prev_;
11153 int Relocatable::ArchiveSpacePerThread() {
11154 return sizeof(Relocatable*);
11159 char* Relocatable::ArchiveState(Isolate* isolate,
char* to) {
11160 *
reinterpret_cast<Relocatable**
>(to) = isolate->relocatable_top();
11161 isolate->set_relocatable_top(
nullptr);
11162 return to + ArchiveSpacePerThread();
11167 char* Relocatable::RestoreState(Isolate* isolate,
char* from) {
11168 isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
11169 return from + ArchiveSpacePerThread();
11172 char* Relocatable::Iterate(RootVisitor* v,
char* thread_storage) {
11173 Relocatable* top = *
reinterpret_cast<Relocatable**
>(thread_storage);
11175 return thread_storage + ArchiveSpacePerThread();
11178 void Relocatable::Iterate(Isolate* isolate, RootVisitor* v) {
11179 Iterate(v, isolate->relocatable_top());
11182 void Relocatable::Iterate(RootVisitor* v, Relocatable* top) {
11183 Relocatable* current = top;
11184 while (current !=
nullptr) {
11185 current->IterateInstance(v);
11186 current = current->prev_;
11191 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
11192 : Relocatable(isolate),
11193 str_(str.location()),
11194 length_(str->length()) {
11195 PostGarbageCollection();
11198 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
11199 : Relocatable(isolate),
11201 is_one_byte_(true),
11202 length_(input.length()),
11203 start_(input.start()) {}
11205 void FlatStringReader::PostGarbageCollection() {
11206 if (str_ ==
nullptr)
return;
11207 Handle<String> str(str_);
11208 DCHECK(str->IsFlat());
11209 DisallowHeapAllocation no_gc;
11211 String::FlatContent content = str->GetFlatContent();
11212 DCHECK(content.IsFlat());
11213 is_one_byte_ = content.IsOneByte();
11214 if (is_one_byte_) {
11215 start_ = content.ToOneByteVector().start();
11217 start_ = content.ToUC16Vector().start();
11221 void ConsStringIterator::Initialize(ConsString cons_string,
int offset) {
11222 DCHECK(!cons_string.is_null());
11223 root_ = cons_string;
11224 consumed_ = offset;
11227 maximum_depth_ = kStackSize + depth_;
11228 DCHECK(StackBlown());
11231 String ConsStringIterator::Continue(
int* offset_out) {
11232 DCHECK_NE(depth_, 0);
11233 DCHECK_EQ(0, *offset_out);
11234 bool blew_stack = StackBlown();
11237 if (!blew_stack)
string = NextLeaf(&blew_stack);
11240 DCHECK(
string.is_null());
11241 string = Search(offset_out);
11244 if (
string.is_null()) Reset(ConsString());
11248 String ConsStringIterator::Search(
int* offset_out) {
11249 ConsString cons_string = root_;
11252 maximum_depth_ = 1;
11253 frames_[0] = cons_string;
11254 const int consumed = consumed_;
11258 String
string = cons_string->first();
11259 int length =
string->length();
11261 if (consumed < offset + length) {
11264 type =
string->map()->instance_type();
11265 if ((type & kStringRepresentationMask) == kConsStringTag) {
11266 cons_string = ConsString::cast(
string);
11267 PushLeft(cons_string);
11271 AdjustMaximumDepth();
11277 string = cons_string->second();
11278 type =
string->map()->instance_type();
11279 if ((type & kStringRepresentationMask) == kConsStringTag) {
11280 cons_string = ConsString::cast(
string);
11281 PushRight(cons_string);
11285 length =
string->length();
11290 Reset(ConsString());
11294 AdjustMaximumDepth();
11298 DCHECK_NE(length, 0);
11300 consumed_ = offset + length;
11301 *offset_out = consumed - offset;
11307 String ConsStringIterator::NextLeaf(
bool* blew_stack) {
11311 *blew_stack =
false;
11315 if (StackBlown()) {
11316 *blew_stack =
true;
11320 ConsString cons_string = frames_[OffsetForDepth(depth_ - 1)];
11321 String
string = cons_string->second();
11322 int32_t type =
string->map()->instance_type();
11323 if ((type & kStringRepresentationMask) != kConsStringTag) {
11326 int length =
string->length();
11328 if (length == 0)
continue;
11329 consumed_ += length;
11332 cons_string = ConsString::cast(
string);
11333 PushRight(cons_string);
11337 string = cons_string->first();
11338 type =
string->map()->instance_type();
11339 if ((type & kStringRepresentationMask) != kConsStringTag) {
11340 AdjustMaximumDepth();
11341 int length =
string->length();
11342 if (length == 0)
break;
11343 consumed_ += length;
11346 cons_string = ConsString::cast(
string);
11347 PushLeft(cons_string);
11353 uint16_t ConsString::ConsStringGet(
int index) {
11354 DCHECK(index >= 0 && index < this->length());
11357 if (second()->length() == 0) {
11358 String left = first();
11359 return left->Get(index);
11362 String
string = String::cast(*
this);
11365 if (StringShape(
string).IsCons()) {
11366 ConsString cons_string = ConsString::cast(
string);
11367 String left = cons_string->first();
11368 if (left->length() > index) {
11371 index -= left->length();
11372 string = cons_string->second();
11375 return string->Get(index);
11382 uint16_t ThinString::ThinStringGet(
int index) {
return actual()->Get(index); }
11384 uint16_t SlicedString::SlicedStringGet(
int index) {
11385 return parent()->Get(offset() + index);
11388 template <
typename sink
char>
11389 void String::WriteToFlat(String src, sinkchar* sink,
int f,
int t) {
11390 DisallowHeapAllocation no_gc;
11391 String source = src;
11395 DCHECK(0 <= from && from <= to && to <= source->length());
11396 switch (StringShape(source).full_representation_tag()) {
11397 case kOneByteStringTag | kExternalStringTag: {
11398 CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
11402 case kTwoByteStringTag | kExternalStringTag: {
11404 ExternalTwoByteString::cast(source)->GetChars();
11410 case kOneByteStringTag | kSeqStringTag: {
11412 SeqOneByteString::cast(source)->GetChars() + from,
11416 case kTwoByteStringTag | kSeqStringTag: {
11418 SeqTwoByteString::cast(source)->GetChars() + from,
11422 case kOneByteStringTag | kConsStringTag:
11423 case kTwoByteStringTag | kConsStringTag: {
11424 ConsString cons_string = ConsString::cast(source);
11425 String first = cons_string->first();
11426 int boundary = first->length();
11427 if (to - boundary >= boundary - from) {
11429 if (from < boundary) {
11430 WriteToFlat(first, sink, from, boundary);
11431 if (from == 0 && cons_string->second() == first) {
11432 CopyChars(sink + boundary, sink, boundary);
11435 sink += boundary - from;
11441 source = cons_string->second();
11444 if (to > boundary) {
11445 String second = cons_string->second();
11449 if (to - boundary == 1) {
11450 sink[boundary - from] =
static_cast<sinkchar
>(second->Get(0));
11451 }
else if (second->IsSeqOneByteString()) {
11452 CopyChars(sink + boundary - from,
11453 SeqOneByteString::cast(second)->GetChars(),
11456 WriteToFlat(second,
11457 sink + boundary - from,
11467 case kOneByteStringTag | kSlicedStringTag:
11468 case kTwoByteStringTag | kSlicedStringTag: {
11469 SlicedString slice = SlicedString::cast(source);
11470 unsigned offset = slice->offset();
11471 WriteToFlat(slice->parent(), sink, from + offset, to + offset);
11474 case kOneByteStringTag | kThinStringTag:
11475 case kTwoByteStringTag | kThinStringTag:
11476 source = ThinString::cast(source)->actual();
11482 template <
typename SourceChar>
11483 static void CalculateLineEndsImpl(Isolate* isolate, std::vector<int>* line_ends,
11484 Vector<const SourceChar> src,
11485 bool include_ending_line) {
11486 const int src_len = src.length();
11487 for (
int i = 0;
i < src_len - 1;
i++) {
11488 SourceChar current = src[
i];
11489 SourceChar next = src[
i + 1];
11490 if (IsLineTerminatorSequence(current, next)) line_ends->push_back(
i);
11493 if (src_len > 0 && IsLineTerminatorSequence(src[src_len - 1], 0)) {
11494 line_ends->push_back(src_len - 1);
11496 if (include_ending_line) {
11499 line_ends->push_back(src_len);
11503 Handle<FixedArray> String::CalculateLineEnds(Isolate* isolate,
11504 Handle<String> src,
11505 bool include_ending_line) {
11506 src = Flatten(isolate, src);
11509 int line_count_estimate = src->length() >> 4;
11510 std::vector<int> line_ends;
11511 line_ends.reserve(line_count_estimate);
11512 { DisallowHeapAllocation no_allocation;
11514 String::FlatContent content = src->GetFlatContent();
11515 DCHECK(content.IsFlat());
11516 if (content.IsOneByte()) {
11517 CalculateLineEndsImpl(isolate,
11519 content.ToOneByteVector(),
11520 include_ending_line);
11522 CalculateLineEndsImpl(isolate,
11524 content.ToUC16Vector(),
11525 include_ending_line);
11528 int line_count =
static_cast<int>(line_ends.size());
11529 Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
11530 for (
int i = 0;
i < line_count;
i++) {
11531 array->set(
i, Smi::FromInt(line_ends[
i]));
11538 template <
typename sink
char>
11539 void WriteFixedArrayToFlat(FixedArray fixed_array,
int length, String separator,
11540 sinkchar* sink,
int sink_length) {
11541 DisallowHeapAllocation no_allocation;
11542 CHECK_GT(length, 0);
11543 CHECK_LE(length, fixed_array->length());
11545 sinkchar* sink_end = sink + sink_length;
11548 const int separator_length = separator->length();
11549 const bool use_one_byte_separator_fast_path =
11550 separator_length == 1 &&
sizeof(sinkchar) == 1 &&
11551 StringShape(separator).IsSequentialOneByte();
11552 uint8_t separator_one_char;
11553 if (use_one_byte_separator_fast_path) {
11554 CHECK(StringShape(separator).IsSequentialOneByte());
11555 CHECK_EQ(separator->length(), 1);
11556 separator_one_char = SeqOneByteString::cast(separator)->GetChars()[0];
11560 for (
int i = 0;
i < length;
i++) {
11561 Object* element = fixed_array->get(
i);
11562 const bool element_is_separator_sequence = element->IsSmi();
11565 if (V8_UNLIKELY(element_is_separator_sequence)) {
11566 CHECK(element->ToUint32(&num_separators));
11573 DCHECK(
i == 0 ||
i == length - 1 || num_separators > 1);
11577 if (num_separators > 0 && separator_length > 0) {
11581 if (use_one_byte_separator_fast_path) {
11582 DCHECK_LE(sink + num_separators, sink_end);
11583 memset(sink, separator_one_char, num_separators);
11584 DCHECK_EQ(separator_length, 1);
11585 sink += num_separators;
11587 for (
uint32_t j = 0; j < num_separators; j++) {
11588 DCHECK_LE(sink + separator_length, sink_end);
11589 String::WriteToFlat(separator, sink, 0, separator_length);
11590 sink += separator_length;
11595 if (V8_UNLIKELY(element_is_separator_sequence)) {
11596 num_separators = 0;
11598 DCHECK(element->IsString());
11599 String
string = String::cast(element);
11600 const int string_length =
string->length();
11602 DCHECK(string_length == 0 || sink < sink_end);
11603 String::WriteToFlat(
string, sink, 0, string_length);
11604 sink += string_length;
11607 num_separators = 1;
11612 DCHECK_EQ(sink, sink_end);
11618 Address JSArray::ArrayJoinConcatToSequentialString(Isolate* isolate,
11619 Address raw_fixed_array,
11621 Address raw_separator,
11622 Address raw_dest) {
11623 DisallowHeapAllocation no_allocation;
11624 DisallowJavascriptExecution no_js(isolate);
11625 FixedArray fixed_array = FixedArray::cast(ObjectPtr(raw_fixed_array));
11626 String separator = String::cast(ObjectPtr(raw_separator));
11627 String dest = String::cast(ObjectPtr(raw_dest));
11628 DCHECK(fixed_array->IsFixedArray());
11629 DCHECK(StringShape(dest).IsSequentialOneByte() ||
11630 StringShape(dest).IsSequentialTwoByte());
11632 if (StringShape(dest).IsSequentialOneByte()) {
11633 WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
11634 SeqOneByteString::cast(dest)->GetChars(),
11637 DCHECK(StringShape(dest).IsSequentialTwoByte());
11638 WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
11639 SeqTwoByteString::cast(dest)->GetChars(),
11642 return dest->ptr();
11647 template <
typename Char>
11648 static inline bool CompareRawStringContents(
const Char*
const a,
11649 const Char*
const b,
11651 return CompareChars(a, b, length) == 0;
11655 template<
typename Chars1,
typename Chars2>
11658 static inline bool compare(
const Chars1* a,
const Chars2* b,
int len) {
11659 DCHECK(
sizeof(Chars1) !=
sizeof(Chars2));
11660 for (
int i = 0;
i < len;
i++) {
11661 if (a[
i] != b[
i]) {
11673 static inline bool compare(
const uint16_t* a,
const uint16_t* b,
int len) {
11674 return CompareRawStringContents(a, b, len);
11682 static inline bool compare(
const uint8_t* a,
const uint8_t* b,
int len) {
11683 return CompareRawStringContents(a, b, len);
11691 State() : is_one_byte_(
true), length_(0), buffer8_(
nullptr) {}
11693 void Init(
String string) {
11694 ConsString cons_string = String::VisitFlat(
this,
string);
11695 iter_.Reset(cons_string);
11696 if (!cons_string.is_null()) {
11698 string = iter_.Next(&offset);
11699 String::VisitFlat(
this,
string, offset);
11703 inline void VisitOneByteString(
const uint8_t* chars,
int length) {
11704 is_one_byte_ =
true;
11709 inline void VisitTwoByteString(
const uint16_t* chars,
int length) {
11710 is_one_byte_ =
false;
11715 void Advance(
int consumed) {
11716 DCHECK(consumed <= length_);
11718 if (length_ != consumed) {
11719 if (is_one_byte_) {
11720 buffer8_ += consumed;
11722 buffer16_ += consumed;
11724 length_ -= consumed;
11729 String next = iter_.Next(&offset);
11730 DCHECK_EQ(0, offset);
11731 DCHECK(!next.is_null());
11732 String::VisitFlat(
this, next);
11739 const uint8_t* buffer8_;
11740 const uint16_t* buffer16_;
11744 DISALLOW_COPY_AND_ASSIGN(State);
11750 template<
typename Chars1,
typename Chars2>
11751 static inline bool Equals(State* state_1, State* state_2,
int to_check) {
11752 const Chars1* a =
reinterpret_cast<const Chars1*
>(state_1->buffer8_);
11753 const Chars2* b =
reinterpret_cast<const Chars2*
>(state_2->buffer8_);
11758 int length = string_1->length();
11759 state_1_.Init(string_1);
11760 state_2_.Init(string_2);
11762 int to_check = Min(state_1_.length_, state_2_.length_);
11763 DCHECK(to_check > 0 && to_check <= length);
11765 if (state_1_.is_one_byte_) {
11766 if (state_2_.is_one_byte_) {
11767 is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
11769 is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
11772 if (state_2_.is_one_byte_) {
11773 is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
11775 is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
11779 if (!is_equal)
return false;
11780 length -= to_check;
11782 if (length == 0)
return true;
11783 state_1_.Advance(to_check);
11784 state_2_.Advance(to_check);
11795 bool String::SlowEquals(
String other) {
11798 int len = length();
11799 if (len != other->length())
return false;
11800 if (len == 0)
return true;
11804 if (this->IsThinString() || other->IsThinString()) {
11805 if (other->IsThinString()) other = ThinString::cast(other)->actual();
11806 if (this->IsThinString()) {
11807 return ThinString::cast(*this)->actual()->Equals(other);
11809 return this->Equals(other);
11815 if (HasHashCode() && other->HasHashCode()) {
11816 #ifdef ENABLE_SLOW_DCHECKS 11817 if (FLAG_enable_slow_asserts) {
11818 if (Hash() != other->Hash()) {
11819 bool found_difference =
false;
11820 for (
int i = 0;
i < len;
i++) {
11821 if (Get(
i) != other->Get(
i)) {
11822 found_difference =
true;
11826 DCHECK(found_difference);
11830 if (Hash() != other->Hash())
return false;
11835 if (this->Get(0) != other->Get(0))
return false;
11837 if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
11838 const uint8_t* str1 = SeqOneByteString::cast(*this)->GetChars();
11839 const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
11840 return CompareRawStringContents(str1, str2, len);
11843 StringComparator comparator;
11844 return comparator.Equals(*
this, other);
11847 bool String::SlowEquals(Isolate* isolate, Handle<String> one,
11848 Handle<String> two) {
11850 int one_length = one->length();
11851 if (one_length != two->length())
return false;
11852 if (one_length == 0)
return true;
11856 if (one->IsThinString() || two->IsThinString()) {
11857 if (one->IsThinString())
11858 one = handle(ThinString::cast(*one)->actual(), isolate);
11859 if (two->IsThinString())
11860 two = handle(ThinString::cast(*two)->actual(), isolate);
11861 return String::Equals(isolate, one, two);
11866 if (one->HasHashCode() && two->HasHashCode()) {
11867 #ifdef ENABLE_SLOW_DCHECKS 11868 if (FLAG_enable_slow_asserts) {
11869 if (one->Hash() != two->Hash()) {
11870 bool found_difference =
false;
11871 for (
int i = 0;
i < one_length;
i++) {
11872 if (one->Get(
i) != two->Get(
i)) {
11873 found_difference =
true;
11877 DCHECK(found_difference);
11881 if (one->Hash() != two->Hash())
return false;
11886 if (one->Get(0) != two->Get(0))
return false;
11888 one = String::Flatten(isolate, one);
11889 two = String::Flatten(isolate, two);
11891 DisallowHeapAllocation no_gc;
11892 String::FlatContent flat1 = one->GetFlatContent();
11893 String::FlatContent flat2 = two->GetFlatContent();
11895 if (flat1.IsOneByte() && flat2.IsOneByte()) {
11896 return CompareRawStringContents(flat1.ToOneByteVector().start(),
11897 flat2.ToOneByteVector().start(),
11900 for (
int i = 0;
i < one_length;
i++) {
11901 if (flat1.Get(
i) != flat2.Get(
i))
return false;
11909 ComparisonResult String::Compare(Isolate* isolate, Handle<String> x,
11910 Handle<String> y) {
11912 if (x.is_identical_to(y)) {
11913 return ComparisonResult::kEqual;
11914 }
else if (y->length() == 0) {
11915 return x->length() == 0 ? ComparisonResult::kEqual
11916 : ComparisonResult::kGreaterThan;
11917 }
else if (x->length() == 0) {
11918 return ComparisonResult::kLessThan;
11921 int const d = x->Get(0) - y->Get(0);
11923 return ComparisonResult::kLessThan;
11924 }
else if (d > 0) {
11925 return ComparisonResult::kGreaterThan;
11929 x = String::Flatten(isolate, x);
11930 y = String::Flatten(isolate, y);
11932 DisallowHeapAllocation no_gc;
11933 ComparisonResult result = ComparisonResult::kEqual;
11934 int prefix_length = x->length();
11935 if (y->length() < prefix_length) {
11936 prefix_length = y->length();
11937 result = ComparisonResult::kGreaterThan;
11938 }
else if (y->length() > prefix_length) {
11939 result = ComparisonResult::kLessThan;
11942 String::FlatContent x_content = x->GetFlatContent();
11943 String::FlatContent y_content = y->GetFlatContent();
11944 if (x_content.IsOneByte()) {
11945 Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
11946 if (y_content.IsOneByte()) {
11947 Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11948 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11950 Vector<const uc16> y_chars = y_content.ToUC16Vector();
11951 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11954 Vector<const uc16> x_chars = x_content.ToUC16Vector();
11955 if (y_content.IsOneByte()) {
11956 Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11957 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11959 Vector<const uc16> y_chars = y_content.ToUC16Vector();
11960 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11964 result = ComparisonResult::kLessThan;
11965 }
else if (r > 0) {
11966 result = ComparisonResult::kGreaterThan;
11971 Object* String::IndexOf(Isolate* isolate, Handle<Object> receiver,
11972 Handle<Object> search, Handle<Object> position) {
11973 if (receiver->IsNullOrUndefined(isolate)) {
11974 THROW_NEW_ERROR_RETURN_FAILURE(
11975 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
11976 isolate->factory()->NewStringFromAsciiChecked(
11977 "String.prototype.indexOf")));
11979 Handle<String> receiver_string;
11980 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
11981 Object::ToString(isolate, receiver));
11983 Handle<String> search_string;
11984 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
11985 Object::ToString(isolate, search));
11987 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
11988 Object::ToInteger(isolate, position));
11990 uint32_t index = receiver_string->ToValidIndex(*position);
11991 return Smi::FromInt(
11992 String::IndexOf(isolate, receiver_string, search_string, index));
11997 template <
typename T>
11998 int SearchString(Isolate* isolate, String::FlatContent receiver_content,
11999 Vector<T> pat_vector,
int start_index) {
12000 if (receiver_content.IsOneByte()) {
12001 return SearchString(isolate, receiver_content.ToOneByteVector(), pat_vector,
12004 return SearchString(isolate, receiver_content.ToUC16Vector(), pat_vector,
12010 int String::IndexOf(Isolate* isolate, Handle<String> receiver,
12011 Handle<String> search,
int start_index) {
12012 DCHECK_LE(0, start_index);
12013 DCHECK(start_index <= receiver->length());
12015 uint32_t search_length = search->length();
12016 if (search_length == 0)
return start_index;
12018 uint32_t receiver_length = receiver->length();
12019 if (start_index + search_length > receiver_length)
return -1;
12021 receiver = String::Flatten(isolate, receiver);
12022 search = String::Flatten(isolate, search);
12024 DisallowHeapAllocation no_gc;
12026 String::FlatContent receiver_content = receiver->GetFlatContent();
12027 String::FlatContent search_content = search->GetFlatContent();
12030 if (search_content.IsOneByte()) {
12031 Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
12032 return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
12035 Vector<const uc16> pat_vector = search_content.ToUC16Vector();
12036 return SearchString<const uc16>(isolate, receiver_content, pat_vector,
12040 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
12041 Handle<String> replacement,
12043 DCHECK_GE(start_index, 0);
12045 Factory* factory = isolate->factory();
12047 const int replacement_length = replacement->length();
12048 const int captures_length = match->CaptureCount();
12050 replacement = String::Flatten(isolate, replacement);
12052 Handle<String> dollar_string =
12053 factory->LookupSingleCharacterStringFromCode(
'$');
12054 int next_dollar_ix =
12055 String::IndexOf(isolate, replacement, dollar_string, start_index);
12056 if (next_dollar_ix < 0) {
12057 return replacement;
12060 IncrementalStringBuilder builder(isolate);
12062 if (next_dollar_ix > 0) {
12063 builder.AppendString(factory->NewSubString(replacement, 0, next_dollar_ix));
12067 const int peek_ix = next_dollar_ix + 1;
12068 if (peek_ix >= replacement_length) {
12069 builder.AppendCharacter(
'$');
12070 return builder.Finish();
12073 int continue_from_ix = -1;
12074 const uint16_t peek = replacement->Get(peek_ix);
12077 builder.AppendCharacter(
'$');
12078 continue_from_ix = peek_ix + 1;
12081 builder.AppendString(match->GetMatch());
12082 continue_from_ix = peek_ix + 1;
12085 builder.AppendString(match->GetPrefix());
12086 continue_from_ix = peek_ix + 1;
12089 builder.AppendString(match->GetSuffix());
12090 continue_from_ix = peek_ix + 1;
12103 int scaled_index = (peek -
'0');
12106 if (peek_ix + 1 < replacement_length) {
12107 const uint16_t next_peek = replacement->Get(peek_ix + 1);
12108 if (next_peek >=
'0' && next_peek <=
'9') {
12109 const int new_scaled_index = scaled_index * 10 + (next_peek -
'0');
12110 if (new_scaled_index < captures_length) {
12111 scaled_index = new_scaled_index;
12117 if (scaled_index == 0 || scaled_index >= captures_length) {
12118 builder.AppendCharacter(
'$');
12119 continue_from_ix = peek_ix;
12123 bool capture_exists;
12124 Handle<String> capture;
12125 ASSIGN_RETURN_ON_EXCEPTION(
12126 isolate, capture, match->GetCapture(scaled_index, &capture_exists),
12128 if (capture_exists) builder.AppendString(capture);
12129 continue_from_ix = peek_ix + advance;
12133 typedef String::Match::CaptureState CaptureState;
12135 if (!match->HasNamedCaptures()) {
12136 builder.AppendCharacter(
'$');
12137 continue_from_ix = peek_ix;
12141 Handle<String> bracket_string =
12142 factory->LookupSingleCharacterStringFromCode(
'>');
12143 const int closing_bracket_ix =
12144 String::IndexOf(isolate, replacement, bracket_string, peek_ix + 1);
12146 if (closing_bracket_ix == -1) {
12148 builder.AppendCharacter(
'$');
12149 continue_from_ix = peek_ix;
12153 Handle<String> capture_name =
12154 factory->NewSubString(replacement, peek_ix + 1, closing_bracket_ix);
12155 Handle<String> capture;
12156 CaptureState capture_state;
12157 ASSIGN_RETURN_ON_EXCEPTION(
12159 match->GetNamedCapture(capture_name, &capture_state), String);
12161 switch (capture_state) {
12162 case CaptureState::INVALID:
12163 case CaptureState::UNMATCHED:
12165 case CaptureState::MATCHED:
12166 builder.AppendString(capture);
12170 continue_from_ix = closing_bracket_ix + 1;
12174 builder.AppendCharacter(
'$');
12175 continue_from_ix = peek_ix;
12181 DCHECK_NE(continue_from_ix, -1);
12183 String::IndexOf(isolate, replacement, dollar_string, continue_from_ix);
12187 if (next_dollar_ix < 0) {
12188 if (continue_from_ix < replacement_length) {
12189 builder.AppendString(factory->NewSubString(
12190 replacement, continue_from_ix, replacement_length));
12192 return builder.Finish();
12196 if (next_dollar_ix > continue_from_ix) {
12197 builder.AppendString(
12198 factory->NewSubString(replacement, continue_from_ix, next_dollar_ix));
12207 template <
typename s
char,
typename p
char>
12208 int StringMatchBackwards(Vector<const schar> subject,
12209 Vector<const pchar> pattern,
int idx) {
12210 int pattern_length = pattern.length();
12211 DCHECK_GE(pattern_length, 1);
12212 DCHECK(idx + pattern_length <= subject.length());
12214 if (
sizeof(schar) == 1 &&
sizeof(pchar) > 1) {
12215 for (
int i = 0;
i < pattern_length;
i++) {
12216 uc16 c = pattern[
i];
12217 if (c > String::kMaxOneByteCharCode) {
12223 pchar pattern_first_char = pattern[0];
12224 for (
int i = idx;
i >= 0;
i--) {
12225 if (subject[
i] != pattern_first_char)
continue;
12227 while (j < pattern_length) {
12228 if (pattern[j] != subject[
i + j]) {
12233 if (j == pattern_length) {
12242 Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
12243 Handle<Object> search, Handle<Object> position) {
12244 if (receiver->IsNullOrUndefined(isolate)) {
12245 THROW_NEW_ERROR_RETURN_FAILURE(
12246 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
12247 isolate->factory()->NewStringFromAsciiChecked(
12248 "String.prototype.lastIndexOf")));
12250 Handle<String> receiver_string;
12251 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
12252 Object::ToString(isolate, receiver));
12254 Handle<String> search_string;
12255 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
12256 Object::ToString(isolate, search));
12258 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
12259 Object::ToNumber(isolate, position));
12263 if (position->IsNaN()) {
12264 start_index = receiver_string->length();
12266 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
12267 Object::ToInteger(isolate, position));
12268 start_index = receiver_string->ToValidIndex(*position);
12271 uint32_t pattern_length = search_string->length();
12272 uint32_t receiver_length = receiver_string->length();
12274 if (start_index + pattern_length > receiver_length) {
12275 start_index = receiver_length - pattern_length;
12278 if (pattern_length == 0) {
12279 return Smi::FromInt(start_index);
12282 receiver_string = String::Flatten(isolate, receiver_string);
12283 search_string = String::Flatten(isolate, search_string);
12285 int last_index = -1;
12286 DisallowHeapAllocation no_gc;
12288 String::FlatContent receiver_content = receiver_string->GetFlatContent();
12289 String::FlatContent search_content = search_string->GetFlatContent();
12291 if (search_content.IsOneByte()) {
12292 Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
12293 if (receiver_content.IsOneByte()) {
12294 last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
12295 pat_vector, start_index);
12297 last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
12298 pat_vector, start_index);
12301 Vector<const uc16> pat_vector = search_content.ToUC16Vector();
12302 if (receiver_content.IsOneByte()) {
12303 last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
12304 pat_vector, start_index);
12306 last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
12307 pat_vector, start_index);
12310 return Smi::FromInt(last_index);
12313 bool String::IsUtf8EqualTo(Vector<const char> str,
bool allow_prefix_match) {
12314 int slen = length();
12316 int str_len = str.length();
12317 if (!allow_prefix_match &&
12319 str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
12325 while (
i < slen && !it.Done()) {
12326 if (Get(
i++) != *it)
return false;
12330 return (allow_prefix_match ||
i == slen) && it.Done();
12334 bool String::IsEqualTo(Vector<const uint8_t> str) {
12335 return IsOneByteEqualTo(str);
12339 bool String::IsEqualTo(Vector<const uc16> str) {
12340 return IsTwoByteEqualTo(str);
12343 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
12344 int slen = length();
12345 if (str.length() != slen)
return false;
12346 DisallowHeapAllocation no_gc;
12347 FlatContent content = GetFlatContent();
12348 if (content.IsOneByte()) {
12349 return CompareChars(content.ToOneByteVector().start(),
12350 str.start(), slen) == 0;
12352 return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
12356 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
12357 int slen = length();
12358 if (str.length() != slen)
return false;
12359 DisallowHeapAllocation no_gc;
12360 FlatContent content = GetFlatContent();
12361 if (content.IsOneByte()) {
12362 return CompareChars(content.ToOneByteVector().start(), str.start(), slen) ==
12365 return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
12368 uint32_t String::ComputeAndSetHash(Isolate* isolate) {
12369 DisallowHeapAllocation no_gc;
12371 DCHECK(!HasHashCode());
12375 IteratingStringHasher::Hash(*
this, isolate->heap()->HashSeed());
12376 set_hash_field(field);
12379 DCHECK(HasHashCode());
12380 uint32_t result = field >> kHashShift;
12381 DCHECK_NE(result, 0);
12386 bool String::ComputeArrayIndex(
uint32_t* index) {
12387 int length = this->length();
12388 if (length == 0 || length > kMaxArrayIndexSize)
return false;
12389 StringCharacterStream stream(*
this);
12390 return StringToArrayIndex(&stream, index);
12394 bool String::SlowAsArrayIndex(
uint32_t* index) {
12395 DisallowHeapAllocation no_gc;
12396 if (length() <= kMaxCachedArrayIndexLength) {
12399 if ((field & kIsNotArrayIndexMask) != 0)
return false;
12401 *index = ArrayIndexValueBits::decode(field);
12404 return ComputeArrayIndex(index);
12409 Handle<String> SeqString::Truncate(Handle<SeqString>
string,
int new_length) {
12410 if (new_length == 0)
return string->GetReadOnlyRoots().empty_string_handle();
12412 int new_size, old_size;
12413 int old_length =
string->length();
12414 if (old_length <= new_length)
return string;
12416 if (string->IsSeqOneByteString()) {
12417 old_size = SeqOneByteString::SizeFor(old_length);
12418 new_size = SeqOneByteString::SizeFor(new_length);
12420 DCHECK(string->IsSeqTwoByteString());
12421 old_size = SeqTwoByteString::SizeFor(old_length);
12422 new_size = SeqTwoByteString::SizeFor(new_length);
12425 int delta = old_size - new_size;
12427 Address start_of_string =
string->address();
12428 DCHECK_OBJECT_ALIGNED(start_of_string);
12429 DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
12431 Heap* heap = Heap::FromWritableHeapObject(*
string);
12434 heap->CreateFillerObjectAt(start_of_string + new_size, delta,
12435 ClearRecordedSlots::kNo);
12438 string->synchronized_set_length(new_length);
12443 void SeqOneByteString::clear_padding() {
12444 int data_size = SeqString::kHeaderSize + length() * kOneByteSize;
12445 memset(reinterpret_cast<void*>(address() + data_size), 0,
12446 SizeFor(length()) - data_size);
12449 void SeqTwoByteString::clear_padding() {
12450 int data_size = SeqString::kHeaderSize + length() * kUC16Size;
12451 memset(reinterpret_cast<void*>(address() + data_size), 0,
12452 SizeFor(length()) - data_size);
12455 int ExternalString::ExternalPayloadSize()
const {
12456 int length_multiplier = IsTwoByteRepresentation() ? i::kShortSize : kCharSize;
12457 return length() * length_multiplier;
12463 DCHECK_GT(length, 0);
12464 DCHECK_LE(length, String::kMaxArrayIndexSize);
12465 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
12466 (1 << String::kArrayIndexValueBits));
12468 value <<= String::ArrayIndexValueBits::kShift;
12469 value |= length << String::ArrayIndexLengthBits::kShift;
12471 DCHECK_EQ(value & String::kIsNotArrayIndexMask, 0);
12472 DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
12473 Name::ContainsCachedArrayIndex(value));
12478 uint32_t StringHasher::GetHashField() {
12479 if (length_ <= String::kMaxHashCalcLength) {
12480 if (is_array_index_) {
12481 return MakeArrayIndexHash(array_index_, length_);
12483 return (GetHashCore(raw_running_hash_) << String::kHashShift) |
12484 String::kIsNotArrayIndexMask;
12486 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
12490 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
12491 int* utf16_length_out) {
12492 int vector_length = chars.length();
12494 if (vector_length <= 1) {
12495 DCHECK(vector_length == 0 ||
12496 static_cast<uint8_t>(chars.start()[0]) <=
12497 unibrow::Utf8::kMaxOneByteChar);
12498 *utf16_length_out = vector_length;
12499 return HashSequentialString(chars.start(), vector_length, seed);
12504 StringHasher hasher(String::kMaxArrayIndexSize, seed);
12505 DCHECK(hasher.is_array_index_);
12508 int utf16_length = 0;
12509 bool is_index =
true;
12511 while (utf16_length < String::kMaxHashCalcLength && !it.Done()) {
12515 hasher.AddCharacter(c);
12516 if (is_index) is_index = hasher.UpdateIndex(c);
12520 while (!it.Done()) {
12525 *utf16_length_out = utf16_length;
12527 hasher.length_ = utf16_length;
12528 return hasher.GetHashField();
12531 void IteratingStringHasher::VisitConsString(ConsString cons_string) {
12533 if (cons_string->length() < 64) {
12534 ConsStringIterator iter(cons_string);
12536 for (String
string = iter.Next(&offset); !
string.is_null();
12537 string = iter.Next(&offset)) {
12538 DCHECK_EQ(0, offset);
12539 String::VisitFlat(
this,
string, 0);
12544 const int max_length = String::kMaxHashCalcLength;
12545 int length = std::min(cons_string->length(), max_length);
12546 if (cons_string->HasOnlyOneByteChars()) {
12547 uint8_t* buffer =
new uint8_t[length];
12548 String::WriteToFlat(cons_string, buffer, 0, length);
12549 AddCharacters(buffer, length);
12552 uint16_t* buffer =
new uint16_t[length];
12553 String::WriteToFlat(cons_string, buffer, 0, length);
12554 AddCharacters(buffer, length);
12559 void String::PrintOn(FILE* file) {
12560 int length = this->length();
12561 for (
int i = 0;
i < length;
i++) {
12562 PrintF(file,
"%c", Get(
i));
12574 int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
12579 hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
12581 return hash ^ (hash >> 16) ^ bit_field2();
12587 bool CheckEquivalent(
const Map first,
const Map second) {
12588 return first->GetConstructor() == second->GetConstructor() &&
12589 first->prototype() == second->prototype() &&
12590 first->instance_type() == second->instance_type() &&
12591 first->bit_field() == second->bit_field() &&
12592 first->is_extensible() == second->is_extensible() &&
12593 first->new_target_is_base() == second->new_target_is_base() &&
12594 first->has_hidden_prototype() == second->has_hidden_prototype();
12599 bool Map::EquivalentToForTransition(
const Map other)
const {
12600 if (!CheckEquivalent(*
this, other))
return false;
12601 if (instance_type() == JS_FUNCTION_TYPE) {
12604 int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
12605 return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
12611 bool Map::EquivalentToForElementsKindTransition(
const Map other)
const {
12612 if (!EquivalentToForTransition(other))
return false;
12617 DescriptorArray* descriptors = instance_descriptors();
12618 int nof = NumberOfOwnDescriptors();
12619 for (
int i = 0;
i < nof;
i++) {
12620 PropertyDetails details = descriptors->GetDetails(
i);
12621 if (details.location() == kField) {
12622 DCHECK(!IsInplaceGeneralizableField(details.constness(),
12623 details.representation(),
12624 descriptors->GetFieldType(
i)));
12631 bool Map::EquivalentToForNormalization(
const Map other,
12632 PropertyNormalizationMode mode)
const {
12634 mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
12635 return CheckEquivalent(*
this, other) && bit_field2() == other->bit_field2() &&
12636 GetInObjectProperties() == properties &&
12637 JSObject::GetEmbedderFieldCount(*
this) ==
12638 JSObject::GetEmbedderFieldCount(other);
12642 void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
12643 Isolate* isolate = GetIsolate();
12644 if (!isolate->concurrent_recompilation_enabled() ||
12645 isolate->bootstrapper()->IsActive()) {
12646 mode = ConcurrencyMode::kNotConcurrent;
12649 DCHECK(!is_compiled() || IsInterpreted());
12650 DCHECK(shared()->IsInterpreted());
12651 DCHECK(!IsOptimized());
12652 DCHECK(!HasOptimizedCode());
12653 DCHECK(shared()->allows_lazy_compilation() ||
12654 !shared()->optimization_disabled());
12656 if (mode == ConcurrencyMode::kConcurrent) {
12657 if (IsInOptimizationQueue()) {
12658 if (FLAG_trace_concurrent_recompilation) {
12659 PrintF(
" ** Not marking ");
12661 PrintF(
" -- already in optimization queue.\n");
12665 if (FLAG_trace_concurrent_recompilation) {
12666 PrintF(
" ** Marking ");
12668 PrintF(
" for concurrent recompilation.\n");
12672 SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
12673 ? OptimizationMarker::kCompileOptimizedConcurrent
12674 : OptimizationMarker::kCompileOptimized);
12678 void JSFunction::EnsureFeedbackVector(Handle<JSFunction>
function) {
12679 Isolate*
const isolate =
function->GetIsolate();
12680 if (function->feedback_cell()->value()->IsUndefined(isolate)) {
12681 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
12682 if (!shared->HasAsmWasmData()) {
12683 Handle<FeedbackVector> feedback_vector =
12684 FeedbackVector::New(isolate, shared);
12685 if (function->feedback_cell() == isolate->heap()->many_closures_cell()) {
12686 Handle<FeedbackCell> feedback_cell =
12687 isolate->factory()->NewOneClosureCell(feedback_vector);
12688 function->set_feedback_cell(*feedback_cell);
12690 function->feedback_cell()->set_value(*feedback_vector);
12696 static void GetMinInobjectSlack(Map map,
void* data) {
12697 int slack = map->UnusedPropertyFields();
12698 if (*reinterpret_cast<int*>(data) > slack) {
12699 *
reinterpret_cast<int*
>(data) = slack;
12703 int Map::InstanceSizeFromSlack(
int slack)
const {
12704 return instance_size() - slack * kPointerSize;
12707 static void ShrinkInstanceSize(Map map,
void* data) {
12708 int slack = *
reinterpret_cast<int*
>(data);
12709 DCHECK_GE(slack, 0);
12711 int old_visitor_id = Map::GetVisitorId(map);
12712 int new_unused = map->UnusedPropertyFields() - slack;
12714 map->set_instance_size(map->InstanceSizeFromSlack(slack));
12715 map->set_construction_counter(Map::kNoSlackTracking);
12716 DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
12717 DCHECK_EQ(new_unused, map->UnusedPropertyFields());
12720 static void StopSlackTracking(Map map,
void* data) {
12721 map->set_construction_counter(Map::kNoSlackTracking);
12724 int Map::ComputeMinObjectSlack(Isolate* isolate) {
12725 DisallowHeapAllocation no_gc;
12727 DCHECK(GetBackPointer()->IsUndefined(isolate));
12729 int slack = UnusedPropertyFields();
12730 TransitionsAccessor transitions(isolate, *
this, &no_gc);
12731 transitions.TraverseTransitionTree(&GetMinInobjectSlack, &slack);
12735 void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
12736 DisallowHeapAllocation no_gc;
12738 DCHECK(GetBackPointer()->IsUndefined(isolate));
12740 int slack = ComputeMinObjectSlack(isolate);
12741 TransitionsAccessor transitions(isolate, *
this, &no_gc);
12744 transitions.TraverseTransitionTree(&ShrinkInstanceSize, &slack);
12746 transitions.TraverseTransitionTree(&StopSlackTracking,
nullptr);
12751 static bool PrototypeBenefitsFromNormalization(Handle<JSObject>
object) {
12752 DisallowHeapAllocation no_gc;
12753 if (!object->HasFastProperties())
return false;
12754 if (object->IsJSGlobalProxy())
return false;
12755 if (object->GetIsolate()->bootstrapper()->IsActive())
return false;
12756 return !
object->map()->is_prototype_map() ||
12757 !
object->map()->should_be_fast_prototype_map();
12761 void JSObject::MakePrototypesFast(Handle<Object> receiver,
12762 WhereToStart where_to_start,
12763 Isolate* isolate) {
12764 if (!receiver->IsJSReceiver())
return;
12765 for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
12767 !iter.IsAtEnd(); iter.Advance()) {
12768 Handle<Object> current = PrototypeIterator::GetCurrent(iter);
12769 if (!current->IsJSObject())
return;
12770 Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
12771 Map current_map = current_obj->map();
12772 if (current_map->is_prototype_map()) {
12775 if (current_map->should_be_fast_prototype_map())
return;
12776 Handle<Map> map(current_map, isolate);
12777 Map::SetShouldBeFastPrototypeMap(map,
true, isolate);
12778 JSObject::OptimizeAsPrototype(current_obj);
12784 void JSObject::OptimizeAsPrototype(Handle<JSObject>
object,
12785 bool enable_setup_mode) {
12786 if (object->IsJSGlobalObject())
return;
12787 if (enable_setup_mode && PrototypeBenefitsFromNormalization(
object)) {
12789 JSObject::NormalizeProperties(
object, KEEP_INOBJECT_PROPERTIES, 0,
12790 "NormalizeAsPrototype");
12792 if (object->map()->is_prototype_map()) {
12793 if (object->map()->should_be_fast_prototype_map() &&
12794 !
object->HasFastProperties()) {
12795 JSObject::MigrateSlowToFast(
object, 0,
"OptimizeAsPrototype");
12798 Handle<Map> new_map = Map::Copy(object->GetIsolate(),
12799 handle(object->map(),
object->GetIsolate()),
12800 "CopyAsPrototype");
12801 JSObject::MigrateToMap(
object, new_map);
12802 object->map()->set_is_prototype_map(
true);
12807 Object* maybe_constructor =
object->map()->GetConstructor();
12808 if (maybe_constructor->IsJSFunction()) {
12809 JSFunction* constructor = JSFunction::cast(maybe_constructor);
12810 if (!constructor->shared()->IsApiFunction()) {
12811 Context context = constructor->context()->native_context();
12812 JSFunction* object_function = context->object_function();
12813 object->map()->SetConstructor(object_function);
12821 void JSObject::ReoptimizeIfPrototype(Handle<JSObject>
object) {
12822 if (!object->map()->is_prototype_map())
return;
12823 if (!object->map()->should_be_fast_prototype_map())
return;
12824 OptimizeAsPrototype(
object);
12829 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12832 DCHECK(user->is_prototype_map());
12834 Handle<Map> current_user = user;
12835 Handle<PrototypeInfo> current_user_info =
12836 Map::GetOrCreatePrototypeInfo(user, isolate);
12837 for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) {
12839 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
12842 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
12845 if (maybe_proto->IsJSProxy())
return;
12846 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
12847 Handle<PrototypeInfo> proto_info =
12848 Map::GetOrCreatePrototypeInfo(proto, isolate);
12849 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
12850 Handle<WeakArrayList> registry =
12851 maybe_registry->IsSmi()
12852 ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
12854 : Handle<WeakArrayList>::cast(maybe_registry);
12856 Handle<WeakArrayList> new_array =
12857 PrototypeUsers::Add(isolate, registry, current_user, &slot);
12858 current_user_info->set_registry_slot(slot);
12859 if (!maybe_registry.is_identical_to(new_array)) {
12860 proto_info->set_prototype_users(*new_array);
12862 if (FLAG_trace_prototype_users) {
12863 PrintF(
"Registering %p as a user of prototype %p (map=%p).\n",
12864 reinterpret_cast<void*>(current_user->ptr()),
12865 reinterpret_cast<void*>(*proto),
12866 reinterpret_cast<void*
>(proto->map()->ptr()));
12869 current_user = handle(proto->map(), isolate);
12870 current_user_info = proto_info;
12878 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12879 DCHECK(user->is_prototype_map());
12881 if (!user->prototype_info()->IsPrototypeInfo())
return false;
12884 if (!user->prototype()->IsJSObject()) {
12886 PrototypeInfo::cast(user->prototype_info())->prototype_users();
12887 return users->IsWeakArrayList();
12889 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
12890 Handle<PrototypeInfo> user_info =
12891 Map::GetOrCreatePrototypeInfo(user, isolate);
12892 int slot = user_info->registry_slot();
12893 if (slot == PrototypeInfo::UNREGISTERED)
return false;
12894 DCHECK(prototype->map()->is_prototype_map());
12895 Object* maybe_proto_info = prototype->map()->prototype_info();
12897 DCHECK(maybe_proto_info->IsPrototypeInfo());
12898 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
12900 Handle<WeakArrayList> prototype_users(
12901 WeakArrayList::cast(proto_info->prototype_users()), isolate);
12902 DCHECK_EQ(prototype_users->Get(slot), HeapObjectReference::Weak(*user));
12903 PrototypeUsers::MarkSlotEmpty(*prototype_users, slot);
12904 if (FLAG_trace_prototype_users) {
12905 PrintF(
"Unregistering %p as a user of prototype %p.\n",
12906 reinterpret_cast<void*>(user->ptr()),
12907 reinterpret_cast<void*>(*prototype));
12917 void InvalidateOnePrototypeValidityCellInternal(Map map) {
12918 DCHECK(map->is_prototype_map());
12919 if (FLAG_trace_prototype_users) {
12920 PrintF(
"Invalidating prototype map %p 's cell\n",
12921 reinterpret_cast<void*>(map.ptr()));
12923 Object* maybe_cell = map->prototype_validity_cell();
12924 if (maybe_cell->IsCell()) {
12926 Cell* cell = Cell::cast(maybe_cell);
12927 cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
12931 void InvalidatePrototypeChainsInternal(Map map) {
12932 InvalidateOnePrototypeValidityCellInternal(map);
12934 Object* maybe_proto_info = map->prototype_info();
12935 if (!maybe_proto_info->IsPrototypeInfo())
return;
12936 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
12937 if (!proto_info->prototype_users()->IsWeakArrayList()) {
12940 WeakArrayList* prototype_users =
12941 WeakArrayList::cast(proto_info->prototype_users());
12943 for (
int i = PrototypeUsers::kFirstIndex;
i < prototype_users->length();
12945 HeapObject* heap_object;
12946 if (prototype_users->Get(
i)->GetHeapObjectIfWeak(&heap_object) &&
12947 heap_object->IsMap()) {
12950 InvalidatePrototypeChainsInternal(Map::cast(heap_object));
12958 Map JSObject::InvalidatePrototypeChains(Map map) {
12959 DisallowHeapAllocation no_gc;
12960 InvalidatePrototypeChainsInternal(map);
12972 void JSObject::InvalidatePrototypeValidityCell(JSGlobalObject* global) {
12973 DisallowHeapAllocation no_gc;
12974 InvalidateOnePrototypeValidityCellInternal(global->map());
12978 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
12979 Isolate* isolate) {
12980 Object* maybe_proto_info = prototype->map()->prototype_info();
12981 if (maybe_proto_info->IsPrototypeInfo()) {
12982 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12984 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12985 prototype->map()->set_prototype_info(*proto_info);
12991 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
12992 Isolate* isolate) {
12993 Object* maybe_proto_info = prototype_map->prototype_info();
12994 if (maybe_proto_info->IsPrototypeInfo()) {
12995 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12997 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12998 prototype_map->set_prototype_info(*proto_info);
13003 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map,
bool value,
13004 Isolate* isolate) {
13005 if (value ==
false && !map->prototype_info()->IsPrototypeInfo()) {
13009 GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
13013 Handle<Object> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
13014 Isolate* isolate) {
13015 Handle<Object> maybe_prototype;
13016 if (map->IsJSGlobalObjectMap()) {
13017 DCHECK(map->is_prototype_map());
13020 maybe_prototype = isolate->global_object();
13023 handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
13025 if (!maybe_prototype->IsJSObject()) {
13026 return handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
13028 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
13031 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
13034 Object* maybe_cell = prototype->map()->prototype_validity_cell();
13036 if (maybe_cell->IsCell()) {
13037 Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
13038 if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
13043 Handle<Cell> cell = isolate->factory()->NewCell(
13044 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
13045 prototype->map()->set_prototype_validity_cell(*cell);
13050 bool Map::IsPrototypeChainInvalidated(Map map) {
13051 DCHECK(map->is_prototype_map());
13052 Object* maybe_cell = map->prototype_validity_cell();
13053 if (maybe_cell->IsCell()) {
13054 Cell* cell = Cell::cast(maybe_cell);
13055 return cell->value() != Smi::FromInt(Map::kPrototypeChainValid);
13061 void Map::SetPrototype(Isolate* isolate, Handle<Map> map,
13062 Handle<Object> prototype,
13063 bool enable_prototype_setup_mode) {
13064 RuntimeCallTimerScope stats_scope(isolate, *map,
13065 RuntimeCallCounterId::kMap_SetPrototype);
13067 bool is_hidden =
false;
13068 if (prototype->IsJSObject()) {
13069 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
13070 JSObject::OptimizeAsPrototype(prototype_jsobj, enable_prototype_setup_mode);
13072 Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
13073 if (maybe_constructor->IsJSFunction()) {
13074 JSFunction* constructor = JSFunction::cast(maybe_constructor);
13075 Object* data = constructor->shared()->function_data();
13076 is_hidden = (data->IsFunctionTemplateInfo() &&
13077 FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
13078 prototype->IsJSGlobalObject();
13079 }
else if (maybe_constructor->IsFunctionTemplateInfo()) {
13081 FunctionTemplateInfo::cast(maybe_constructor)->hidden_prototype() ||
13082 prototype->IsJSGlobalObject();
13085 map->set_has_hidden_prototype(is_hidden);
13087 WriteBarrierMode wb_mode =
13088 prototype->IsNull(isolate) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
13089 map->set_prototype(*prototype, wb_mode);
13092 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
13093 Handle<Map> initial_map) {
13096 Handle<Map> current_map = initial_map;
13097 ElementsKind kind = current_map->elements_kind();
13098 DCHECK_EQ(GetInitialFastElementsKind(), kind);
13099 native_context->set(Context::ArrayMapIndex(kind), *current_map);
13100 for (
int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
13101 i < kFastElementsKindCount; ++
i) {
13102 Handle<Map> new_map;
13103 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(
i);
13104 Map maybe_elements_transition = current_map->ElementsTransitionMap();
13105 if (!maybe_elements_transition.is_null()) {
13106 new_map = handle(maybe_elements_transition, native_context->GetIsolate());
13109 Map::CopyAsElementsKind(native_context->GetIsolate(), current_map,
13110 next_kind, INSERT_TRANSITION);
13112 DCHECK_EQ(next_kind, new_map->elements_kind());
13113 native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
13114 current_map = new_map;
13116 return initial_map;
13121 void SetInstancePrototype(Isolate* isolate, Handle<JSFunction>
function,
13122 Handle<JSReceiver> value) {
13125 if (function->has_initial_map()) {
13130 function->CompleteInobjectSlackTrackingIfActive();
13132 Handle<Map> initial_map(function->initial_map(), isolate);
13134 if (!isolate->bootstrapper()->IsActive() &&
13135 initial_map->instance_type() == JS_OBJECT_TYPE) {
13139 function->set_prototype_or_initial_map(*value);
13141 Handle<Map> new_map =
13142 Map::Copy(isolate, initial_map,
"SetInstancePrototype");
13143 JSFunction::SetInitialMap(
function, new_map, value);
13147 Handle<Context> native_context(function->context()->native_context(),
13149 Handle<Object> array_function(
13150 native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
13151 if (array_function->IsJSFunction() &&
13152 *
function == JSFunction::cast(*array_function)) {
13153 CacheInitialJSArrayMaps(native_context, new_map);
13158 initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
13159 isolate, DependentCode::kInitialMapChangedGroup);
13164 function->set_prototype_or_initial_map(*value);
13165 if (value->IsJSObject()) {
13167 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
13174 void JSFunction::SetPrototype(Handle<JSFunction>
function,
13175 Handle<Object> value) {
13176 DCHECK(function->IsConstructor() ||
13177 IsGeneratorFunction(function->shared()->kind()));
13178 Isolate* isolate =
function->GetIsolate();
13179 Handle<JSReceiver> construct_prototype;
13185 if (!value->IsJSReceiver()) {
13189 Handle<Map> new_map =
13190 Map::Copy(isolate, handle(function->map(), isolate),
"SetPrototype");
13192 JSObject::MigrateToMap(
function, new_map);
13193 new_map->SetConstructor(*value);
13194 new_map->set_has_non_instance_prototype(
true);
13196 FunctionKind kind =
function->shared()->kind();
13197 Handle<Context> native_context(function->context()->native_context(),
13200 construct_prototype = Handle<JSReceiver>(
13201 IsGeneratorFunction(kind)
13202 ? IsAsyncFunction(kind)
13203 ? native_context->initial_async_generator_prototype()
13204 : native_context->initial_generator_prototype()
13205 : native_context->initial_object_prototype(),
13208 construct_prototype = Handle<JSReceiver>::cast(value);
13209 function->map()->set_has_non_instance_prototype(
false);
13212 SetInstancePrototype(isolate,
function, construct_prototype);
13215 void JSFunction::SetInitialMap(Handle<JSFunction>
function, Handle<Map> map,
13216 Handle<Object> prototype) {
13217 if (map->prototype() != *prototype)
13218 Map::SetPrototype(function->GetIsolate(), map, prototype);
13219 function->set_prototype_or_initial_map(*map);
13220 map->SetConstructor(*
function);
13221 if (FLAG_trace_maps) {
13222 LOG(function->GetIsolate(), MapEvent(
"InitialMap", Map(), *map,
"",
13223 function->shared()->DebugName()));
13231 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
13232 switch (instance_type) {
13233 case JS_API_OBJECT_TYPE:
13234 case JS_ARRAY_BUFFER_TYPE:
13235 case JS_ARRAY_TYPE:
13236 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
13237 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
13238 case JS_DATA_VIEW_TYPE:
13240 case JS_FUNCTION_TYPE:
13241 case JS_GENERATOR_OBJECT_TYPE:
13242 #ifdef V8_INTL_SUPPORT 13243 case JS_INTL_COLLATOR_TYPE:
13244 case JS_INTL_DATE_TIME_FORMAT_TYPE:
13245 case JS_INTL_LIST_FORMAT_TYPE:
13246 case JS_INTL_LOCALE_TYPE:
13247 case JS_INTL_NUMBER_FORMAT_TYPE:
13248 case JS_INTL_PLURAL_RULES_TYPE:
13249 case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
13250 case JS_INTL_SEGMENT_ITERATOR_TYPE:
13251 case JS_INTL_SEGMENTER_TYPE:
13252 case JS_INTL_V8_BREAK_ITERATOR_TYPE:
13254 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
13255 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
13257 case JS_MESSAGE_OBJECT_TYPE:
13258 case JS_OBJECT_TYPE:
13259 case JS_ERROR_TYPE:
13260 case JS_ARGUMENTS_TYPE:
13261 case JS_PROMISE_TYPE:
13262 case JS_REGEXP_TYPE:
13264 case JS_SPECIAL_API_OBJECT_TYPE:
13265 case JS_TYPED_ARRAY_TYPE:
13266 case JS_VALUE_TYPE:
13267 case JS_WEAK_MAP_TYPE:
13268 case JS_WEAK_SET_TYPE:
13269 case WASM_GLOBAL_TYPE:
13270 case WASM_INSTANCE_TYPE:
13271 case WASM_MEMORY_TYPE:
13272 case WASM_MODULE_TYPE:
13273 case WASM_TABLE_TYPE:
13277 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
13278 case BYTECODE_ARRAY_TYPE:
13279 case BYTE_ARRAY_TYPE:
13283 case FIXED_ARRAY_TYPE:
13284 case SCRIPT_CONTEXT_TABLE_TYPE:
13285 case FIXED_DOUBLE_ARRAY_TYPE:
13286 case FEEDBACK_METADATA_TYPE:
13288 case FREE_SPACE_TYPE:
13289 case HASH_TABLE_TYPE:
13290 case ORDERED_HASH_MAP_TYPE:
13291 case ORDERED_HASH_SET_TYPE:
13292 case ORDERED_NAME_DICTIONARY_TYPE:
13293 case NAME_DICTIONARY_TYPE:
13294 case GLOBAL_DICTIONARY_TYPE:
13295 case NUMBER_DICTIONARY_TYPE:
13296 case SIMPLE_NUMBER_DICTIONARY_TYPE:
13297 case STRING_TABLE_TYPE:
13298 case HEAP_NUMBER_TYPE:
13299 case JS_BOUND_FUNCTION_TYPE:
13300 case JS_GLOBAL_OBJECT_TYPE:
13301 case JS_GLOBAL_PROXY_TYPE:
13302 case JS_PROXY_TYPE:
13304 case MUTABLE_HEAP_NUMBER_TYPE:
13306 case PROPERTY_CELL_TYPE:
13307 case SHARED_FUNCTION_INFO_TYPE:
13309 case ALLOCATION_SITE_TYPE:
13311 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 13312 case FIXED_##TYPE##_ARRAY_TYPE: 13313 #undef TYPED_ARRAY_CASE 13315 #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE: 13316 STRUCT_LIST(MAKE_STRUCT_CASE)
13317 #undef MAKE_STRUCT_CASE 13330 void JSFunction::EnsureHasInitialMap(Handle<JSFunction>
function) {
13331 DCHECK(function->has_prototype_slot());
13332 DCHECK(function->IsConstructor() ||
13333 IsResumableFunction(function->shared()->kind()));
13334 if (function->has_initial_map())
return;
13335 Isolate* isolate =
function->GetIsolate();
13339 InstanceType instance_type;
13340 if (IsResumableFunction(function->shared()->kind())) {
13341 instance_type = IsAsyncGeneratorFunction(function->shared()->kind())
13342 ? JS_ASYNC_GENERATOR_OBJECT_TYPE
13343 : JS_GENERATOR_OBJECT_TYPE;
13345 instance_type = JS_OBJECT_TYPE;
13350 int expected_nof_properties = 0;
13351 if (function->shared()->is_compiled() ||
13352 Compiler::Compile(
function, Compiler::CLEAR_EXCEPTION)) {
13353 DCHECK(function->shared()->is_compiled());
13354 expected_nof_properties =
function->shared()->expected_nof_properties();
13358 int inobject_properties;
13359 CalculateInstanceSizeHelper(instance_type,
false, 0, expected_nof_properties,
13360 &instance_size, &inobject_properties);
13362 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size,
13363 TERMINAL_FAST_ELEMENTS_KIND,
13364 inobject_properties);
13367 Handle<Object> prototype;
13368 if (function->has_instance_prototype()) {
13369 prototype = handle(function->instance_prototype(), isolate);
13371 prototype = isolate->factory()->NewFunctionPrototype(
function);
13373 DCHECK(map->has_fast_object_elements());
13376 DCHECK(prototype->IsJSReceiver());
13377 JSFunction::SetInitialMap(
function, map, prototype);
13378 map->StartInobjectSlackTracking();
13382 bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
13383 Handle<JSFunction> constructor,
13384 Handle<Map> constructor_initial_map) {
13386 if (!new_target->has_prototype_slot())
return false;
13389 if (new_target->has_initial_map() &&
13390 new_target->initial_map()->GetConstructor() == *constructor) {
13391 DCHECK(new_target->instance_prototype()->IsJSReceiver());
13394 InstanceType instance_type = constructor_initial_map->instance_type();
13395 DCHECK(CanSubclassHaveInobjectProperties(instance_type));
13401 if (!IsDerivedConstructor(new_target->shared()->kind()))
return false;
13404 int in_object_properties;
13405 int embedder_fields =
13406 JSObject::GetEmbedderFieldCount(*constructor_initial_map);
13407 bool success = JSFunction::CalculateInstanceSizeForDerivedClass(
13408 new_target, instance_type, embedder_fields, &instance_size,
13409 &in_object_properties);
13413 int pre_allocated = constructor_initial_map->GetInObjectProperties() -
13414 constructor_initial_map->UnusedPropertyFields();
13415 CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size);
13416 int unused_property_fields = in_object_properties - pre_allocated;
13417 map = Map::CopyInitialMap(isolate, constructor_initial_map, instance_size,
13418 in_object_properties, unused_property_fields);
13420 map = Map::CopyInitialMap(isolate, constructor_initial_map);
13422 map->set_new_target_is_base(
false);
13423 Handle<Object> prototype(new_target->instance_prototype(), isolate);
13424 JSFunction::SetInitialMap(new_target, map, prototype);
13425 DCHECK(new_target->instance_prototype()->IsJSReceiver());
13426 map->SetConstructor(*constructor);
13427 map->set_construction_counter(Map::kNoSlackTracking);
13428 map->StartInobjectSlackTracking();
13435 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
13436 Handle<JSFunction> constructor,
13437 Handle<JSReceiver> new_target) {
13438 EnsureHasInitialMap(constructor);
13440 Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
13441 if (*new_target == *constructor)
return constructor_initial_map;
13443 Handle<Map> result_map;
13447 if (new_target->IsJSFunction()) {
13448 Handle<JSFunction>
function = Handle<JSFunction>::cast(new_target);
13449 if (FastInitializeDerivedMap(isolate,
function, constructor,
13450 constructor_initial_map)) {
13451 return handle(function->initial_map(), isolate);
13458 Handle<Object> prototype;
13459 if (new_target->IsJSFunction()) {
13460 Handle<JSFunction>
function = Handle<JSFunction>::cast(new_target);
13461 if (function->has_prototype_slot()) {
13463 EnsureHasInitialMap(
function);
13464 prototype = handle(function->prototype(), isolate);
13467 prototype = isolate->factory()->undefined_value();
13470 Handle<String> prototype_string = isolate->factory()->prototype_string();
13471 ASSIGN_RETURN_ON_EXCEPTION(
13472 isolate, prototype,
13473 JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);
13476 EnsureHasInitialMap(constructor);
13477 constructor_initial_map = handle(constructor->initial_map(), isolate);
13484 if (!prototype->IsJSReceiver()) {
13485 Handle<Context> context;
13486 ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
13487 JSReceiver::GetFunctionRealm(new_target), Map);
13488 DCHECK(context->IsNativeContext());
13489 Handle<Object> maybe_index = JSReceiver::GetDataProperty(
13490 constructor, isolate->factory()->native_context_index_symbol());
13491 int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index)
13492 : Context::OBJECT_FUNCTION_INDEX;
13493 Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)),
13495 prototype = handle(realm_constructor->prototype(), isolate);
13498 Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map);
13499 map->set_new_target_is_base(
false);
13500 CHECK(prototype->IsJSReceiver());
13501 if (map->prototype() != *prototype)
13502 Map::SetPrototype(isolate, map, prototype);
13503 map->SetConstructor(*constructor);
13507 int JSFunction::ComputeInstanceSizeWithMinSlack(Isolate* isolate) {
13508 CHECK(has_initial_map());
13509 if (initial_map()->IsInobjectSlackTrackingInProgress()) {
13510 int slack = initial_map()->ComputeMinObjectSlack(isolate);
13511 return initial_map()->InstanceSizeFromSlack(slack);
13513 return initial_map()->instance_size();
13516 void JSFunction::PrintName(FILE* out) {
13517 std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
13518 PrintF(out,
"%s", name.get());
13522 Handle<String> JSFunction::GetName(Handle<JSFunction>
function) {
13523 Isolate* isolate =
function->GetIsolate();
13524 Handle<Object> name =
13525 JSReceiver::GetDataProperty(
function, isolate->factory()->name_string());
13526 if (name->IsString())
return Handle<String>::cast(name);
13527 return handle(function->shared()->DebugName(), isolate);
13531 Handle<String> JSFunction::GetDebugName(Handle<JSFunction>
function) {
13532 Isolate* isolate =
function->GetIsolate();
13533 Handle<Object> name = JSReceiver::GetDataProperty(
13534 function, isolate->factory()->display_name_string());
13535 if (name->IsString())
return Handle<String>::cast(name);
13536 return JSFunction::GetName(
function);
13539 bool JSFunction::SetName(Handle<JSFunction>
function, Handle<Name> name,
13540 Handle<String> prefix) {
13541 Isolate* isolate =
function->GetIsolate();
13542 Handle<String> function_name;
13543 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name,
13544 Name::ToFunctionName(isolate, name),
false);
13545 if (prefix->length() > 0) {
13546 IncrementalStringBuilder builder(isolate);
13547 builder.AppendString(prefix);
13548 builder.AppendCharacter(
' ');
13549 builder.AppendString(function_name);
13550 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name, builder.Finish(),
13553 RETURN_ON_EXCEPTION_VALUE(
13555 JSObject::DefinePropertyOrElementIgnoreAttributes(
13556 function, isolate->factory()->name_string(), function_name,
13557 static_cast<PropertyAttributes
>(DONT_ENUM | READ_ONLY)),
13564 Handle<String> NativeCodeFunctionSourceString(
13565 Handle<SharedFunctionInfo> shared_info) {
13566 Isolate*
const isolate = shared_info->GetIsolate();
13567 IncrementalStringBuilder builder(isolate);
13568 builder.AppendCString(
"function ");
13569 builder.AppendString(handle(shared_info->Name(), isolate));
13570 builder.AppendCString(
"() { [native code] }");
13571 return builder.Finish().ToHandleChecked();
13578 Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction>
function) {
13579 Isolate*
const isolate =
function->GetIsolate();
13580 return isolate->factory()->function_native_code_string();
13585 Handle<String> JSFunction::ToString(Handle<JSFunction>
function) {
13586 Isolate*
const isolate =
function->GetIsolate();
13587 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
13590 if (!shared_info->IsUserJavaScript()) {
13591 return NativeCodeFunctionSourceString(shared_info);
13595 Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
13596 function, isolate->factory()->class_positions_symbol());
13597 if (maybe_class_positions->IsTuple2()) {
13598 Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
13599 int start_position = Smi::ToInt(class_positions->value1());
13600 int end_position = Smi::ToInt(class_positions->value2());
13601 Handle<String> script_source(
13602 String::cast(Script::cast(shared_info->script())->source()), isolate);
13603 return isolate->factory()->NewSubString(script_source, start_position,
13608 if (!shared_info->HasSourceCode()) {
13609 return NativeCodeFunctionSourceString(shared_info);
13612 if (shared_info->function_token_position() == kNoSourcePosition) {
13616 isolate->CountUsage(
13617 v8::Isolate::UseCounterFeature::kFunctionTokenOffsetTooLongForToString);
13618 return NativeCodeFunctionSourceString(shared_info);
13620 return Handle<String>::cast(
13621 SharedFunctionInfo::GetSourceCodeHarmony(shared_info));
13624 void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
13625 const char* to_string, Handle<Object> to_number,
13626 const char* type_of, byte kind) {
13627 Handle<String> internalized_to_string =
13628 isolate->factory()->InternalizeUtf8String(to_string);
13629 Handle<String> internalized_type_of =
13630 isolate->factory()->InternalizeUtf8String(type_of);
13631 if (to_number->IsHeapNumber()) {
13632 oddball->set_to_number_raw_as_bits(
13633 Handle<HeapNumber>::cast(to_number)->value_as_bits());
13635 oddball->set_to_number_raw(to_number->Number());
13637 oddball->set_to_number(*to_number);
13638 oddball->set_to_string(*internalized_to_string);
13639 oddball->set_type_of(*internalized_type_of);
13640 oddball->set_kind(kind);
13643 int Script::GetEvalPosition() {
13644 DisallowHeapAllocation no_gc;
13645 DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
13646 int position = eval_from_position();
13647 if (position < 0) {
13651 if (!has_eval_from_shared()) {
13654 SharedFunctionInfo* shared = eval_from_shared();
13655 position = shared->abstract_code()->SourcePosition(-position);
13657 DCHECK_GE(position, 0);
13658 set_eval_from_position(position);
13663 void Script::InitLineEnds(Handle<Script> script) {
13664 Isolate* isolate = script->GetIsolate();
13665 if (!script->line_ends()->IsUndefined(isolate))
return;
13666 DCHECK(script->type() != Script::TYPE_WASM ||
13667 script->source_mapping_url()->IsString());
13669 Object* src_obj = script->source();
13670 if (!src_obj->IsString()) {
13671 DCHECK(src_obj->IsUndefined(isolate));
13672 script->set_line_ends(ReadOnlyRoots(isolate).empty_fixed_array());
13674 DCHECK(src_obj->IsString());
13675 Handle<String> src(String::cast(src_obj), isolate);
13676 Handle<FixedArray> array = String::CalculateLineEnds(isolate, src,
true);
13677 script->set_line_ends(*array);
13680 DCHECK(script->line_ends()->IsFixedArray());
13683 bool Script::GetPositionInfo(Handle<Script> script,
int position,
13684 PositionInfo* info, OffsetFlag offset_flag) {
13687 if (script->type() != Script::TYPE_WASM) InitLineEnds(script);
13688 return script->GetPositionInfo(position, info, offset_flag);
13691 bool Script::IsUserJavaScript() {
return type() == Script::TYPE_NORMAL; }
13693 bool Script::ContainsAsmModule() {
13694 DisallowHeapAllocation no_gc;
13695 SharedFunctionInfo::ScriptIterator iter(this->GetIsolate(),
this);
13696 while (SharedFunctionInfo* info = iter.Next()) {
13697 if (info->HasAsmWasmData())
return true;
13703 bool GetPositionInfoSlow(
const Script* script,
int position,
13704 Script::PositionInfo* info) {
13705 if (!script->source()->IsString())
return false;
13706 if (position < 0) position = 0;
13708 String source_string = String::cast(script->source());
13710 int line_start = 0;
13711 int len = source_string->length();
13712 for (
int pos = 0; pos <= len; ++pos) {
13713 if (pos == len || source_string->Get(pos) ==
'\n') {
13714 if (position <= pos) {
13716 info->column = position - line_start;
13717 info->line_start = line_start;
13718 info->line_end = pos;
13722 line_start = pos + 1;
13729 #define SMI_VALUE(x) (Smi::ToInt(x)) 13730 bool Script::GetPositionInfo(
int position, PositionInfo* info,
13731 OffsetFlag offset_flag)
const {
13732 DisallowHeapAllocation no_allocation;
13736 if (type() == Script::TYPE_WASM) {
13737 DCHECK_LE(0, position);
13738 return WasmModuleObject::cast(wasm_module_object())
13739 ->GetPositionInfo(static_cast<uint32_t>(position), info);
13742 if (line_ends()->IsUndefined()) {
13744 if (!GetPositionInfoSlow(
this, position, info))
return false;
13746 DCHECK(line_ends()->IsFixedArray());
13747 FixedArray ends = FixedArray::cast(line_ends());
13749 const int ends_len = ends->length();
13750 if (ends_len == 0)
return false;
13754 if (position < 0) {
13756 }
else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
13761 if (SMI_VALUE(ends->get(0)) >= position) {
13763 info->line_start = 0;
13764 info->column = position;
13767 int right = ends_len - 1;
13769 while (right > 0) {
13770 DCHECK_LE(left, right);
13771 const int mid = (left + right) / 2;
13772 if (position > SMI_VALUE(ends->get(mid))) {
13774 }
else if (position <= SMI_VALUE(ends->get(mid - 1))) {
13781 DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
13782 SMI_VALUE(ends->get(info->line - 1)) < position);
13783 info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
13784 info->column = position - info->line_start;
13788 info->line_end = SMI_VALUE(ends->get(info->line));
13789 if (info->line_end > 0) {
13790 DCHECK(source()->IsString());
13791 String src = String::cast(source());
13792 if (src->length() >= info->line_end &&
13793 src->Get(info->line_end - 1) ==
'\r') {
13800 if (offset_flag == WITH_OFFSET) {
13801 if (info->line == 0) {
13802 info->column += column_offset();
13804 info->line += line_offset();
13811 int Script::GetColumnNumber(Handle<Script> script,
int code_pos) {
13813 GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
13814 return info.column;
13817 int Script::GetColumnNumber(
int code_pos)
const {
13819 GetPositionInfo(code_pos, &info, WITH_OFFSET);
13820 return info.column;
13823 int Script::GetLineNumber(Handle<Script> script,
int code_pos) {
13825 GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
13829 int Script::GetLineNumber(
int code_pos)
const {
13831 GetPositionInfo(code_pos, &info, WITH_OFFSET);
13835 Object* Script::GetNameOrSourceURL() {
13837 if (!source_url()->IsUndefined())
return source_url();
13841 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
13842 Isolate* isolate,
const FunctionLiteral* fun) {
13843 CHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
13848 CHECK_LT(fun->function_literal_id(), shared_function_infos()->length());
13849 MaybeObject shared = shared_function_infos()->Get(fun->function_literal_id());
13850 HeapObject* heap_object;
13851 if (!shared->GetHeapObject(&heap_object) ||
13852 heap_object->IsUndefined(isolate)) {
13853 return MaybeHandle<SharedFunctionInfo>();
13855 return handle(SharedFunctionInfo::cast(heap_object), isolate);
13858 Script::Iterator::Iterator(Isolate* isolate)
13859 : iterator_(isolate->heap()->script_list()) {}
13861 Script* Script::Iterator::Next() {
13862 Object* o = iterator_.Next();
13863 if (o !=
nullptr) {
13864 return Script::cast(o);
13869 Code SharedFunctionInfo::GetCode()
const {
13875 Isolate* isolate = GetIsolate();
13876 Object* data = function_data();
13877 if (data->IsSmi()) {
13879 DCHECK(HasBuiltinId());
13880 return isolate->builtins()->builtin(builtin_id());
13881 }
else if (data->IsBytecodeArray()) {
13883 DCHECK(HasBytecodeArray());
13884 return isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
13885 }
else if (data->IsAsmWasmData()) {
13887 DCHECK(HasAsmWasmData());
13888 return isolate->builtins()->builtin(Builtins::kInstantiateAsmJs);
13889 }
else if (data->IsUncompiledData()) {
13891 DCHECK(HasUncompiledData());
13892 return isolate->builtins()->builtin(Builtins::kCompileLazy);
13893 }
else if (data->IsFunctionTemplateInfo()) {
13895 DCHECK(IsApiFunction());
13896 return isolate->builtins()->builtin(Builtins::kHandleApiCall);
13897 }
else if (data->IsWasmExportedFunctionData()) {
13899 DCHECK(HasWasmExportedFunctionData());
13900 return wasm_exported_function_data()->wrapper_code();
13901 }
else if (data->IsInterpreterData()) {
13902 Code code = InterpreterTrampoline();
13903 DCHECK(code->IsCode());
13904 DCHECK(code->is_interpreter_trampoline_builtin());
13910 WasmExportedFunctionData* SharedFunctionInfo::wasm_exported_function_data()
13912 DCHECK(HasWasmExportedFunctionData());
13913 return WasmExportedFunctionData::cast(function_data());
13916 SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
13918 : ScriptIterator(isolate,
13919 handle(script->shared_function_infos(), isolate)) {}
13921 SharedFunctionInfo::ScriptIterator::ScriptIterator(
13922 Isolate* isolate, Handle<WeakFixedArray> shared_function_infos)
13923 : isolate_(isolate),
13924 shared_function_infos_(shared_function_infos),
13927 SharedFunctionInfo* SharedFunctionInfo::ScriptIterator::Next() {
13928 while (index_ < shared_function_infos_->length()) {
13929 MaybeObject raw = shared_function_infos_->Get(index_++);
13930 HeapObject* heap_object;
13931 if (!raw->GetHeapObject(&heap_object) ||
13932 heap_object->IsUndefined(isolate_)) {
13935 return SharedFunctionInfo::cast(heap_object);
13940 void SharedFunctionInfo::ScriptIterator::Reset(Script* script) {
13941 shared_function_infos_ = handle(script->shared_function_infos(), isolate_);
13945 SharedFunctionInfo::GlobalIterator::GlobalIterator(Isolate* isolate)
13946 : script_iterator_(isolate),
13947 noscript_sfi_iterator_(isolate->heap()->noscript_shared_function_infos()),
13948 sfi_iterator_(isolate, script_iterator_.Next()) {}
13950 SharedFunctionInfo* SharedFunctionInfo::GlobalIterator::Next() {
13951 HeapObject* next = noscript_sfi_iterator_.Next();
13952 if (next !=
nullptr)
return SharedFunctionInfo::cast(next);
13954 next = sfi_iterator_.Next();
13955 if (next !=
nullptr)
return SharedFunctionInfo::cast(next);
13956 Script* next_script = script_iterator_.Next();
13957 if (next_script ==
nullptr)
return nullptr;
13958 sfi_iterator_.Reset(next_script);
13962 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
13963 Handle<Object> script_object,
13964 int function_literal_id,
13965 bool reset_preparsed_scope_data) {
13966 if (shared->script() == *script_object)
return;
13967 Isolate* isolate = shared->GetIsolate();
13969 if (reset_preparsed_scope_data &&
13970 shared->HasUncompiledDataWithPreParsedScope()) {
13971 shared->ClearPreParsedScopeData();
13978 if (script_object->IsScript()) {
13979 DCHECK(!shared->script()->IsScript());
13980 Handle<Script> script = Handle<Script>::cast(script_object);
13981 Handle<WeakFixedArray> list =
13982 handle(script->shared_function_infos(), isolate);
13984 DCHECK_LT(function_literal_id, list->length());
13985 MaybeObject maybe_object = list->Get(function_literal_id);
13986 HeapObject* heap_object;
13987 if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
13988 DCHECK_EQ(heap_object, *shared);
13991 list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
13994 WeakArrayList* noscript_list =
13995 isolate->heap()->noscript_shared_function_infos();
13996 CHECK(noscript_list->RemoveOne(MaybeObjectHandle::Weak(shared)));
13998 DCHECK(shared->script()->IsScript());
13999 Handle<WeakArrayList> list =
14000 isolate->factory()->noscript_shared_function_infos();
14003 if (FLAG_enable_slow_asserts) {
14004 WeakArrayList::Iterator iterator(*list);
14006 while ((next = iterator.Next()) !=
nullptr) {
14007 DCHECK_NE(next, *shared);
14013 WeakArrayList::AddToEnd(isolate, list, MaybeObjectHandle::Weak(shared));
14015 isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
14018 Script* old_script = Script::cast(shared->script());
14022 Handle<WeakFixedArray> infos(old_script->shared_function_infos(), isolate);
14023 if (function_literal_id < infos->length()) {
14025 old_script->shared_function_infos()->Get(function_literal_id);
14026 HeapObject* heap_object;
14027 if (raw->GetHeapObjectIfWeak(&heap_object) && heap_object == *shared) {
14028 old_script->shared_function_infos()->Set(
14029 function_literal_id, HeapObjectReference::Strong(
14030 ReadOnlyRoots(isolate).undefined_value()));
14036 shared->set_script(*script_object);
14039 bool SharedFunctionInfo::HasBreakInfo()
const {
14040 if (!HasDebugInfo())
return false;
14041 DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14042 bool has_break_info = info->HasBreakInfo();
14043 return has_break_info;
14046 bool SharedFunctionInfo::BreakAtEntry()
const {
14047 if (!HasDebugInfo())
return false;
14048 DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14049 bool break_at_entry = info->BreakAtEntry();
14050 return break_at_entry;
14053 bool SharedFunctionInfo::HasCoverageInfo()
const {
14054 if (!HasDebugInfo())
return false;
14055 DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14056 bool has_coverage_info = info->HasCoverageInfo();
14057 return has_coverage_info;
14060 CoverageInfo SharedFunctionInfo::GetCoverageInfo()
const {
14061 DCHECK(HasCoverageInfo());
14062 return CoverageInfo::cast(GetDebugInfo()->coverage_info());
14065 String SharedFunctionInfo::DebugName() {
14066 DisallowHeapAllocation no_gc;
14067 String function_name = Name();
14068 if (function_name->length() > 0)
return function_name;
14069 return inferred_name();
14072 bool SharedFunctionInfo::PassesFilter(
const char* raw_filter) {
14073 Vector<const char> filter = CStrVector(raw_filter);
14074 std::unique_ptr<char[]> cstrname(DebugName()->ToCString());
14075 return v8::internal::PassesFilter(CStrVector(cstrname.get()), filter);
14078 bool SharedFunctionInfo::HasSourceCode()
const {
14079 Isolate* isolate = GetIsolate();
14080 return !script()->IsUndefined(isolate) &&
14081 !
reinterpret_cast<Script*
>(script())->source()->IsUndefined(isolate);
14085 Handle<Object> SharedFunctionInfo::GetSourceCode(
14086 Handle<SharedFunctionInfo> shared) {
14087 Isolate* isolate = shared->GetIsolate();
14088 if (!shared->HasSourceCode())
return isolate->factory()->undefined_value();
14089 Handle<String> source(String::cast(Script::cast(shared->script())->source()),
14091 return isolate->factory()->NewSubString(source, shared->StartPosition(),
14092 shared->EndPosition());
14096 Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony(
14097 Handle<SharedFunctionInfo> shared) {
14098 Isolate* isolate = shared->GetIsolate();
14099 if (!shared->HasSourceCode())
return isolate->factory()->undefined_value();
14100 Handle<String> script_source(
14101 String::cast(Script::cast(shared->script())->source()), isolate);
14102 int start_pos = shared->function_token_position();
14103 DCHECK_NE(start_pos, kNoSourcePosition);
14104 Handle<String> source = isolate->factory()->NewSubString(
14105 script_source, start_pos, shared->EndPosition());
14106 if (!shared->is_wrapped())
return source;
14108 DCHECK(!shared->name_should_print_as_anonymous());
14109 IncrementalStringBuilder builder(isolate);
14110 builder.AppendCString(
"function ");
14111 builder.AppendString(Handle<String>(shared->Name(), isolate));
14112 builder.AppendCString(
"(");
14113 Handle<FixedArray> args(Script::cast(shared->script())->wrapped_arguments(),
14115 int argc = args->length();
14116 for (
int i = 0;
i < argc;
i++) {
14117 if (
i > 0) builder.AppendCString(
", ");
14118 builder.AppendString(Handle<String>(String::cast(args->get(
i)), isolate));
14120 builder.AppendCString(
") {\n");
14121 builder.AppendString(source);
14122 builder.AppendCString(
"\n}");
14123 return builder.Finish().ToHandleChecked();
14126 bool SharedFunctionInfo::IsInlineable() {
14128 if (!script()->IsScript())
return false;
14129 if (GetIsolate()->is_precise_binary_code_coverage() &&
14130 !has_reported_binary_coverage()) {
14134 return !optimization_disabled();
14137 int SharedFunctionInfo::SourceSize() {
return EndPosition() - StartPosition(); }
14139 int SharedFunctionInfo::FindIndexInScript(Isolate* isolate)
const {
14140 DisallowHeapAllocation no_gc;
14142 Object* script_obj = script();
14143 if (!script_obj->IsScript())
return FunctionLiteral::kIdTypeInvalid;
14145 WeakFixedArray* shared_info_list =
14146 Script::cast(script_obj)->shared_function_infos();
14147 SharedFunctionInfo::ScriptIterator iterator(
14148 isolate, Handle<WeakFixedArray>(&shared_info_list));
14150 for (SharedFunctionInfo* shared = iterator.Next(); shared !=
nullptr;
14151 shared = iterator.Next()) {
14152 if (shared ==
this) {
14153 return iterator.CurrentIndex();
14157 return FunctionLiteral::kIdTypeInvalid;
14160 void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
14161 bool has_prototype_slot,
14162 int requested_embedder_fields,
14163 int requested_in_object_properties,
14164 int* instance_size,
14165 int* in_object_properties) {
14166 DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
14167 JSObject::kMaxEmbedderFields);
14168 requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
14169 int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
14170 int max_nof_fields =
14171 (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2;
14172 CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
14173 CHECK_LE(static_cast<unsigned>(requested_embedder_fields),
14174 static_cast<unsigned>(max_nof_fields));
14175 *in_object_properties = Min(requested_in_object_properties,
14176 max_nof_fields - requested_embedder_fields);
14179 ((requested_embedder_fields + *in_object_properties) << kPointerSizeLog2);
14180 CHECK_EQ(*in_object_properties,
14181 ((*instance_size - header_size) >> kPointerSizeLog2) -
14182 requested_embedder_fields);
14183 CHECK_LE(static_cast<unsigned>(*instance_size),
14184 static_cast<unsigned>(JSObject::kMaxInstanceSize));
14188 bool JSFunction::CalculateInstanceSizeForDerivedClass(
14189 Handle<JSFunction>
function, InstanceType instance_type,
14190 int requested_embedder_fields,
int* instance_size,
14191 int* in_object_properties) {
14192 Isolate* isolate =
function->GetIsolate();
14193 int expected_nof_properties = 0;
14194 for (PrototypeIterator iter(isolate,
function, kStartAtReceiver);
14195 !iter.IsAtEnd(); iter.Advance()) {
14196 Handle<JSReceiver> current =
14197 PrototypeIterator::GetCurrent<JSReceiver>(iter);
14198 if (!current->IsJSFunction())
break;
14199 Handle<JSFunction> func(Handle<JSFunction>::cast(current));
14202 Handle<SharedFunctionInfo> shared(func->shared(), isolate);
14203 if (shared->is_compiled() ||
14204 Compiler::Compile(func, Compiler::CLEAR_EXCEPTION)) {
14205 DCHECK(shared->is_compiled());
14206 int count = shared->expected_nof_properties();
14208 if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) {
14209 expected_nof_properties += count;
14211 expected_nof_properties = JSObject::kMaxInObjectProperties;
14213 }
else if (!shared->is_compiled()) {
14218 if (!IsDerivedConstructor(shared->kind()))
break;
14220 CalculateInstanceSizeHelper(instance_type,
true, requested_embedder_fields,
14221 expected_nof_properties, instance_size,
14222 in_object_properties);
14228 std::ostream& operator<<(std::ostream& os,
const SourceCodeOf& v) {
14229 const SharedFunctionInfo* s = v.value;
14231 if (!s->HasSourceCode())
return os <<
"<No Source>";
14236 String script_source =
14237 String::unchecked_cast(Script::cast(s->script())->source());
14239 if (!script_source->LooksValid())
return os <<
"<Invalid Source>";
14241 if (!s->is_toplevel()) {
14243 String name = s->Name();
14244 if (name->length() > 0) {
14245 name->PrintUC16(os);
14249 int len = s->EndPosition() - s->StartPosition();
14250 if (len <= v.max_length || v.max_length < 0) {
14251 script_source->PrintUC16(os, s->StartPosition(), s->EndPosition());
14254 script_source->PrintUC16(os, s->StartPosition(),
14255 s->StartPosition() + v.max_length);
14256 return os <<
"...\n";
14261 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
14262 DCHECK_NE(reason, BailoutReason::kNoReason);
14264 set_flags(DisabledOptimizationReasonBits::update(flags(), reason));
14266 DCHECK(abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
14267 abstract_code()->kind() == AbstractCode::BUILTIN);
14268 PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(),
this));
14269 if (FLAG_trace_opt) {
14270 PrintF(
"[disabled optimization for ");
14272 PrintF(
", reason: %s]\n", GetBailoutReason(reason));
14276 void SharedFunctionInfo::InitFromFunctionLiteral(
14277 Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit,
14278 bool is_toplevel) {
14279 Isolate* isolate = shared_info->GetIsolate();
14280 bool needs_position_info =
true;
14284 shared_info->set_internal_formal_parameter_count(lit->parameter_count());
14285 shared_info->SetFunctionTokenPosition(lit->function_token_position(),
14286 lit->start_position());
14287 if (shared_info->scope_info()->HasPositionInfo()) {
14288 shared_info->scope_info()->SetPositionInfo(lit->start_position(),
14289 lit->end_position());
14290 needs_position_info =
false;
14292 shared_info->set_is_declaration(lit->is_declaration());
14293 shared_info->set_is_named_expression(lit->is_named_expression());
14294 shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
14295 shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
14296 shared_info->set_language_mode(lit->language_mode());
14297 shared_info->set_is_wrapped(lit->is_wrapped());
14300 DCHECK(lit->kind() == shared_info->kind());
14301 shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
14302 DCHECK_IMPLIES(lit->requires_instance_members_initializer(),
14303 IsClassConstructor(lit->kind()));
14304 shared_info->set_requires_instance_members_initializer(
14305 lit->requires_instance_members_initializer());
14307 shared_info->set_is_toplevel(is_toplevel);
14308 DCHECK(shared_info->outer_scope_info()->IsTheHole());
14309 if (!is_toplevel) {
14310 Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
14312 shared_info->set_outer_scope_info(*outer_scope->scope_info());
14320 if (lit->ShouldEagerCompile()) {
14321 shared_info->set_length(lit->function_length());
14322 shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
14323 shared_info->SetExpectedNofPropertiesFromEstimate(lit);
14324 DCHECK_NULL(lit->produced_preparsed_scope_data());
14329 needs_position_info =
false;
14334 shared_info->set_length(SharedFunctionInfo::kInvalidLength);
14335 ProducedPreParsedScopeData* scope_data =
14336 lit->produced_preparsed_scope_data();
14337 if (scope_data !=
nullptr) {
14338 Handle<PreParsedScopeData> pre_parsed_scope_data;
14339 if (scope_data->Serialize(shared_info->GetIsolate())
14340 .ToHandle(&pre_parsed_scope_data)) {
14341 Handle<UncompiledData> data =
14342 isolate->factory()->NewUncompiledDataWithPreParsedScope(
14343 lit->inferred_name(), lit->start_position(),
14344 lit->end_position(), lit->function_literal_id(),
14345 pre_parsed_scope_data);
14346 shared_info->set_uncompiled_data(*data);
14347 needs_position_info =
false;
14351 if (needs_position_info) {
14352 Handle<UncompiledData> data =
14353 isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
14354 lit->inferred_name(), lit->start_position(), lit->end_position(),
14355 lit->function_literal_id());
14356 shared_info->set_uncompiled_data(*data);
14360 void SharedFunctionInfo::SetExpectedNofPropertiesFromEstimate(
14361 FunctionLiteral* literal) {
14362 int estimate = literal->expected_property_count();
14366 if (estimate == 0) estimate = 2;
14374 STATIC_ASSERT(JSObject::kMaxInObjectProperties <= kMaxUInt8);
14375 estimate = std::min(estimate, kMaxUInt8);
14377 set_expected_nof_properties(estimate);
14380 void SharedFunctionInfo::SetFunctionTokenPosition(
int function_token_position,
14381 int start_position) {
14383 if (function_token_position == kNoSourcePosition) {
14386 offset = start_position - function_token_position;
14389 if (offset > kMaximumFunctionTokenOffset) {
14390 offset = kFunctionTokenOutOfRange;
14392 set_raw_function_token_offset(offset);
14395 int SharedFunctionInfo::StartPosition()
const {
14396 Object* maybe_scope_info = name_or_scope_info();
14397 if (maybe_scope_info->IsScopeInfo()) {
14398 ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14399 if (info->HasPositionInfo()) {
14400 return info->StartPosition();
14402 }
else if (HasUncompiledData()) {
14404 return uncompiled_data()->start_position();
14405 }
else if (IsApiFunction() || HasBuiltinId()) {
14406 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
14409 return kNoSourcePosition;
14412 int SharedFunctionInfo::EndPosition()
const {
14413 Object* maybe_scope_info = name_or_scope_info();
14414 if (maybe_scope_info->IsScopeInfo()) {
14415 ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14416 if (info->HasPositionInfo()) {
14417 return info->EndPosition();
14419 }
else if (HasUncompiledData()) {
14421 return uncompiled_data()->end_position();
14422 }
else if (IsApiFunction() || HasBuiltinId()) {
14423 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
14426 return kNoSourcePosition;
14429 int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate)
const {
14432 if (HasUncompiledData()) {
14433 int id = uncompiled_data()->function_literal_id();
14435 DCHECK_EQ(
id, FindIndexInScript(isolate));
14441 return FindIndexInScript(isolate);
14444 void SharedFunctionInfo::SetPosition(
int start_position,
int end_position) {
14445 Object* maybe_scope_info = name_or_scope_info();
14446 if (maybe_scope_info->IsScopeInfo()) {
14447 ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14448 if (info->HasPositionInfo()) {
14449 info->SetPositionInfo(start_position, end_position);
14451 }
else if (HasUncompiledData()) {
14452 if (HasUncompiledDataWithPreParsedScope()) {
14455 ClearPreParsedScopeData();
14457 uncompiled_data()->set_start_position(start_position);
14458 uncompiled_data()->set_end_position(end_position);
14464 void Map::StartInobjectSlackTracking() {
14465 DCHECK(!IsInobjectSlackTrackingInProgress());
14466 if (UnusedPropertyFields() == 0)
return;
14467 set_construction_counter(Map::kSlackTrackingCounterStart);
14470 void ObjectVisitor::VisitCodeTarget(Code host, RelocInfo* rinfo) {
14471 DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
14472 Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
14473 Object* new_pointer = old_pointer;
14474 VisitPointer(host, ObjectSlot(&new_pointer));
14475 DCHECK_EQ(old_pointer, new_pointer);
14478 void ObjectVisitor::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) {
14479 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
14480 Object* old_pointer = rinfo->target_object();
14481 Object* new_pointer = old_pointer;
14482 VisitPointer(host, ObjectSlot(&new_pointer));
14483 DCHECK_EQ(old_pointer, new_pointer);
14486 void ObjectVisitor::VisitRelocInfo(RelocIterator* it) {
14487 for (; !it->done(); it->next()) {
14488 it->rinfo()->Visit(
this);
14492 void Code::ClearEmbeddedObjects(Heap* heap) {
14493 HeapObject* undefined = ReadOnlyRoots(heap).undefined_value();
14494 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14495 for (RelocIterator it(*
this, mode_mask); !it.done(); it.next()) {
14496 RelocInfo::Mode mode = it.rinfo()->rmode();
14497 if (mode == RelocInfo::EMBEDDED_OBJECT) {
14498 it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
14501 set_embedded_objects_cleared(
true);
14505 void Code::Relocate(intptr_t delta) {
14506 for (RelocIterator it(*
this, RelocInfo::kApplyMask); !it.done(); it.next()) {
14507 it.rinfo()->apply(delta);
14509 Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
14512 void Code::FlushICache()
const {
14513 Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
14516 void Code::CopyFromNoFlush(Heap* heap,
const CodeDesc& desc) {
14518 CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
14519 static_cast<size_t>(desc.instr_size));
14522 if (desc.unwinding_info) {
14523 DCHECK_GT(desc.unwinding_info_size, 0);
14524 set_unwinding_info_size(desc.unwinding_info_size);
14525 CopyBytes(reinterpret_cast<byte*>(unwinding_info_start()),
14526 desc.unwinding_info,
14527 static_cast<size_t>(desc.unwinding_info_size));
14531 CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
14534 Assembler* origin = desc.origin;
14535 AllowDeferredHandleDereference embedding_raw_address;
14536 const int mode_mask = RelocInfo::PostCodegenRelocationMask();
14537 for (RelocIterator it(*
this, mode_mask); !it.done(); it.next()) {
14538 RelocInfo::Mode mode = it.rinfo()->rmode();
14539 if (mode == RelocInfo::EMBEDDED_OBJECT) {
14540 Handle<HeapObject> p = it.rinfo()->target_object_handle(origin);
14541 it.rinfo()->set_target_object(heap, *p, UPDATE_WRITE_BARRIER,
14542 SKIP_ICACHE_FLUSH);
14543 }
else if (RelocInfo::IsCodeTargetMode(mode)) {
14546 Handle<Object> p = it.rinfo()->target_object_handle(origin);
14547 Code code = Code::cast(*p);
14548 it.rinfo()->set_target_address(code->raw_instruction_start(),
14549 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
14550 }
else if (RelocInfo::IsRuntimeEntry(mode)) {
14551 Address p = it.rinfo()->target_runtime_entry(origin);
14552 it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
14553 SKIP_ICACHE_FLUSH);
14556 raw_instruction_start() -
reinterpret_cast<Address
>(desc.buffer);
14557 it.rinfo()->apply(delta);
14563 SafepointEntry Code::GetSafepointEntry(Address pc) {
14564 SafepointTable table(*
this);
14565 return table.FindEntry(pc);
14568 int Code::OffHeapInstructionSize()
const {
14569 DCHECK(is_off_heap_trampoline());
14570 if (Isolate::CurrentEmbeddedBlob() ==
nullptr)
return raw_instruction_size();
14571 EmbeddedData d = EmbeddedData::FromBlob();
14572 return d.InstructionSizeOfBuiltin(builtin_index());
14575 Address Code::OffHeapInstructionStart()
const {
14576 DCHECK(is_off_heap_trampoline());
14577 if (Isolate::CurrentEmbeddedBlob() ==
nullptr)
return raw_instruction_start();
14578 EmbeddedData d = EmbeddedData::FromBlob();
14579 return d.InstructionStartOfBuiltin(builtin_index());
14582 Address Code::OffHeapInstructionEnd()
const {
14583 DCHECK(is_off_heap_trampoline());
14584 if (Isolate::CurrentEmbeddedBlob() ==
nullptr)
return raw_instruction_end();
14585 EmbeddedData d = EmbeddedData::FromBlob();
14586 return d.InstructionStartOfBuiltin(builtin_index()) +
14587 d.InstructionSizeOfBuiltin(builtin_index());
14591 template <
typename Code>
14592 void SetStackFrameCacheCommon(Isolate* isolate, Handle<Code> code,
14593 Handle<SimpleNumberDictionary> cache) {
14594 Handle<Object> maybe_table(code->source_position_table(), isolate);
14595 if (maybe_table->IsSourcePositionTableWithFrameCache()) {
14596 Handle<SourcePositionTableWithFrameCache>::cast(maybe_table)
14597 ->set_stack_frame_cache(*cache);
14600 DCHECK(maybe_table->IsByteArray());
14601 Handle<ByteArray> table(Handle<ByteArray>::cast(maybe_table));
14602 Handle<SourcePositionTableWithFrameCache> table_with_cache =
14603 isolate->factory()->NewSourcePositionTableWithFrameCache(table, cache);
14604 code->set_source_position_table(*table_with_cache);
14609 void AbstractCode::SetStackFrameCache(Handle<AbstractCode> abstract_code,
14610 Handle<SimpleNumberDictionary> cache) {
14611 if (abstract_code->IsCode()) {
14612 SetStackFrameCacheCommon(
14613 abstract_code->GetIsolate(),
14614 handle(abstract_code->GetCode(), abstract_code->GetIsolate()), cache);
14616 SetStackFrameCacheCommon(
14617 abstract_code->GetIsolate(),
14618 handle(abstract_code->GetBytecodeArray(), abstract_code->GetIsolate()),
14624 template <
typename Code>
14625 void DropStackFrameCacheCommon(Code code) {
14626 i::Object* maybe_table = code->source_position_table();
14627 if (maybe_table->IsByteArray())
return;
14628 DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
14629 code->set_source_position_table(
14630 i::SourcePositionTableWithFrameCache::cast(maybe_table)
14631 ->source_position_table());
14635 void AbstractCode::DropStackFrameCache() {
14637 DropStackFrameCacheCommon(GetCode());
14639 DropStackFrameCacheCommon(GetBytecodeArray());
14643 int AbstractCode::SourcePosition(
int offset) {
14646 if (IsCode()) offset--;
14647 for (SourcePositionTableIterator iterator(source_position_table());
14648 !iterator.done() && iterator.code_offset() <= offset;
14649 iterator.Advance()) {
14650 position = iterator.source_position().ScriptOffset();
14655 int AbstractCode::SourceStatementPosition(
int offset) {
14657 int position = SourcePosition(offset);
14659 int statement_position = 0;
14660 for (SourcePositionTableIterator it(source_position_table()); !it.done();
14662 if (it.is_statement()) {
14663 int p = it.source_position().ScriptOffset();
14664 if (statement_position < p && p <= position) {
14665 statement_position = p;
14669 return statement_position;
14672 void JSFunction::ClearTypeFeedbackInfo() {
14673 if (feedback_cell()->value()->IsFeedbackVector()) {
14674 FeedbackVector* vector = feedback_vector();
14675 Isolate* isolate = GetIsolate();
14676 if (vector->ClearSlots(isolate)) {
14677 IC::OnFeedbackChanged(isolate, vector, FeedbackSlot::Invalid(),
this,
14678 "ClearTypeFeedbackInfo");
14683 void Code::PrintDeoptLocation(FILE* out,
const char* str, Address pc) {
14684 Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(*
this, pc);
14685 class SourcePosition pos = info.position;
14686 if (info.deopt_reason != DeoptimizeReason::kUnknown || pos.IsKnown()) {
14687 PrintF(out,
"%s", str);
14688 OFStream outstr(out);
14689 pos.Print(outstr, *
this);
14690 PrintF(out,
", %s\n", DeoptimizeReasonToString(info.deopt_reason));
14695 bool Code::CanDeoptAt(Address pc) {
14696 DeoptimizationData deopt_data =
14697 DeoptimizationData::cast(deoptimization_data());
14698 Address code_start_address = InstructionStart();
14699 for (
int i = 0;
i < deopt_data->DeoptCount();
i++) {
14700 if (deopt_data->Pc(
i)->value() == -1)
continue;
14701 Address address = code_start_address + deopt_data->Pc(
i)->value();
14702 if (address == pc && deopt_data->BytecodeOffset(
i) != BailoutId::None()) {
14711 const char* Code::Kind2String(Kind kind) {
14713 #define CASE(name) case name: return #name; 14714 CODE_KIND_LIST(CASE)
14716 case NUMBER_OF_KINDS:
break;
14722 const char* AbstractCode::Kind2String(Kind kind) {
14723 if (kind < AbstractCode::INTERPRETED_FUNCTION)
14724 return Code::Kind2String(static_cast<Code::Kind>(kind));
14725 if (kind == AbstractCode::INTERPRETED_FUNCTION)
return "INTERPRETED_FUNCTION";
14729 bool Code::IsIsolateIndependent(Isolate* isolate) {
14730 constexpr
int all_real_modes_mask =
14731 (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
14732 constexpr
int mode_mask = all_real_modes_mask &
14733 ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
14734 ~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
14735 ~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
14736 ~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
14737 STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
14738 STATIC_ASSERT(RelocInfo::ModeMask(RelocInfo::COMMENT) ==
14739 (1 << RelocInfo::COMMENT));
14740 STATIC_ASSERT(mode_mask ==
14741 (RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14742 RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
14743 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
14744 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
14745 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
14746 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
14747 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
14748 RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
14749 RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
14751 bool is_process_independent =
true;
14752 for (RelocIterator it(*
this, mode_mask); !it.done(); it.next()) {
14753 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \ 14754 defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) || \ 14755 defined(V8_TARGET_ARCH_IA32) 14760 if (RelocInfo::IsCodeTargetMode(it.rinfo()->rmode())) {
14761 Address target_address = it.rinfo()->target_address();
14762 if (InstructionStream::PcIsOffHeap(isolate, target_address))
continue;
14764 Code target = Code::GetCodeFromTargetAddress(target_address);
14765 CHECK(target->IsCode());
14766 if (Builtins::IsIsolateIndependentBuiltin(target))
continue;
14769 is_process_independent =
false;
14772 return is_process_independent;
14775 bool Code::Inlines(SharedFunctionInfo* sfi) {
14777 DCHECK(is_optimized_code());
14778 DisallowHeapAllocation no_gc;
14779 DeoptimizationData
const data =
14780 DeoptimizationData::cast(deoptimization_data());
14781 if (data->length() == 0)
return false;
14782 if (data->SharedFunctionInfo() == sfi)
return true;
14783 FixedArray
const literals = data->LiteralArray();
14784 int const inlined_count = data->InlinedFunctionCount()->value();
14785 for (
int i = 0;
i < inlined_count; ++
i) {
14786 if (SharedFunctionInfo::cast(literals->get(
i)) == sfi)
return true;
14791 Code::OptimizedCodeIterator::OptimizedCodeIterator(Isolate* isolate) {
14792 isolate_ = isolate;
14793 Object* list = isolate->heap()->native_contexts_list();
14794 next_context_ = list->IsUndefined(isolate_) ? Context() : Context::cast(list);
14797 Code Code::OptimizedCodeIterator::Next() {
14800 if (!current_code_.is_null()) {
14802 next = current_code_->next_code_link();
14803 }
else if (!next_context_.is_null()) {
14805 next = next_context_->OptimizedCodeListHead();
14806 Object* next_context = next_context_->next_context_link();
14807 next_context_ = next_context->IsUndefined(isolate_)
14809 : Context::cast(next_context);
14814 current_code_ = next->IsUndefined(isolate_) ? Code() : Code::cast(next);
14815 }
while (current_code_.is_null());
14816 DCHECK_EQ(Code::OPTIMIZED_FUNCTION, current_code_->kind());
14817 return current_code_;
14820 #ifdef ENABLE_DISASSEMBLER 14823 void print_pc(std::ostream& os,
int pc) {
14827 os << std::hex << pc << std::dec;
14832 void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) {
14833 if (length() == 0) {
14834 os <<
"Deoptimization Input Data invalidated by lazy deoptimization\n";
14839 int const inlined_function_count = InlinedFunctionCount()->value();
14840 os <<
"Inlined functions (count = " << inlined_function_count <<
")\n";
14841 for (
int id = 0;
id < inlined_function_count; ++id) {
14842 Object* info = LiteralArray()->get(
id);
14843 os <<
" " << Brief(SharedFunctionInfo::cast(info)) <<
"\n";
14846 int deopt_count = DeoptCount();
14847 os <<
"Deoptimization Input Data (deopt points = " << deopt_count <<
")\n";
14848 if (0 != deopt_count) {
14849 os <<
" index bytecode-offset pc";
14850 if (FLAG_print_code_verbose) os <<
" commands";
14853 for (
int i = 0;
i < deopt_count;
i++) {
14854 os << std::setw(6) <<
i <<
" " << std::setw(15)
14855 << BytecodeOffset(
i).ToInt() <<
" " << std::setw(4);
14856 print_pc(os, Pc(
i)->value());
14857 os << std::setw(2);
14859 if (!FLAG_print_code_verbose) {
14865 int translation_index = TranslationIndex(
i)->value();
14866 TranslationIterator iterator(TranslationByteArray(), translation_index);
14867 Translation::Opcode opcode =
14868 static_cast<Translation::Opcode
>(iterator.Next());
14869 DCHECK(Translation::BEGIN == opcode);
14870 int frame_count = iterator.Next();
14871 int jsframe_count = iterator.Next();
14872 int update_feedback_count = iterator.Next();
14873 os <<
" " << Translation::StringFor(opcode)
14874 <<
" {frame count=" << frame_count
14875 <<
", js frame count=" << jsframe_count
14876 <<
", update_feedback_count=" << update_feedback_count <<
"}\n";
14878 while (iterator.HasNext() &&
14879 Translation::BEGIN !=
14880 (opcode =
static_cast<Translation::Opcode
>(iterator.Next()))) {
14881 os << std::setw(31) <<
" " << Translation::StringFor(opcode) <<
" ";
14884 case Translation::BEGIN:
14888 case Translation::INTERPRETED_FRAME: {
14889 int bytecode_offset = iterator.Next();
14890 int shared_info_id = iterator.Next();
14891 unsigned height = iterator.Next();
14892 int return_value_offset = iterator.Next();
14893 int return_value_count = iterator.Next();
14894 Object* shared_info = LiteralArray()->get(shared_info_id);
14895 os <<
"{bytecode_offset=" << bytecode_offset <<
", function=" 14896 << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14897 <<
", height=" << height <<
", retval=@" << return_value_offset
14898 <<
"(#" << return_value_count <<
")}";
14902 case Translation::CONSTRUCT_STUB_FRAME: {
14903 int bailout_id = iterator.Next();
14904 int shared_info_id = iterator.Next();
14905 Object* shared_info = LiteralArray()->get(shared_info_id);
14906 unsigned height = iterator.Next();
14907 os <<
"{bailout_id=" << bailout_id <<
", function=" 14908 << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14909 <<
", height=" << height <<
"}";
14913 case Translation::BUILTIN_CONTINUATION_FRAME:
14914 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
14915 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
14916 int bailout_id = iterator.Next();
14917 int shared_info_id = iterator.Next();
14918 Object* shared_info = LiteralArray()->get(shared_info_id);
14919 unsigned height = iterator.Next();
14920 os <<
"{bailout_id=" << bailout_id <<
", function=" 14921 << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14922 <<
", height=" << height <<
"}";
14926 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
14927 int shared_info_id = iterator.Next();
14928 Object* shared_info = LiteralArray()->get(shared_info_id);
14929 unsigned height = iterator.Next();
14931 << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14932 <<
", height=" << height <<
"}";
14936 case Translation::REGISTER: {
14937 int reg_code = iterator.Next();
14938 os <<
"{input=" << converter.NameOfCPURegister(reg_code) <<
"}";
14942 case Translation::INT32_REGISTER: {
14943 int reg_code = iterator.Next();
14944 os <<
"{input=" << converter.NameOfCPURegister(reg_code)
14949 case Translation::INT64_REGISTER: {
14950 int reg_code = iterator.Next();
14951 os <<
"{input=" << converter.NameOfCPURegister(reg_code)
14956 case Translation::UINT32_REGISTER: {
14957 int reg_code = iterator.Next();
14958 os <<
"{input=" << converter.NameOfCPURegister(reg_code)
14963 case Translation::BOOL_REGISTER: {
14964 int reg_code = iterator.Next();
14965 os <<
"{input=" << converter.NameOfCPURegister(reg_code)
14970 case Translation::FLOAT_REGISTER: {
14971 int reg_code = iterator.Next();
14972 os <<
"{input=" << FloatRegister::from_code(reg_code) <<
"}";
14976 case Translation::DOUBLE_REGISTER: {
14977 int reg_code = iterator.Next();
14978 os <<
"{input=" << DoubleRegister::from_code(reg_code) <<
"}";
14982 case Translation::STACK_SLOT: {
14983 int input_slot_index = iterator.Next();
14984 os <<
"{input=" << input_slot_index <<
"}";
14988 case Translation::INT32_STACK_SLOT: {
14989 int input_slot_index = iterator.Next();
14990 os <<
"{input=" << input_slot_index <<
" (int32)}";
14994 case Translation::INT64_STACK_SLOT: {
14995 int input_slot_index = iterator.Next();
14996 os <<
"{input=" << input_slot_index <<
" (int64)}";
15000 case Translation::UINT32_STACK_SLOT: {
15001 int input_slot_index = iterator.Next();
15002 os <<
"{input=" << input_slot_index <<
" (uint32)}";
15006 case Translation::BOOL_STACK_SLOT: {
15007 int input_slot_index = iterator.Next();
15008 os <<
"{input=" << input_slot_index <<
" (bool)}";
15012 case Translation::FLOAT_STACK_SLOT:
15013 case Translation::DOUBLE_STACK_SLOT: {
15014 int input_slot_index = iterator.Next();
15015 os <<
"{input=" << input_slot_index <<
"}";
15019 case Translation::LITERAL: {
15020 int literal_index = iterator.Next();
15021 Object* literal_value = LiteralArray()->get(literal_index);
15022 os <<
"{literal_id=" << literal_index <<
" (" << Brief(literal_value)
15027 case Translation::DUPLICATED_OBJECT: {
15028 int object_index = iterator.Next();
15029 os <<
"{object_index=" << object_index <<
"}";
15033 case Translation::ARGUMENTS_ELEMENTS:
15034 case Translation::ARGUMENTS_LENGTH: {
15035 CreateArgumentsType arguments_type =
15036 static_cast<CreateArgumentsType
>(iterator.Next());
15037 os <<
"{arguments_type=" << arguments_type <<
"}";
15041 case Translation::CAPTURED_OBJECT: {
15042 int args_length = iterator.Next();
15043 os <<
"{length=" << args_length <<
"}";
15047 case Translation::UPDATE_FEEDBACK: {
15048 int literal_index = iterator.Next();
15049 FeedbackSlot slot(iterator.Next());
15050 os <<
"{feedback={vector_index=" << literal_index <<
", slot=" << slot
15060 const char* Code::GetName(Isolate* isolate)
const {
15062 return CodeStub::MajorName(CodeStub::GetMajorKey(*
this));
15063 }
else if (kind() == BYTECODE_HANDLER) {
15064 return isolate->interpreter()->LookupNameOfBytecodeHandler(*
this);
15068 return isolate->builtins()->Lookup(raw_instruction_start());
15074 inline void DisassembleCodeRange(Isolate* isolate, std::ostream& os, Code code,
15075 Address begin,
size_t size,
15076 Address current_pc) {
15077 Address end = begin + size;
15080 AllowHandleAllocation allow_handles;
15081 DisallowHeapAllocation no_gc;
15082 HandleScope handle_scope(isolate);
15083 Disassembler::Decode(isolate, &os, reinterpret_cast<byte*>(begin),
15084 reinterpret_cast<byte*>(end),
15085 CodeReference(handle(code, isolate)), current_pc);
15090 void Code::Disassemble(
const char* name, std::ostream& os, Address current_pc) {
15091 Isolate* isolate = GetIsolate();
15092 os <<
"kind = " << Kind2String(kind()) <<
"\n";
15094 const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(*
this));
15095 os <<
"major_key = " << (n ==
nullptr ?
"null" : n) <<
"\n";
15096 os <<
"minor_key = " << CodeStub::MinorKeyFromKey(this->stub_key()) <<
"\n";
15098 if (name ==
nullptr) {
15099 name = GetName(isolate);
15101 if ((name !=
nullptr) && (name[0] !=
'\0')) {
15102 os <<
"name = " << name <<
"\n";
15104 if (kind() == OPTIMIZED_FUNCTION) {
15105 os <<
"stack_slots = " << stack_slots() <<
"\n";
15107 os <<
"compiler = " << (is_turbofanned() ?
"turbofan" :
"unknown") <<
"\n";
15108 os <<
"address = " <<
static_cast<const void*
>(
this) <<
"\n\n";
15110 if (is_off_heap_trampoline()) {
15111 int trampoline_size = raw_instruction_size();
15112 os <<
"Trampoline (size = " << trampoline_size <<
")\n";
15113 DisassembleCodeRange(isolate, os, *
this, raw_instruction_start(),
15114 trampoline_size, current_pc);
15119 int size = InstructionSize();
15120 int safepoint_offset =
15121 has_safepoint_info() ? safepoint_table_offset() : size;
15122 int constant_pool_offset = this->constant_pool_offset();
15123 int handler_offset = handler_table_offset() ? handler_table_offset() : size;
15127 Min(handler_offset, Min(safepoint_offset, constant_pool_offset));
15128 os <<
"Instructions (size = " << code_size <<
")\n";
15129 DisassembleCodeRange(isolate, os, *
this, InstructionStart(), code_size,
15132 if (constant_pool_offset < size) {
15133 int constant_pool_size = safepoint_offset - constant_pool_offset;
15134 DCHECK_EQ(constant_pool_size & kPointerAlignmentMask, 0);
15135 os <<
"\nConstant Pool (size = " << constant_pool_size <<
")\n";
15136 Vector<char> buf = Vector<char>::New(50);
15137 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(InstructionStart() +
15138 constant_pool_offset);
15139 for (
int i = 0;
i < constant_pool_size;
i += kPointerSize, ptr++) {
15140 SNPrintF(buf,
"%4d %08" V8PRIxPTR,
i, *ptr);
15141 os << static_cast<const void*>(ptr) <<
" " << buf.start() <<
"\n";
15147 SourcePositionTableIterator it(SourcePositionTable());
15149 os <<
"Source positions:\n pc offset position\n";
15150 for (; !it.done(); it.Advance()) {
15151 os << std::setw(10) << std::hex << it.code_offset() << std::dec
15152 << std::setw(10) << it.source_position().ScriptOffset()
15153 << (it.is_statement() ?
" statement" :
"") <<
"\n";
15158 if (kind() == OPTIMIZED_FUNCTION) {
15159 DeoptimizationData data =
15160 DeoptimizationData::cast(this->deoptimization_data());
15161 data->DeoptimizationDataPrint(os);
15165 if (has_safepoint_info()) {
15166 SafepointTable table(*
this);
15167 os <<
"Safepoints (size = " << table.size() <<
")\n";
15168 for (
unsigned i = 0;
i < table.length();
i++) {
15169 unsigned pc_offset = table.GetPcOffset(
i);
15170 os << reinterpret_cast<const void*>(InstructionStart() + pc_offset)
15172 os << std::setw(6) << std::hex << pc_offset <<
" " << std::setw(4);
15173 int trampoline_pc = table.GetTrampolinePcOffset(
i);
15174 print_pc(os, trampoline_pc);
15175 os << std::dec <<
" ";
15176 table.PrintEntry(
i, os);
15177 os <<
" (sp -> fp) ";
15178 SafepointEntry entry = table.GetEntry(
i);
15179 if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
15180 os << std::setw(6) << entry.deoptimization_index();
15184 if (entry.argument_count() > 0) {
15185 os <<
" argc: " << entry.argument_count();
15192 if (handler_table_offset() > 0) {
15193 HandlerTable table(*
this);
15194 os <<
"Handler Table (size = " << table.NumberOfReturnEntries() <<
")\n";
15195 if (kind() == OPTIMIZED_FUNCTION) {
15196 table.HandlerTableReturnPrint(os);
15201 os <<
"RelocInfo (size = " << relocation_size() <<
")\n";
15202 for (RelocIterator it(*
this); !it.done(); it.next()) {
15203 it.rinfo()->Print(isolate, os);
15207 if (has_unwinding_info()) {
15208 os <<
"UnwindingInfo (size = " << unwinding_info_size() <<
")\n";
15209 EhFrameDisassembler eh_frame_disassembler(
15210 reinterpret_cast<byte*>(unwinding_info_start()),
15211 reinterpret_cast<byte*>(unwinding_info_end()));
15212 eh_frame_disassembler.DisassembleToStream(os);
15216 #endif // ENABLE_DISASSEMBLER 15218 void BytecodeArray::Disassemble(std::ostream& os) {
15219 DisallowHeapAllocation no_gc;
15221 os <<
"Parameter count " << parameter_count() <<
"\n";
15222 os <<
"Frame size " << frame_size() <<
"\n";
15224 Address base_address = GetFirstBytecodeAddress();
15225 SourcePositionTableIterator source_positions(SourcePositionTable());
15229 BytecodeArray handle_storage = *
this;
15230 Handle<BytecodeArray> handle(reinterpret_cast<Address*>(&handle_storage));
15231 interpreter::BytecodeArrayIterator iterator(handle);
15232 while (!iterator.done()) {
15233 if (!source_positions.done() &&
15234 iterator.current_offset() == source_positions.code_offset()) {
15235 os << std::setw(5) << source_positions.source_position().ScriptOffset();
15236 os << (source_positions.is_statement() ?
" S> " :
" E> ");
15237 source_positions.Advance();
15241 Address current_address = base_address + iterator.current_offset();
15242 os << reinterpret_cast<const void*>(current_address) <<
" @ " 15243 << std::setw(4) << iterator.current_offset() <<
" : ";
15244 interpreter::BytecodeDecoder::Decode(
15245 os, reinterpret_cast<byte*>(current_address), parameter_count());
15246 if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
15247 Address jump_target = base_address + iterator.GetJumpTargetOffset();
15248 os <<
" (" <<
reinterpret_cast<void*
>(jump_target) <<
" @ " 15249 << iterator.GetJumpTargetOffset() <<
")";
15251 if (interpreter::Bytecodes::IsSwitch(iterator.current_bytecode())) {
15253 bool first_entry =
true;
15254 for (
const auto& entry : iterator.GetJumpTableTargetOffsets()) {
15256 first_entry =
false;
15260 os <<
" " << entry.case_value <<
": @" << entry.target_offset;
15265 iterator.Advance();
15268 os <<
"Constant pool (size = " << constant_pool()->length() <<
")\n";
15269 #ifdef OBJECT_PRINT 15270 if (constant_pool()->length() > 0) {
15271 constant_pool()->Print();
15275 os <<
"Handler Table (size = " << handler_table()->length() <<
")\n";
15276 #ifdef ENABLE_DISASSEMBLER 15277 if (handler_table()->length() > 0) {
15278 HandlerTable table(*
this);
15279 table.HandlerTableRangePrint(os);
15284 void BytecodeArray::CopyBytecodesTo(BytecodeArray to) {
15285 BytecodeArray from = *
this;
15286 DCHECK_EQ(from->length(), to->length());
15287 CopyBytes(reinterpret_cast<byte*>(to->GetFirstBytecodeAddress()),
15288 reinterpret_cast<byte*>(from->GetFirstBytecodeAddress()),
15292 void BytecodeArray::MakeOlder() {
15295 Address age_addr = address() + kBytecodeAgeOffset;
15296 DCHECK_LE((age_addr & ~kPointerAlignmentMask) + kPointerSize,
15297 address() + Size());
15298 Age age = bytecode_age();
15299 if (age < kLastBytecodeAge) {
15300 base::AsAtomic8::Release_CompareAndSwap(reinterpret_cast<byte*>(age_addr),
15304 DCHECK_GE(bytecode_age(), kFirstBytecodeAge);
15305 DCHECK_LE(bytecode_age(), kLastBytecodeAge);
15308 bool BytecodeArray::IsOld()
const {
15309 return bytecode_age() >= kIsOldBytecodeAge;
15313 void JSArray::Initialize(Handle<JSArray> array,
int capacity,
int length) {
15314 DCHECK_GE(capacity, 0);
15315 array->GetIsolate()->factory()->NewJSArrayStorage(
15316 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
15319 void JSArray::SetLength(Handle<JSArray> array,
uint32_t new_length) {
15321 DCHECK(array->AllowsSetLength());
15322 if (array->SetLengthWouldNormalize(new_length)) {
15323 JSObject::NormalizeElements(array);
15325 array->GetElementsAccessor()->SetLength(array, new_length);
15328 DependentCode* DependentCode::GetDependentCode(Handle<HeapObject>
object) {
15329 if (object->IsMap()) {
15330 return Handle<Map>::cast(
object)->dependent_code();
15331 }
else if (object->IsPropertyCell()) {
15332 return Handle<PropertyCell>::cast(
object)->dependent_code();
15333 }
else if (object->IsAllocationSite()) {
15334 return Handle<AllocationSite>::cast(
object)->dependent_code();
15339 void DependentCode::SetDependentCode(Handle<HeapObject>
object,
15340 Handle<DependentCode> dep) {
15341 if (object->IsMap()) {
15342 Handle<Map>::cast(
object)->set_dependent_code(*dep);
15343 }
else if (object->IsPropertyCell()) {
15344 Handle<PropertyCell>::cast(
object)->set_dependent_code(*dep);
15345 }
else if (object->IsAllocationSite()) {
15346 Handle<AllocationSite>::cast(
object)->set_dependent_code(*dep);
15352 void DependentCode::InstallDependency(Isolate* isolate,
15353 const MaybeObjectHandle& code,
15354 Handle<HeapObject>
object,
15355 DependencyGroup group) {
15356 Handle<DependentCode> old_deps(DependentCode::GetDependentCode(
object),
15358 Handle<DependentCode> new_deps =
15359 InsertWeakCode(isolate, old_deps, group, code);
15361 if (!new_deps.is_identical_to(old_deps))
15362 DependentCode::SetDependentCode(
object, new_deps);
15365 Handle<DependentCode> DependentCode::InsertWeakCode(
15366 Isolate* isolate, Handle<DependentCode> entries, DependencyGroup group,
15367 const MaybeObjectHandle& code) {
15368 if (entries->length() == 0 || entries->group() > group) {
15370 return DependentCode::New(isolate, group, code, entries);
15372 if (entries->group() < group) {
15374 Handle<DependentCode> old_next(entries->next_link(), isolate);
15375 Handle<DependentCode> new_next =
15376 InsertWeakCode(isolate, old_next, group, code);
15377 if (!old_next.is_identical_to(new_next)) {
15378 entries->set_next_link(*new_next);
15382 DCHECK_EQ(group, entries->group());
15383 int count = entries->count();
15385 for (
int i = 0;
i < count;
i++) {
15386 if (entries->object_at(
i) == *code)
return entries;
15388 if (entries->length() < kCodesStartIndex + count + 1) {
15389 entries = EnsureSpace(isolate, entries);
15391 count = entries->count();
15393 entries->set_object_at(count, *code);
15394 entries->set_count(count + 1);
15398 Handle<DependentCode> DependentCode::New(Isolate* isolate,
15399 DependencyGroup group,
15400 const MaybeObjectHandle&
object,
15401 Handle<DependentCode> next) {
15402 Handle<DependentCode> result = Handle<DependentCode>::cast(
15403 isolate->factory()->NewWeakFixedArray(kCodesStartIndex + 1, TENURED));
15404 result->set_next_link(*next);
15405 result->set_flags(GroupField::encode(group) | CountField::encode(1));
15406 result->set_object_at(0, *
object);
15410 Handle<DependentCode> DependentCode::EnsureSpace(
15411 Isolate* isolate, Handle<DependentCode> entries) {
15412 if (entries->Compact())
return entries;
15413 int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
15414 int grow_by = capacity - entries->length();
15415 return Handle<DependentCode>::cast(
15416 isolate->factory()->CopyWeakFixedArrayAndGrow(entries, grow_by, TENURED));
15420 bool DependentCode::Compact() {
15421 int old_count = count();
15423 for (
int i = 0;
i < old_count;
i++) {
15424 MaybeObject obj = object_at(
i);
15425 if (!obj->IsCleared()) {
15426 if (
i != new_count) {
15427 copy(
i, new_count);
15432 set_count(new_count);
15433 for (
int i = new_count;
i < old_count;
i++) {
15436 return new_count < old_count;
15439 bool DependentCode::MarkCodeForDeoptimization(
15441 DependentCode::DependencyGroup group) {
15442 if (this->length() == 0 || this->group() > group) {
15446 if (this->group() < group) {
15448 return next_link()->MarkCodeForDeoptimization(isolate, group);
15450 DCHECK_EQ(group, this->group());
15451 DisallowHeapAllocation no_allocation_scope;
15453 bool marked =
false;
15454 int count = this->count();
15455 for (
int i = 0;
i < count;
i++) {
15456 MaybeObject obj = object_at(
i);
15457 if (obj->IsCleared())
continue;
15458 Code code = Code::cast(obj->GetHeapObjectAssumeWeak());
15459 if (!code->marked_for_deoptimization()) {
15460 code->SetMarkedForDeoptimization(DependencyGroupName(group));
15464 for (
int i = 0;
i < count;
i++) {
15472 void DependentCode::DeoptimizeDependentCodeGroup(
15474 DependentCode::DependencyGroup group) {
15475 DisallowHeapAllocation no_allocation_scope;
15476 bool marked = MarkCodeForDeoptimization(isolate, group);
15478 DCHECK(AllowCodeDependencyChange::IsAllowed());
15479 Deoptimizer::DeoptimizeMarkedCode(isolate);
15483 void Code::SetMarkedForDeoptimization(
const char* reason) {
15484 set_marked_for_deoptimization(
true);
15485 if (FLAG_trace_deopt &&
15486 (deoptimization_data() != GetReadOnlyRoots().empty_fixed_array())) {
15487 DeoptimizationData deopt_data =
15488 DeoptimizationData::cast(deoptimization_data());
15489 CodeTracer::Scope scope(GetHeap()->isolate()->GetCodeTracer());
15490 PrintF(scope.file(),
15491 "[marking dependent code " V8PRIxPTR_FMT
15492 " (opt #%d) for deoptimization, reason: %s]\n",
15493 ptr(), deopt_data->OptimizationId()->value(), reason);
15498 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
15500 case kTransitionGroup:
15501 return "transition";
15502 case kPrototypeCheckGroup:
15503 return "prototype-check";
15504 case kPropertyCellChangedGroup:
15505 return "property-cell-changed";
15506 case kFieldOwnerGroup:
15507 return "field-owner";
15508 case kInitialMapChangedGroup:
15509 return "initial-map-changed";
15510 case kAllocationSiteTenuringChangedGroup:
15511 return "allocation-site-tenuring-changed";
15512 case kAllocationSiteTransitionChangedGroup:
15513 return "allocation-site-transition-changed";
15518 Handle<Map> Map::TransitionToPrototype(Isolate* isolate, Handle<Map> map,
15519 Handle<Object> prototype) {
15520 Handle<Map> new_map =
15521 TransitionsAccessor(isolate, map).GetPrototypeTransition(prototype);
15522 if (new_map.is_null()) {
15523 new_map = Copy(isolate, map,
"TransitionToPrototype");
15524 TransitionsAccessor(isolate, map)
15525 .PutPrototypeTransition(prototype, new_map);
15526 Map::SetPrototype(isolate, new_map, prototype);
15532 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver>
object,
15533 Handle<Object> value,
bool from_javascript,
15534 ShouldThrow should_throw) {
15535 if (object->IsJSProxy()) {
15536 return JSProxy::SetPrototype(Handle<JSProxy>::cast(
object), value,
15537 from_javascript, should_throw);
15539 return JSObject::SetPrototype(Handle<JSObject>::cast(
object), value,
15540 from_javascript, should_throw);
15546 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
15547 bool from_javascript,
15548 ShouldThrow should_throw) {
15549 Isolate* isolate = proxy->GetIsolate();
15550 STACK_CHECK(isolate, Nothing<bool>());
15551 Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
15553 DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
15555 Handle<Object> handler(proxy->handler(), isolate);
15558 if (proxy->IsRevoked()) {
15559 isolate->Throw(*isolate->factory()->NewTypeError(
15560 MessageTemplate::kProxyRevoked, trap_name));
15561 return Nothing<bool>();
15564 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
15566 Handle<Object> trap;
15567 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15569 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
15572 if (trap->IsUndefined(isolate)) {
15573 return JSReceiver::SetPrototype(target, value, from_javascript,
15577 Handle<Object> argv[] = {target, value};
15578 Handle<Object> trap_result;
15579 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15580 isolate, trap_result,
15581 Execution::Call(isolate, trap, handler, arraysize(argv), argv),
15583 bool bool_trap_result = trap_result->BooleanValue(isolate);
15585 if (!bool_trap_result) {
15587 isolate, should_throw,
15588 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15591 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
15592 if (is_extensible.IsNothing())
return Nothing<bool>();
15594 if (is_extensible.FromJust()) {
15595 if (bool_trap_result)
return Just(
true);
15597 isolate, should_throw,
15598 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15601 Handle<Object> target_proto;
15602 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
15603 JSReceiver::GetPrototype(isolate, target),
15606 if (bool_trap_result && !value->SameValue(*target_proto)) {
15607 isolate->Throw(*isolate->factory()->NewTypeError(
15608 MessageTemplate::kProxySetPrototypeOfNonExtensible));
15609 return Nothing<bool>();
15616 Maybe<bool> JSObject::SetPrototype(Handle<JSObject>
object,
15617 Handle<Object> value,
bool from_javascript,
15618 ShouldThrow should_throw) {
15619 Isolate* isolate =
object->GetIsolate();
15622 int size =
object->Size();
15625 if (from_javascript) {
15626 if (object->IsAccessCheckNeeded() &&
15627 !isolate->MayAccess(handle(isolate->context(), isolate),
object)) {
15628 isolate->ReportFailedAccessCheck(
object);
15629 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
15630 RETURN_FAILURE(isolate, should_throw,
15631 NewTypeError(MessageTemplate::kNoAccess));
15634 DCHECK(!object->IsAccessCheckNeeded());
15639 if (!value->IsJSReceiver() && !value->IsNull(isolate))
return Just(
true);
15641 bool all_extensible =
object->map()->is_extensible();
15642 Handle<JSObject> real_receiver = object;
15643 if (from_javascript) {
15646 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
15647 PrototypeIterator::END_AT_NON_HIDDEN);
15648 while (!iter.IsAtEnd()) {
15651 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
15653 all_extensible = all_extensible && real_receiver->map()->is_extensible();
15656 Handle<Map> map(real_receiver->map(), isolate);
15659 if (map->prototype() == *value)
return Just(
true);
15661 bool immutable_proto = map->is_immutable_proto();
15662 if (immutable_proto) {
15664 isolate, should_throw,
15665 NewTypeError(MessageTemplate::kImmutablePrototypeSet,
object));
15676 if (!all_extensible) {
15677 RETURN_FAILURE(isolate, should_throw,
15678 NewTypeError(MessageTemplate::kNonExtensibleProto,
object));
15684 if (value->IsJSReceiver()) {
15685 for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
15687 !iter.IsAtEnd(); iter.Advance()) {
15688 if (iter.GetCurrent<JSReceiver>() == *object) {
15690 RETURN_FAILURE(isolate, should_throw,
15691 NewTypeError(MessageTemplate::kCyclicProto));
15698 isolate->UpdateNoElementsProtectorOnSetPrototype(real_receiver);
15700 Handle<Map> new_map = Map::TransitionToPrototype(isolate, map, value);
15701 DCHECK(new_map->prototype() == *value);
15702 JSObject::MigrateToMap(real_receiver, new_map);
15704 DCHECK(size == object->Size());
15709 void JSObject::SetImmutableProto(Handle<JSObject>
object) {
15710 DCHECK(!object->IsAccessCheckNeeded());
15711 Handle<Map> map(object->map(),
object->GetIsolate());
15714 if (map->is_immutable_proto())
return;
15716 Handle<Map> new_map =
15717 Map::TransitionToImmutableProto(object->GetIsolate(), map);
15718 object->synchronized_set_map(*new_map);
15721 void JSObject::EnsureCanContainElements(Handle<JSObject>
object,
15725 EnsureElementsMode mode) {
15729 return EnsureCanContainElements(
15730 object, args->slot_at(first_arg + arg_count - 1), arg_count, mode);
15734 ElementsAccessor* JSObject::GetElementsAccessor() {
15735 return ElementsAccessor::ForKind(GetElementsKind());
15738 void JSObject::ValidateElements(JSObject*
object) {
15739 #ifdef ENABLE_SLOW_DCHECKS 15740 if (FLAG_enable_slow_asserts) {
15741 object->GetElementsAccessor()->Validate(
object);
15747 static bool ShouldConvertToSlowElements(JSObject*
object,
uint32_t capacity,
15750 STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
15751 JSObject::kMaxUncheckedFastElementsLength);
15752 if (index < capacity) {
15753 *new_capacity = capacity;
15756 if (index - capacity >= JSObject::kMaxGap)
return true;
15757 *new_capacity = JSObject::NewElementsCapacity(index + 1);
15758 DCHECK_LT(index, *new_capacity);
15759 if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
15760 (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
15761 Heap::InNewSpace(
object))) {
15766 int used_elements =
object->GetFastElementsUsage();
15767 uint32_t size_threshold = NumberDictionary::kPreferFastElementsSizeFactor *
15768 NumberDictionary::ComputeCapacity(used_elements) *
15769 NumberDictionary::kEntrySize;
15770 return size_threshold <= *new_capacity;
15774 bool JSObject::WouldConvertToSlowElements(
uint32_t index) {
15775 if (!HasFastElements())
return false;
15778 return ShouldConvertToSlowElements(
this, capacity, index, &new_capacity);
15782 static ElementsKind BestFittingFastElementsKind(JSObject*
object) {
15783 if (!object->map()->CanHaveFastTransitionableElementsKind()) {
15784 return HOLEY_ELEMENTS;
15786 if (object->HasSloppyArgumentsElements()) {
15787 return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
15789 if (object->HasStringWrapperElements()) {
15790 return FAST_STRING_WRAPPER_ELEMENTS;
15792 DCHECK(object->HasDictionaryElements());
15793 NumberDictionary dictionary =
object->element_dictionary();
15794 ElementsKind kind = HOLEY_SMI_ELEMENTS;
15795 for (
int i = 0;
i < dictionary->Capacity();
i++) {
15796 Object* key = dictionary->KeyAt(
i);
15797 if (key->IsNumber()) {
15798 Object* value = dictionary->ValueAt(
i);
15799 if (!value->IsNumber())
return HOLEY_ELEMENTS;
15800 if (!value->IsSmi()) {
15801 if (!FLAG_unbox_double_arrays)
return HOLEY_ELEMENTS;
15802 kind = HOLEY_DOUBLE_ELEMENTS;
15809 static bool ShouldConvertToFastElements(JSObject*
object,
15810 NumberDictionary dictionary,
15815 if (dictionary->requires_slow_elements())
return false;
15818 if (index >= static_cast<uint32_t>(Smi::kMaxValue))
return false;
15820 if (object->IsJSArray()) {
15821 Object* length = JSArray::cast(
object)->length();
15822 if (!length->IsSmi())
return false;
15823 *new_capacity =
static_cast<uint32_t>(Smi::ToInt(length));
15824 }
else if (object->IsJSSloppyArgumentsObject()) {
15827 *new_capacity = dictionary->max_number_key() + 1;
15829 *new_capacity = Max(index + 1, *new_capacity);
15831 uint32_t dictionary_size =
static_cast<uint32_t>(dictionary->Capacity()) *
15832 NumberDictionary::kEntrySize;
15835 return 2 * dictionary_size >= *new_capacity;
15839 void JSObject::AddDataElement(Handle<JSObject>
object,
uint32_t index,
15840 Handle<Object> value,
15841 PropertyAttributes attributes) {
15842 DCHECK(object->map()->is_extensible());
15844 Isolate* isolate =
object->GetIsolate();
15849 if (object->IsJSArray()) {
15850 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
15853 ElementsKind kind =
object->GetElementsKind();
15854 FixedArrayBase elements =
object->elements();
15855 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15856 if (IsSloppyArgumentsElementsKind(kind)) {
15857 elements = SloppyArgumentsElements::cast(elements)->arguments();
15858 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15859 }
else if (IsStringWrapperElementsKind(kind)) {
15860 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
15863 if (attributes != NONE) {
15864 kind = dictionary_kind;
15865 }
else if (elements->IsNumberDictionary()) {
15866 kind = ShouldConvertToFastElements(
15867 *
object, NumberDictionary::cast(elements), index, &new_capacity)
15868 ? BestFittingFastElementsKind(*
object)
15870 }
else if (ShouldConvertToSlowElements(
15871 *
object, static_cast<uint32_t>(elements->length()), index,
15873 kind = dictionary_kind;
15876 ElementsKind to = value->OptimalElementsKind();
15877 if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
15878 to = GetHoleyElementsKind(to);
15879 kind = GetHoleyElementsKind(kind);
15881 to = GetMoreGeneralElementsKind(kind, to);
15882 ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
15883 accessor->Add(
object, index, value, attributes, new_capacity);
15885 if (object->IsJSArray() && index >= old_length) {
15886 Handle<Object> new_length =
15887 isolate->factory()->NewNumberFromUint(index + 1);
15888 JSArray::cast(*object)->set_length(*new_length);
15893 bool JSArray::SetLengthWouldNormalize(
uint32_t new_length) {
15894 if (!HasFastElements())
return false;
15897 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
15898 ShouldConvertToSlowElements(
this, capacity, new_length - 1,
15903 const double AllocationSite::kPretenureRatio = 0.85;
15906 void AllocationSite::ResetPretenureDecision() {
15907 set_pretenure_decision(kUndecided);
15908 set_memento_found_count(0);
15909 set_memento_create_count(0);
15912 PretenureFlag AllocationSite::GetPretenureMode()
const {
15913 PretenureDecision mode = pretenure_decision();
15915 return mode == kTenure ? TENURED : NOT_TENURED;
15918 bool AllocationSite::IsNested() {
15919 DCHECK(FLAG_trace_track_allocation_sites);
15920 Object* current = boilerplate()->GetHeap()->allocation_sites_list();
15921 while (current->IsAllocationSite()) {
15922 AllocationSite* current_site = AllocationSite::cast(current);
15923 if (current_site->nested_site() ==
this) {
15926 current = current_site->weak_next();
15931 template <AllocationSiteUpdateMode update_or_check>
15932 bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
15933 ElementsKind to_kind) {
15934 Isolate* isolate = site->GetIsolate();
15935 bool result =
false;
15937 if (site->PointsToLiteral() && site->boilerplate()->IsJSArray()) {
15938 Handle<JSArray> boilerplate(JSArray::cast(site->boilerplate()), isolate);
15939 ElementsKind kind = boilerplate->GetElementsKind();
15941 if (IsHoleyElementsKind(kind)) {
15942 to_kind = GetHoleyElementsKind(to_kind);
15944 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15948 CHECK(boilerplate->length()->ToArrayLength(&length));
15949 if (length <= kMaximumArrayBytesToPretransition) {
15950 if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
15953 if (FLAG_trace_track_allocation_sites) {
15954 bool is_nested = site->IsNested();
15955 PrintF(
"AllocationSite: JSArray %p boilerplate %supdated %s->%s\n",
15956 reinterpret_cast<void*>(*site), is_nested ?
"(nested)" :
" ",
15957 ElementsKindToString(kind), ElementsKindToString(to_kind));
15959 JSObject::TransitionElementsKind(boilerplate, to_kind);
15960 site->dependent_code()->DeoptimizeDependentCodeGroup(
15961 isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15967 ElementsKind kind = site->GetElementsKind();
15969 if (IsHoleyElementsKind(kind)) {
15970 to_kind = GetHoleyElementsKind(to_kind);
15972 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15973 if (update_or_check == AllocationSiteUpdateMode::kCheckOnly)
return true;
15974 if (FLAG_trace_track_allocation_sites) {
15975 PrintF(
"AllocationSite: JSArray %p site updated %s->%s\n",
15976 reinterpret_cast<void*>(*site),
15977 ElementsKindToString(kind),
15978 ElementsKindToString(to_kind));
15980 site->SetElementsKind(to_kind);
15981 site->dependent_code()->DeoptimizeDependentCodeGroup(
15982 isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15989 bool AllocationSite::ShouldTrack(ElementsKind from, ElementsKind to) {
15990 return IsSmiElementsKind(from) &&
15991 IsMoreGeneralElementsKindTransition(from, to);
15994 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
15995 switch (decision) {
15996 case kUndecided:
return "undecided";
15997 case kDontTenure:
return "don't tenure";
15998 case kMaybeTenure:
return "maybe tenure";
15999 case kTenure:
return "tenure";
16000 case kZombie:
return "zombie";
16001 default: UNREACHABLE();
16006 template <AllocationSiteUpdateMode update_or_check>
16007 bool JSObject::UpdateAllocationSite(Handle<JSObject>
object,
16008 ElementsKind to_kind) {
16009 if (!object->IsJSArray())
return false;
16011 if (!Heap::InNewSpace(*
object))
return false;
16013 Handle<AllocationSite> site;
16015 DisallowHeapAllocation no_allocation;
16017 Heap* heap =
object->GetHeap();
16018 AllocationMemento* memento =
16019 heap->FindAllocationMemento<Heap::kForRuntime>(
object->map(), *object);
16020 if (memento ==
nullptr)
return false;
16023 site = handle(memento->GetAllocationSite(), heap->isolate());
16025 return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
16030 JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
16031 Handle<JSObject> object, ElementsKind to_kind);
16033 template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
16034 Handle<JSObject> object, ElementsKind to_kind);
16036 void JSObject::TransitionElementsKind(Handle<JSObject>
object,
16037 ElementsKind to_kind) {
16038 ElementsKind from_kind =
object->GetElementsKind();
16040 if (IsHoleyElementsKind(from_kind)) {
16041 to_kind = GetHoleyElementsKind(to_kind);
16044 if (from_kind == to_kind)
return;
16047 DCHECK(IsFastElementsKind(from_kind));
16048 DCHECK(IsFastElementsKind(to_kind));
16049 DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
16051 UpdateAllocationSite(
object, to_kind);
16052 if (object->elements() ==
object->GetReadOnlyRoots().empty_fixed_array() ||
16053 IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
16056 Handle<Map> new_map = GetElementsTransitionMap(
object, to_kind);
16057 MigrateToMap(
object, new_map);
16058 if (FLAG_trace_elements_transitions) {
16059 Handle<FixedArrayBase> elms(object->elements(),
object->GetIsolate());
16060 PrintElementsTransition(stdout,
object, from_kind, elms, to_kind, elms);
16063 DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
16064 (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
16066 ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(
object, c);
16071 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
16072 Map map = array->map();
16075 if (!map->is_dictionary_map()) {
16076 DCHECK(map->instance_descriptors()->GetKey(0) ==
16077 array->GetReadOnlyRoots().length_string());
16078 return map->instance_descriptors()->GetDetails(0).IsReadOnly();
16081 Isolate* isolate = array->GetIsolate();
16082 LookupIterator it(array, isolate->factory()->length_string(), array,
16083 LookupIterator::OWN_SKIP_INTERCEPTOR);
16084 CHECK_EQ(LookupIterator::ACCESSOR, it.state());
16085 return it.IsReadOnly();
16089 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
16092 CHECK(array->length()->ToArrayLength(&length));
16093 if (length <= index)
return HasReadOnlyLength(array);
16097 template <
typename BackingStore>
16098 static int HoleyElementsUsage(JSObject*
object, BackingStore store) {
16099 Isolate* isolate =
object->GetIsolate();
16100 int limit =
object->IsJSArray() ? Smi::ToInt(JSArray::cast(
object)->length())
16103 for (
int i = 0;
i < limit; ++
i) {
16104 if (!store->is_the_hole(isolate,
i)) ++used;
16109 int JSObject::GetFastElementsUsage() {
16110 FixedArrayBase store = elements();
16111 switch (GetElementsKind()) {
16112 case PACKED_SMI_ELEMENTS:
16113 case PACKED_DOUBLE_ELEMENTS:
16114 case PACKED_ELEMENTS:
16115 return IsJSArray() ? Smi::ToInt(JSArray::cast(
this)->length())
16117 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16118 store = SloppyArgumentsElements::cast(store)->arguments();
16120 case HOLEY_SMI_ELEMENTS:
16121 case HOLEY_ELEMENTS:
16122 case FAST_STRING_WRAPPER_ELEMENTS:
16123 return HoleyElementsUsage(
this, FixedArray::cast(store));
16124 case HOLEY_DOUBLE_ELEMENTS:
16125 if (elements()->length() == 0)
return 0;
16126 return HoleyElementsUsage(
this, FixedDoubleArray::cast(store));
16128 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
16129 case SLOW_STRING_WRAPPER_ELEMENTS:
16130 case DICTIONARY_ELEMENTS:
16132 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS: 16134 TYPED_ARRAYS(TYPED_ARRAY_CASE)
16135 #undef TYPED_ARRAY_CASE 16147 #ifdef OBJECT_PRINT 16148 template <
typename Derived,
typename Shape>
16149 void Dictionary<Derived, Shape>::Print(std::ostream& os) {
16150 DisallowHeapAllocation no_gc;
16151 ReadOnlyRoots roots = this->GetReadOnlyRoots();
16152 Derived dictionary = Derived::cast(*
this);
16153 int capacity = dictionary->Capacity();
16154 for (
int i = 0;
i < capacity;
i++) {
16155 Object* k = dictionary->KeyAt(
i);
16156 if (!dictionary->ToKey(roots,
i, &k))
continue;
16158 if (k->IsString()) {
16159 String::cast(k)->StringPrint(os);
16163 os <<
": " << Brief(dictionary->ValueAt(
i)) <<
" ";
16164 dictionary->DetailsAt(
i).PrintAsSlowTo(os);
16167 template <
typename Derived,
typename Shape>
16168 void Dictionary<Derived, Shape>::Print() {
16176 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
16178 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
16179 return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
16182 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject>
object,
16183 Handle<Name> name) {
16184 LookupIterator it = LookupIterator::PropertyOrElement(
16185 object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16186 return HasProperty(&it);
16190 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject>
object,
16192 Isolate* isolate =
object->GetIsolate();
16193 LookupIterator it(isolate,
object, index,
object,
16194 LookupIterator::OWN_SKIP_INTERCEPTOR);
16195 return HasProperty(&it);
16199 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject>
object,
16200 Handle<Name> name) {
16201 LookupIterator it = LookupIterator::PropertyOrElement(
16202 object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16203 Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
16204 return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
16208 int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
16209 return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
16210 ElementsKindToShiftSize(kind));
16213 bool FixedArrayBase::IsCowArray()
const {
16214 return map() == GetReadOnlyRoots().fixed_cow_array_map();
16217 bool JSObject::IsApiWrapper() {
16221 auto instance_type = map()->instance_type();
16222 return instance_type == JS_API_OBJECT_TYPE ||
16223 instance_type == JS_ARRAY_BUFFER_TYPE ||
16224 instance_type == JS_DATA_VIEW_TYPE ||
16225 instance_type == JS_SPECIAL_API_OBJECT_TYPE ||
16226 instance_type == JS_TYPED_ARRAY_TYPE;
16229 bool JSObject::IsDroppableApiWrapper() {
16230 auto instance_type = map()->instance_type();
16231 return instance_type == JS_API_OBJECT_TYPE ||
16232 instance_type == JS_SPECIAL_API_OBJECT_TYPE;
16235 const char* Symbol::PrivateSymbolToName()
const {
16236 ReadOnlyRoots roots = GetReadOnlyRoots();
16237 #define SYMBOL_CHECK_AND_PRINT(_, name) \ 16238 if (*this == roots.name()) return #name; 16239 PRIVATE_SYMBOL_LIST_GENERATOR(SYMBOL_CHECK_AND_PRINT, )
16240 #undef SYMBOL_CHECK_AND_PRINT 16245 void Symbol::SymbolShortPrint(std::ostream& os) {
16247 if (!name()->IsUndefined()) {
16249 HeapStringAllocator allocator;
16250 StringStream accumulator(&allocator);
16251 String::cast(name())->StringShortPrint(&accumulator,
false);
16252 os << accumulator.ToCString().get();
16254 os <<
" (" << PrivateSymbolToName() <<
")";
16274 LanguageMode language_mode,
int position)
16275 :
HashTableKey(CompilationCacheShape::StringSharedHash(
16276 *source, *shared, language_mode, position)),
16279 language_mode_(language_mode),
16280 position_(position) {}
16282 bool IsMatch(
Object* other)
override {
16284 if (!other->IsFixedArray()) {
16285 DCHECK(other->IsNumber());
16287 return Hash() == other_hash;
16289 FixedArray other_array = FixedArray::cast(other);
16291 if (shared != *shared_)
return false;
16292 int language_unchecked = Smi::ToInt(other_array->get(2));
16293 DCHECK(is_valid_language_mode(language_unchecked));
16294 LanguageMode language_mode =
static_cast<LanguageMode
>(language_unchecked);
16295 if (language_mode != language_mode_)
return false;
16296 int position = Smi::ToInt(other_array->get(3));
16297 if (position != position_)
return false;
16298 String source = String::cast(other_array->get(1));
16299 return source->Equals(*source_);
16304 array->set(0, *shared_);
16305 array->set(1, *source_);
16306 array->set(2, Smi::FromEnum(language_mode_));
16307 array->set(3, Smi::FromInt(position_));
16308 array->set_map(
ReadOnlyRoots(isolate).fixed_cow_array_map());
16315 LanguageMode language_mode_;
16320 int value = flags() & kStatusMask;
16321 DCHECK(value == 0 || value == 1 || value == 2);
16326 int value = flags() & ~kStatusMask;
16327 set_flags(value | status);
16333 case v8::Promise::kFulfilled:
16335 case v8::Promise::kPending:
16337 case v8::Promise::kRejected:
16343 int JSPromise::async_task_id()
const {
16344 return AsyncTaskIdField::decode(flags());
16347 void JSPromise::set_async_task_id(
int id) {
16348 set_flags(AsyncTaskIdField::update(flags(),
id));
16352 Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
16353 Handle<Object> value) {
16354 Isolate*
const isolate = promise->GetIsolate();
16357 DCHECK_EQ(Promise::kPending, promise->status());
16360 Handle<Object> reactions(promise->reactions(), isolate);
16365 promise->set_reactions_or_result(*value);
16368 promise->set_status(Promise::kFulfilled);
16371 return TriggerPromiseReactions(isolate, reactions, value,
16372 PromiseReaction::kFulfill);
16376 Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
16377 Handle<Object> reason,
bool debug_event) {
16378 Isolate*
const isolate = promise->GetIsolate();
16380 if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
16381 isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
16382 isolate->factory()->undefined_value());
16385 DCHECK_EQ(Promise::kPending, promise->status());
16388 Handle<Object> reactions(promise->reactions(), isolate);
16393 promise->set_reactions_or_result(*reason);
16396 promise->set_status(Promise::kRejected);
16400 if (!promise->has_handler()) {
16401 isolate->ReportPromiseReject(promise, reason, kPromiseRejectWithNoHandler);
16405 return TriggerPromiseReactions(isolate, reactions, reason,
16406 PromiseReaction::kReject);
16410 MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
16411 Handle<Object> resolution) {
16412 Isolate*
const isolate = promise->GetIsolate();
16414 isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
16415 isolate->factory()->undefined_value());
16418 if (promise.is_identical_to(resolution)) {
16420 Handle<Object> self_resolution_error = isolate->factory()->NewTypeError(
16421 MessageTemplate::kPromiseCyclic, resolution);
16423 return Reject(promise, self_resolution_error);
16427 if (!resolution->IsJSReceiver()) {
16429 return Fulfill(promise, resolution);
16433 MaybeHandle<Object> then;
16434 if (isolate->IsPromiseThenLookupChainIntact(
16435 Handle<JSReceiver>::cast(resolution))) {
16440 then = isolate->promise_then();
16443 JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(resolution),
16444 isolate->factory()->then_string());
16448 Handle<Object> then_action;
16449 if (!then.ToHandle(&then_action)) {
16451 Handle<Object> reason(isolate->pending_exception(), isolate);
16452 isolate->clear_pending_exception();
16453 return Reject(promise, reason,
false);
16458 if (!then_action->IsCallable()) {
16460 return Fulfill(promise, resolution);
16465 Handle<PromiseResolveThenableJobTask> task =
16466 isolate->factory()->NewPromiseResolveThenableJobTask(
16467 promise, Handle<JSReceiver>::cast(then_action),
16468 Handle<JSReceiver>::cast(resolution), isolate->native_context());
16469 if (isolate->debug()->is_active() && resolution->IsJSPromise()) {
16471 Object::SetProperty(isolate, resolution,
16472 isolate->factory()->promise_handled_by_symbol(),
16473 promise, LanguageMode::kStrict)
16476 isolate->EnqueueMicrotask(task);
16479 return isolate->factory()->undefined_value();
16483 Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
16484 Handle<Object> reactions,
16485 Handle<Object> argument,
16486 PromiseReaction::Type type) {
16487 DCHECK(reactions->IsSmi() || reactions->IsPromiseReaction());
16492 DisallowHeapAllocation no_gc;
16493 Object* current = *reactions;
16494 Object* reversed = Smi::kZero;
16495 while (!current->IsSmi()) {
16496 Object* next = PromiseReaction::cast(current)->next();
16497 PromiseReaction::cast(current)->set_next(reversed);
16498 reversed = current;
16501 reactions = handle(reversed, isolate);
16506 while (!reactions->IsSmi()) {
16507 Handle<HeapObject> task = Handle<HeapObject>::cast(reactions);
16508 Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(task);
16509 reactions = handle(reaction->next(), isolate);
16511 STATIC_ASSERT(PromiseReaction::kSize == PromiseReactionJobTask::kSize);
16512 if (type == PromiseReaction::kFulfill) {
16513 task->synchronized_set_map(
16514 ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map());
16515 Handle<PromiseFulfillReactionJobTask>::cast(task)->set_argument(
16517 Handle<PromiseFulfillReactionJobTask>::cast(task)->set_context(
16518 *isolate->native_context());
16519 STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset ==
16520 PromiseFulfillReactionJobTask::kHandlerOffset);
16521 STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
16522 PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset);
16524 DisallowHeapAllocation no_gc;
16525 HeapObject* handler = reaction->reject_handler();
16526 task->synchronized_set_map(
16527 ReadOnlyRoots(isolate).promise_reject_reaction_job_task_map());
16528 Handle<PromiseRejectReactionJobTask>::cast(task)->set_argument(*argument);
16529 Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
16530 *isolate->native_context());
16531 Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(handler);
16532 STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
16533 PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset);
16536 isolate->EnqueueMicrotask(Handle<PromiseReactionJobTask>::cast(task));
16539 return isolate->factory()->undefined_value();
16544 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags,
bool* success) {
16545 JSRegExp::Flags value = JSRegExp::kNone;
16546 int length = flags->length();
16548 if (length > JSRegExp::FlagCount())
return JSRegExp::Flags(0);
16549 for (
int i = 0;
i < length;
i++) {
16550 JSRegExp::Flag flag = JSRegExp::kNone;
16551 switch (flags->Get(
i)) {
16553 flag = JSRegExp::kGlobal;
16556 flag = JSRegExp::kIgnoreCase;
16559 flag = JSRegExp::kMultiline;
16562 flag = JSRegExp::kDotAll;
16565 flag = JSRegExp::kUnicode;
16568 flag = JSRegExp::kSticky;
16571 return JSRegExp::Flags(0);
16574 if (value & flag)
return JSRegExp::Flags(0);
16585 MaybeHandle<JSRegExp> JSRegExp::New(Isolate* isolate, Handle<String> pattern,
16587 Handle<JSFunction> constructor = isolate->regexp_function();
16588 Handle<JSRegExp> regexp =
16589 Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
16591 return JSRegExp::Initialize(regexp, pattern, flags);
16596 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
16597 Isolate*
const isolate = regexp->GetIsolate();
16598 return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
16602 template <
typename Char>
16603 inline int CountRequiredEscapes(Handle<String> source) {
16604 DisallowHeapAllocation no_gc;
16606 Vector<const Char> src = source->GetCharVector<Char>();
16607 for (
int i = 0;
i < src.length();
i++) {
16608 if (src[
i] ==
'\\') {
16611 }
else if (src[
i] ==
'/') {
16620 template <
typename Char,
typename StringType>
16621 inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
16622 Handle<StringType> result) {
16623 DisallowHeapAllocation no_gc;
16624 Vector<const Char> src = source->GetCharVector<Char>();
16625 Vector<Char> dst(result->GetChars(), result->length());
16628 while (s < src.length()) {
16629 if (src[s] ==
'\\') {
16631 dst[d++] = src[s++];
16632 if (s == src.length())
break;
16633 }
else if (src[s] ==
'/') {
16637 dst[d++] = src[s++];
16639 DCHECK_EQ(result->length(), d);
16644 MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
16645 Handle<String> source) {
16646 DCHECK(source->IsFlat());
16647 if (source->length() == 0)
return isolate->factory()->query_colon_string();
16648 bool one_byte = source->IsOneByteRepresentationUnderneath();
16649 int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
16650 : CountRequiredEscapes<uc16>(source);
16651 if (escapes == 0)
return source;
16652 int length = source->length() + escapes;
16654 Handle<SeqOneByteString> result;
16655 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16656 isolate->factory()->NewRawOneByteString(length),
16658 return WriteEscapedRegExpSource<uint8_t>(source, result);
16660 Handle<SeqTwoByteString> result;
16661 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16662 isolate->factory()->NewRawTwoByteString(length),
16664 return WriteEscapedRegExpSource<uc16>(source, result);
16670 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16671 Handle<String> source,
16672 Handle<String> flags_string) {
16673 Isolate* isolate = regexp->GetIsolate();
16674 bool success =
false;
16675 Flags flags = RegExpFlagsFromString(flags_string, &success);
16679 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
16682 return Initialize(regexp, source, flags);
16687 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16688 Handle<String> source, Flags flags) {
16689 Isolate* isolate = regexp->GetIsolate();
16690 Factory* factory = isolate->factory();
16693 if (source->length() == 0) source = factory->query_colon_string();
16695 source = String::Flatten(isolate, source);
16697 Handle<String> escaped_source;
16698 ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
16699 EscapeRegExpSource(isolate, source), JSRegExp);
16701 RETURN_ON_EXCEPTION(
16702 isolate, RegExpImpl::Compile(isolate, regexp, source, flags), JSRegExp);
16704 regexp->set_source(*escaped_source);
16705 regexp->set_flags(Smi::FromInt(flags));
16707 Map map = regexp->map();
16708 Object* constructor = map->GetConstructor();
16709 if (constructor->IsJSFunction() &&
16710 JSFunction::cast(constructor)->initial_map() == map) {
16712 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
16713 SKIP_WRITE_BARRIER);
16716 RETURN_ON_EXCEPTION(
16718 JSReceiver::SetProperty(isolate, regexp, factory->lastIndex_string(),
16719 Handle<Smi>(Smi::zero(), isolate),
16720 LanguageMode::kStrict),
16733 CompilationCacheShape::RegExpHash(*
string, Smi::FromInt(flags))),
16735 flags_(Smi::FromInt(flags)) {}
16741 bool IsMatch(
Object* obj)
override {
16743 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
16744 && (flags_ == val->get(JSRegExp::kFlagsIndex));
16752 return isolate->factory()->NewOneByteInternalizedString(string_, HashField());
16756 return isolate->factory()->NewTwoByteInternalizedString(string_, HashField());
16759 Handle<String> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
16760 return isolate->factory()->NewOneByteInternalizedSubString(
16761 string_, from_, length_, HashField());
16765 bool SeqOneByteSubStringKey::IsMatch(Object*
string) {
16766 DisallowHeapAllocation no_gc;
16767 Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
16768 return String::cast(
string)->IsOneByteEqualTo(chars);
16777 DCHECK(!string->IsInternalizedString());
16778 DCHECK(string->IsFlat());
16781 set_hash_field(string->hash_field());
16784 bool IsMatch(
Object*
string)
override {
16785 return string_->SlowEquals(String::cast(
string));
16791 isolate->factory()->InternalizedStringMapForString(string_);
16793 if (maybe_map.ToHandle(&map)) {
16794 string_->set_map_no_write_barrier(*map);
16795 DCHECK(string_->IsInternalizedString());
16798 if (FLAG_thin_strings) {
16801 if (string_->IsExternalOneByteString()) {
16802 return isolate->factory()
16804 }
else if (string_->IsExternalTwoByteString()) {
16805 return isolate->factory()
16810 return isolate->factory()->NewInternalizedStringImpl(
16811 string_, string_->length(), string_->hash_field());
16818 template <
typename Derived,
typename Shape>
16820 BodyDescriptorBase::IteratePointers(*
this, 0, kElementsStartOffset, v);
16823 template <
typename Derived,
typename Shape>
16824 void HashTable<Derived, Shape>::IterateElements(ObjectVisitor* v) {
16825 BodyDescriptorBase::IteratePointers(*
this, kElementsStartOffset,
16826 kHeaderSize + length() * kPointerSize, v);
16829 template <
typename Derived,
typename Shape>
16830 Handle<Derived> HashTable<Derived, Shape>::New(
16831 Isolate* isolate,
int at_least_space_for, PretenureFlag pretenure,
16832 MinimumCapacity capacity_option) {
16833 DCHECK_LE(0, at_least_space_for);
16834 DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
16835 base::bits::IsPowerOfTwo(at_least_space_for));
16837 int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
16838 ? at_least_space_for
16839 : ComputeCapacity(at_least_space_for);
16840 if (capacity > HashTable::kMaxCapacity) {
16841 isolate->heap()->FatalProcessOutOfMemory(
"invalid table size");
16843 return NewInternal(isolate, capacity, pretenure);
16846 template <
typename Derived,
typename Shape>
16847 Handle<Derived> HashTable<Derived, Shape>::NewInternal(
16848 Isolate* isolate,
int capacity, PretenureFlag pretenure) {
16849 Factory* factory = isolate->factory();
16850 int length = EntryToIndex(capacity);
16851 RootIndex map_root_index = Shape::GetMapRootIndex();
16852 Handle<FixedArray> array =
16853 factory->NewFixedArrayWithMap(map_root_index, length, pretenure);
16854 Handle<Derived> table = Handle<Derived>::cast(array);
16856 table->SetNumberOfElements(0);
16857 table->SetNumberOfDeletedElements(0);
16858 table->SetCapacity(capacity);
16862 template <
typename Derived,
typename Shape>
16863 void HashTable<Derived, Shape>::Rehash(Isolate* isolate, Derived new_table) {
16864 DisallowHeapAllocation no_gc;
16865 WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
16867 DCHECK_LT(NumberOfElements(), new_table->Capacity());
16870 for (
int i = kPrefixStartIndex;
i < kElementsStartIndex;
i++) {
16871 new_table->set(
i,
get(
i), mode);
16875 int capacity = this->Capacity();
16876 ReadOnlyRoots roots(isolate);
16877 for (
int i = 0;
i < capacity;
i++) {
16879 Object* k = this->
get(from_index);
16880 if (!Shape::IsLive(roots, k))
continue;
16881 uint32_t hash = Shape::HashForObject(isolate, k);
16883 EntryToIndex(new_table->FindInsertionEntry(hash));
16884 for (
int j = 0; j < Shape::kEntrySize; j++) {
16885 new_table->set(insertion_index + j,
get(from_index + j), mode);
16888 new_table->SetNumberOfElements(NumberOfElements());
16889 new_table->SetNumberOfDeletedElements(0);
16892 template <
typename Derived,
typename Shape>
16893 uint32_t HashTable<Derived, Shape>::EntryForProbe(Isolate* isolate, Object* k,
16896 uint32_t hash = Shape::HashForObject(isolate, k);
16897 uint32_t capacity = this->Capacity();
16898 uint32_t entry = FirstProbe(hash, capacity);
16899 for (
int i = 1;
i < probe;
i++) {
16900 if (entry == expected)
return expected;
16901 entry = NextProbe(entry,
i, capacity);
16906 template <
typename Derived,
typename Shape>
16908 WriteBarrierMode mode) {
16909 int index1 = EntryToIndex(entry1);
16910 int index2 = EntryToIndex(entry2);
16911 Object* temp[Shape::kEntrySize];
16912 for (
int j = 0; j < Shape::kEntrySize; j++) {
16913 temp[j] =
get(index1 + j);
16915 for (
int j = 0; j < Shape::kEntrySize; j++) {
16916 set(index1 + j,
get(index2 + j), mode);
16918 for (
int j = 0; j < Shape::kEntrySize; j++) {
16919 set(index2 + j, temp[j], mode);
16923 template <
typename Derived,
typename Shape>
16924 void HashTable<Derived, Shape>::Rehash(Isolate* isolate) {
16925 DisallowHeapAllocation no_gc;
16926 WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
16927 ReadOnlyRoots roots(isolate);
16930 for (
int probe = 1; !done; probe++) {
16934 for (
uint32_t current = 0; current < capacity; current++) {
16935 Object* current_key = KeyAt(current);
16936 if (!Shape::IsLive(roots, current_key))
continue;
16937 uint32_t target = EntryForProbe(isolate, current_key, probe, current);
16938 if (current == target)
continue;
16939 Object* target_key = KeyAt(target);
16940 if (!Shape::IsLive(roots, target_key) ||
16941 EntryForProbe(isolate, target_key, probe, target) != target) {
16943 Swap(current, target, mode);
16954 Object* the_hole = roots.the_hole_value();
16955 Object* undefined = roots.undefined_value();
16956 for (
uint32_t current = 0; current < capacity; current++) {
16957 if (KeyAt(current) == the_hole) {
16958 set(EntryToIndex(current) + kEntryKeyIndex, undefined);
16961 SetNumberOfDeletedElements(0);
16964 template <
typename Derived,
typename Shape>
16965 Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
16966 Isolate* isolate, Handle<Derived> table,
int n, PretenureFlag pretenure) {
16967 if (table->HasSufficientCapacityToAdd(n))
return table;
16969 int capacity = table->Capacity();
16970 int new_nof = table->NumberOfElements() + n;
16972 const int kMinCapacityForPretenure = 256;
16973 bool should_pretenure =
16974 pretenure == TENURED ||
16975 ((capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(*table));
16976 Handle<Derived> new_table = HashTable::New(
16977 isolate, new_nof, should_pretenure ? TENURED : NOT_TENURED);
16979 table->Rehash(isolate, *new_table);
16984 HashTable<NameDictionary, NameDictionaryShape>::HasSufficientCapacityToAdd(
int);
16986 template <
typename Derived,
typename Shape>
16987 bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
16988 int number_of_additional_elements) {
16989 int capacity = Capacity();
16990 int nof = NumberOfElements() + number_of_additional_elements;
16991 int nod = NumberOfDeletedElements();
16995 if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
16996 int needed_free = nof >> 1;
16997 if (nof + needed_free <= capacity)
return true;
17002 template <
typename Derived,
typename Shape>
17003 Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
17004 Handle<Derived> table,
17005 int additionalCapacity) {
17006 int capacity = table->Capacity();
17007 int nof = table->NumberOfElements();
17011 if (nof > (capacity >> 2))
return table;
17016 int at_least_room_for = nof + additionalCapacity;
17017 int new_capacity = ComputeCapacity(at_least_room_for);
17018 if (new_capacity < Derived::kMinShrinkCapacity)
return table;
17019 if (new_capacity == capacity)
return table;
17021 const int kMinCapacityForPretenure = 256;
17022 bool pretenure = (at_least_room_for > kMinCapacityForPretenure) &&
17023 !Heap::InNewSpace(*table);
17024 Handle<Derived> new_table =
17025 HashTable::New(isolate, new_capacity, pretenure ? TENURED : NOT_TENURED,
17026 USE_CUSTOM_MINIMUM_CAPACITY);
17028 table->Rehash(isolate, *new_table);
17032 template <
typename Derived,
typename Shape>
17035 uint32_t entry = FirstProbe(hash, capacity);
17038 ReadOnlyRoots roots = GetReadOnlyRoots();
17040 if (!Shape::IsLive(roots, KeyAt(entry)))
break;
17041 entry = NextProbe(entry, count++, capacity);
17046 void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
17047 Handle<Name> name) {
17050 JSObject::InvalidatePrototypeValidityCell(*global);
17052 DCHECK(!global->HasFastProperties());
17053 auto dictionary = handle(global->global_dictionary(), global->GetIsolate());
17054 int entry = dictionary->FindEntry(global->GetIsolate(), name);
17055 if (entry == GlobalDictionary::kNotFound)
return;
17056 PropertyCell::InvalidateEntry(global->GetIsolate(), dictionary, entry);
17059 Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
17060 Handle<JSGlobalObject> global, Handle<Name> name,
17061 PropertyCellType cell_type,
int* entry_out) {
17062 Isolate* isolate = global->GetIsolate();
17063 DCHECK(!global->HasFastProperties());
17064 Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
17065 int entry = dictionary->FindEntry(isolate, name);
17066 Handle<PropertyCell> cell;
17067 if (entry != GlobalDictionary::kNotFound) {
17068 if (entry_out) *entry_out = entry;
17069 cell = handle(dictionary->CellAt(entry), isolate);
17070 PropertyCellType original_cell_type = cell->property_details().cell_type();
17071 DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
17072 original_cell_type == PropertyCellType::kUninitialized);
17073 DCHECK(cell->value()->IsTheHole(isolate));
17074 if (original_cell_type == PropertyCellType::kInvalidated) {
17075 cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
17077 PropertyDetails details(kData, NONE, cell_type);
17078 cell->set_property_details(details);
17081 cell = isolate->factory()->NewPropertyCell(name);
17082 PropertyDetails details(kData, NONE, cell_type);
17083 dictionary = GlobalDictionary::Add(isolate, dictionary, name, cell, details,
17086 global->SetProperties(*dictionary);
17099 :
StringTableKey(ComputeHashField(c1, c2, seed)), c1_(c1), c2_(c2) {}
17101 bool IsMatch(
Object* o)
override {
17102 String other = String::cast(o);
17103 if (other->length() != 2)
return false;
17104 if (other->Get(0) != c1_)
return false;
17105 return other->Get(1) == c2_;
17115 uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint64_t seed) {
17119 hash += hash << 10;
17123 hash += hash << 10;
17127 hash ^= hash >> 11;
17128 hash += hash << 15;
17129 if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
17130 hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
17136 uint16_t chars[2] = {c1, c2};
17137 uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
17138 DCHECK_EQ(hash, check_hash);
17153 int entry = string_table->FindEntry(isolate, &key);
17156 Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
17158 DCHECK_EQ(result->Hash(), key.Hash());
17162 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17166 table = StringTable::EnsureCapacity(isolate, table, expected);
17167 isolate->heap()->SetRootStringTable(*table);
17172 template <
class StringClass>
17173 void MigrateExternalStringResource(Isolate* isolate, String from, String to) {
17174 StringClass cast_from = StringClass::cast(from);
17175 StringClass cast_to = StringClass::cast(to);
17176 const typename StringClass::Resource* to_resource = cast_to->resource();
17177 if (to_resource ==
nullptr) {
17179 cast_to->SetResource(isolate, cast_from->resource());
17182 isolate->heap()->UpdateExternalString(
17183 from, ExternalString::cast(from)->ExternalPayloadSize(), 0);
17184 cast_from->SetResource(isolate,
nullptr);
17185 }
else if (to_resource != cast_from->resource()) {
17187 isolate->heap()->FinalizeExternalString(from);
17191 void MakeStringThin(String
string, String internalized, Isolate* isolate) {
17192 DCHECK_NE(
string, internalized);
17193 DCHECK(internalized->IsInternalizedString());
17195 if (string->IsExternalString()) {
17196 if (internalized->IsExternalOneByteString()) {
17197 MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
17199 }
else if (internalized->IsExternalTwoByteString()) {
17200 MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
17206 isolate->heap()->FinalizeExternalString(
string);
17210 DisallowHeapAllocation no_gc;
17211 int old_size =
string->Size();
17212 isolate->heap()->NotifyObjectLayoutChange(
string, old_size, no_gc);
17213 bool one_byte = internalized->IsOneByteRepresentation();
17214 Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
17215 : isolate->factory()->thin_string_map();
17216 DCHECK_GE(old_size, ThinString::kSize);
17217 string->synchronized_set_map(*map);
17218 ThinString thin = ThinString::cast(
string);
17219 thin->set_actual(internalized);
17220 Address thin_end = thin->address() + ThinString::kSize;
17221 int size_delta = old_size - ThinString::kSize;
17222 if (size_delta != 0) {
17223 Heap* heap = isolate->heap();
17224 heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
17231 Handle<String> StringTable::LookupString(Isolate* isolate,
17232 Handle<String>
string) {
17233 string = String::Flatten(isolate,
string);
17234 if (string->IsInternalizedString())
return string;
17236 InternalizedStringKey key(
string);
17237 Handle<String> result = LookupKey(isolate, &key);
17239 if (FLAG_thin_strings) {
17240 if (!string->IsInternalizedString()) {
17241 MakeStringThin(*
string, *result, isolate);
17244 if (string->IsConsString()) {
17245 Handle<ConsString> cons = Handle<ConsString>::cast(
string);
17246 cons->set_first(isolate, *result);
17247 cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
17248 }
else if (string->IsSlicedString()) {
17249 STATIC_ASSERT(static_cast<int>(ConsString::kSize) ==
17250 static_cast<int>(SlicedString::kSize));
17251 DisallowHeapAllocation no_gc;
17252 bool one_byte = result->IsOneByteRepresentation();
17253 Handle<Map> map = one_byte
17254 ? isolate->factory()->cons_one_byte_string_map()
17255 : isolate->factory()->cons_string_map();
17256 string->set_map(*map);
17257 Handle<ConsString> cons = Handle<ConsString>::cast(
string);
17258 cons->set_first(isolate, *result);
17259 cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
17266 Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
17267 Handle<StringTable> table = isolate->factory()->string_table();
17268 int entry = table->FindEntry(isolate, key);
17271 if (entry != kNotFound) {
17272 return handle(String::cast(table->KeyAt(entry)), isolate);
17275 table = StringTable::CautiousShrink(isolate, table);
17277 table = StringTable::EnsureCapacity(isolate, table, 1);
17278 isolate->heap()->SetRootStringTable(*table);
17280 return AddKeyNoResize(isolate, key);
17283 Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
17284 StringTableKey* key) {
17285 Handle<StringTable> table = isolate->factory()->string_table();
17286 DCHECK(table->HasSufficientCapacityToAdd(1));
17288 Handle<String>
string = key->AsHandle(isolate);
17291 CHECK(!
string.is_null());
17292 DCHECK(string->HasHashCode());
17293 DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
17296 int entry = table->FindInsertionEntry(key->Hash());
17297 table->set(EntryToIndex(entry), *
string);
17298 table->ElementAdded();
17300 return Handle<String>::cast(
string);
17303 Handle<StringTable> StringTable::CautiousShrink(Isolate* isolate,
17304 Handle<StringTable> table) {
17306 int capacity = table->Capacity();
17307 int nof = table->NumberOfElements();
17308 if (capacity <= StringTable::kMinCapacity)
return table;
17309 if (nof > (capacity / kMaxEmptyFactor))
return table;
17311 int slack_capacity = nof >> 2;
17312 return Shrink(isolate, table, slack_capacity);
17317 class StringTableNoAllocateKey :
public StringTableKey {
17319 StringTableNoAllocateKey(String
string, uint64_t seed)
17320 : StringTableKey(0), string_(string) {
17321 StringShape shape(
string);
17322 one_byte_ = shape.HasOnlyOneByteChars();
17323 DCHECK(!shape.IsInternalized());
17324 DCHECK(!shape.IsThin());
17325 int length =
string->length();
17326 if (shape.IsCons() && length <= String::kMaxHashCalcLength) {
17327 special_flattening_ =
true;
17330 if (V8_LIKELY(length <=
17331 static_cast<int>(arraysize(one_byte_buffer_)))) {
17332 one_byte_content_ = one_byte_buffer_;
17334 one_byte_content_ =
new uint8_t[length];
17336 String::WriteToFlat(
string, one_byte_content_, 0, length);
17338 StringHasher::HashSequentialString(one_byte_content_, length, seed);
17340 if (V8_LIKELY(length <=
17341 static_cast<int>(arraysize(two_byte_buffer_)))) {
17342 two_byte_content_ = two_byte_buffer_;
17344 two_byte_content_ =
new uint16_t[length];
17346 String::WriteToFlat(
string, two_byte_content_, 0, length);
17348 StringHasher::HashSequentialString(two_byte_content_, length, seed);
17350 string->set_hash_field(hash_field);
17352 special_flattening_ =
false;
17353 one_byte_content_ =
nullptr;
17357 DCHECK(string->HasHashCode());
17358 set_hash_field(string->hash_field());
17361 ~StringTableNoAllocateKey()
override {
17363 if (one_byte_content_ != one_byte_buffer_)
delete[] one_byte_content_;
17365 if (two_byte_content_ != two_byte_buffer_)
delete[] two_byte_content_;
17369 bool IsMatch(Object* otherstring)
override {
17370 String other = String::cast(otherstring);
17371 DCHECK(other->IsInternalizedString());
17372 DCHECK(other->IsFlat());
17373 if (Hash() != other->Hash())
return false;
17374 int len = string_->length();
17375 if (len != other->length())
return false;
17377 if (!special_flattening_) {
17378 if (string_->Get(0) != other->Get(0))
return false;
17379 if (string_->IsFlat()) {
17380 StringShape shape1(string_);
17381 StringShape shape2(other);
17382 if (shape1.encoding_tag() == kOneByteStringTag &&
17383 shape2.encoding_tag() == kOneByteStringTag) {
17384 String::FlatContent flat1 = string_->GetFlatContent();
17385 String::FlatContent flat2 = other->GetFlatContent();
17386 return CompareRawStringContents(flat1.ToOneByteVector().start(),
17387 flat2.ToOneByteVector().start(), len);
17389 if (shape1.encoding_tag() == kTwoByteStringTag &&
17390 shape2.encoding_tag() == kTwoByteStringTag) {
17391 String::FlatContent flat1 = string_->GetFlatContent();
17392 String::FlatContent flat2 = other->GetFlatContent();
17393 return CompareRawStringContents(flat1.ToUC16Vector().start(),
17394 flat2.ToUC16Vector().start(), len);
17397 StringComparator comparator;
17398 return comparator.Equals(string_, other);
17401 String::FlatContent flat_content = other->GetFlatContent();
17403 if (flat_content.IsOneByte()) {
17404 return CompareRawStringContents(
17405 one_byte_content_, flat_content.ToOneByteVector().start(), len);
17407 DCHECK(flat_content.IsTwoByte());
17408 for (
int i = 0;
i < len;
i++) {
17409 if (flat_content.Get(
i) != one_byte_content_[
i])
return false;
17414 if (flat_content.IsTwoByte()) {
17415 return CompareRawStringContents(
17416 two_byte_content_, flat_content.ToUC16Vector().start(), len);
17418 DCHECK(flat_content.IsOneByte());
17419 for (
int i = 0;
i < len;
i++) {
17420 if (flat_content.Get(
i) != two_byte_content_[
i])
return false;
17427 V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate)
override {
17434 bool special_flattening_;
17436 uint8_t* one_byte_content_;
17437 uint16_t* two_byte_content_;
17440 uint8_t one_byte_buffer_[256];
17441 uint16_t two_byte_buffer_[128];
17448 Address StringTable::LookupStringIfExists_NoAllocate(Isolate* isolate,
17449 Address raw_string) {
17450 DisallowHeapAllocation no_gc;
17451 String
string = String::cast(ObjectPtr(raw_string));
17452 Heap* heap = isolate->heap();
17453 StringTable table = heap->string_table();
17455 StringTableNoAllocateKey key(
string, heap->HashSeed());
17458 uint32_t hash =
string->hash_field();
17463 !String::ArrayIndexValueBits::is_valid(ResultSentinel::kUnsupported));
17465 !String::ArrayIndexValueBits::is_valid(ResultSentinel::kNotFound));
17467 if (Name::ContainsCachedArrayIndex(hash)) {
17468 return Smi::FromInt(String::ArrayIndexValueBits::decode(hash)).ptr();
17470 if ((hash & Name::kIsNotArrayIndexMask) == 0) {
17472 return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
17475 DCHECK(!string->IsInternalizedString());
17476 int entry = table->FindEntry(ReadOnlyRoots(isolate), &key, key.Hash());
17477 if (entry != kNotFound) {
17478 String internalized = String::cast(table->KeyAt(entry));
17479 if (FLAG_thin_strings) {
17480 MakeStringThin(
string, internalized, isolate);
17482 return internalized.ptr();
17486 return Smi::FromInt(ResultSentinel::kNotFound).ptr();
17489 String StringTable::ForwardStringIfExists(Isolate* isolate, StringTableKey* key,
17491 Handle<StringTable> table = isolate->factory()->string_table();
17492 int entry = table->FindEntry(isolate, key);
17493 if (entry == kNotFound)
return String();
17495 String canonical = String::cast(table->KeyAt(entry));
17496 if (canonical !=
string) MakeStringThin(
string, canonical, isolate);
17500 Handle<StringSet> StringSet::New(Isolate* isolate) {
17501 return HashTable::New(isolate, 0);
17504 Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
17505 Handle<String> name) {
17506 if (!stringset->Has(isolate, name)) {
17507 stringset = EnsureCapacity(isolate, stringset, 1);
17508 uint32_t hash = ShapeT::Hash(isolate, *name);
17509 int entry = stringset->FindInsertionEntry(hash);
17510 stringset->set(EntryToIndex(entry), *name);
17511 stringset->ElementAdded();
17516 bool StringSet::Has(Isolate* isolate, Handle<String> name) {
17517 return FindEntry(isolate, *name) != kNotFound;
17520 Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
17521 Handle<ObjectHashSet>
set,
17522 Handle<Object> key) {
17523 int32_t hash = key->GetOrCreateHash(isolate)->value();
17524 if (!set->Has(isolate, key, hash)) {
17525 set = EnsureCapacity(isolate,
set, 1);
17526 int entry =
set->FindInsertionEntry(hash);
17527 set->set(EntryToIndex(entry), *key);
17528 set->ElementAdded();
17535 const int kLiteralEntryLength = 2;
17536 const int kLiteralInitialLength = 2;
17537 const int kLiteralContextOffset = 0;
17538 const int kLiteralLiteralsOffset = 1;
17540 int SearchLiteralsMapEntry(CompilationCacheTable cache,
int cache_entry,
17541 Context native_context) {
17542 DisallowHeapAllocation no_gc;
17543 DCHECK(native_context->IsNativeContext());
17544 Object* obj = cache->get(cache_entry);
17548 DCHECK(!obj->IsFixedArray());
17549 if (obj->IsWeakFixedArray()) {
17550 WeakFixedArray* literals_map = WeakFixedArray::cast(obj);
17551 int length = literals_map->length();
17552 for (
int i = 0;
i < length;
i += kLiteralEntryLength) {
17553 DCHECK(literals_map->Get(
i + kLiteralContextOffset)->IsWeakOrCleared());
17554 if (literals_map->Get(
i + kLiteralContextOffset) ==
17555 HeapObjectReference::Weak(native_context)) {
17563 void AddToFeedbackCellsMap(Handle<CompilationCacheTable> cache,
int cache_entry,
17564 Handle<Context> native_context,
17565 Handle<FeedbackCell> feedback_cell) {
17566 Isolate* isolate = native_context->GetIsolate();
17567 DCHECK(native_context->IsNativeContext());
17568 STATIC_ASSERT(kLiteralEntryLength == 2);
17569 Handle<WeakFixedArray> new_literals_map;
17572 Object* obj = cache->get(cache_entry);
17576 DCHECK(!obj->IsFixedArray());
17577 if (!obj->IsWeakFixedArray() || WeakFixedArray::cast(obj)->length() == 0) {
17579 isolate->factory()->NewWeakFixedArray(kLiteralInitialLength, TENURED);
17582 Handle<WeakFixedArray> old_literals_map(WeakFixedArray::cast(obj), isolate);
17583 entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context);
17586 old_literals_map->Set(entry + kLiteralLiteralsOffset,
17587 HeapObjectReference::Weak(*feedback_cell));
17592 DCHECK_LT(entry, 0);
17593 int length = old_literals_map->length();
17594 for (
int i = 0;
i < length;
i += kLiteralEntryLength) {
17595 if (old_literals_map->Get(
i + kLiteralContextOffset)->IsCleared()) {
17596 new_literals_map = old_literals_map;
17604 new_literals_map = isolate->factory()->CopyWeakFixedArrayAndGrow(
17605 old_literals_map, kLiteralEntryLength, TENURED);
17606 entry = old_literals_map->length();
17610 new_literals_map->Set(entry + kLiteralContextOffset,
17611 HeapObjectReference::Weak(*native_context));
17612 new_literals_map->Set(entry + kLiteralLiteralsOffset,
17613 HeapObjectReference::Weak(*feedback_cell));
17616 for (
int i = 0;
i < new_literals_map->length();
i += kLiteralEntryLength) {
17617 MaybeObject
object = new_literals_map->Get(
i + kLiteralContextOffset);
17618 DCHECK(object->IsCleared() ||
17619 object->GetHeapObjectAssumeWeak()->IsNativeContext());
17620 object = new_literals_map->Get(
i + kLiteralLiteralsOffset);
17621 DCHECK(object->IsCleared() ||
17622 object->GetHeapObjectAssumeWeak()->IsFeedbackCell());
17626 Object* old_literals_map = cache->get(cache_entry);
17627 if (old_literals_map != *new_literals_map) {
17628 cache->set(cache_entry, *new_literals_map);
17632 FeedbackCell* SearchLiteralsMap(CompilationCacheTable cache,
int cache_entry,
17633 Context native_context) {
17634 FeedbackCell* result =
nullptr;
17635 int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context);
17637 WeakFixedArray* literals_map =
17638 WeakFixedArray::cast(cache->get(cache_entry));
17639 DCHECK_LE(entry + kLiteralEntryLength, literals_map->length());
17640 MaybeObject
object = literals_map->Get(entry + kLiteralLiteralsOffset);
17642 result =
object->IsCleared()
17644 : FeedbackCell::cast(object->GetHeapObjectAssumeWeak());
17646 DCHECK(result ==
nullptr || result->IsFeedbackCell());
17652 MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
17653 Handle<CompilationCacheTable> table, Handle<String> src,
17654 Handle<Context> native_context, LanguageMode language_mode) {
17659 Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
17660 native_context->GetIsolate());
17661 Isolate* isolate = native_context->GetIsolate();
17662 src = String::Flatten(isolate, src);
17663 StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
17664 int entry = table->FindEntry(isolate, &key);
17665 if (entry == kNotFound)
return MaybeHandle<SharedFunctionInfo>();
17666 int index = EntryToIndex(entry);
17667 if (!table->get(index)->IsFixedArray()) {
17668 return MaybeHandle<SharedFunctionInfo>();
17670 Object* obj = table->get(index + 1);
17671 if (obj->IsSharedFunctionInfo()) {
17672 return handle(SharedFunctionInfo::cast(obj), native_context->GetIsolate());
17674 return MaybeHandle<SharedFunctionInfo>();
17677 InfoCellPair CompilationCacheTable::LookupEval(
17678 Handle<CompilationCacheTable> table, Handle<String> src,
17679 Handle<SharedFunctionInfo> outer_info, Handle<Context> native_context,
17680 LanguageMode language_mode,
int position) {
17681 InfoCellPair empty_result;
17682 Isolate* isolate = native_context->GetIsolate();
17683 src = String::Flatten(isolate, src);
17684 StringSharedKey key(src, outer_info, language_mode, position);
17685 int entry = table->FindEntry(isolate, &key);
17686 if (entry == kNotFound)
return empty_result;
17687 int index = EntryToIndex(entry);
17688 if (!table->get(index)->IsFixedArray())
return empty_result;
17689 Object* obj = table->get(EntryToIndex(entry) + 1);
17690 if (obj->IsSharedFunctionInfo()) {
17691 FeedbackCell* feedback_cell =
17692 SearchLiteralsMap(*table, EntryToIndex(entry) + 2, *native_context);
17693 return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
17695 return empty_result;
17698 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
17699 JSRegExp::Flags flags) {
17700 Isolate* isolate = GetIsolate();
17701 DisallowHeapAllocation no_allocation;
17702 RegExpKey key(src, flags);
17703 int entry = FindEntry(isolate, &key);
17704 if (entry == kNotFound)
return isolate->factory()->undefined_value();
17705 return Handle<Object>(
get(EntryToIndex(entry) + 1), isolate);
17708 Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
17709 Handle<CompilationCacheTable> cache, Handle<String> src,
17710 Handle<Context> native_context, LanguageMode language_mode,
17711 Handle<SharedFunctionInfo> value) {
17712 Isolate* isolate = native_context->GetIsolate();
17717 Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
17719 src = String::Flatten(isolate, src);
17720 StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
17721 Handle<Object> k = key.AsHandle(isolate);
17722 cache = EnsureCapacity(isolate, cache, 1);
17723 int entry = cache->FindInsertionEntry(key.Hash());
17724 cache->set(EntryToIndex(entry), *k);
17725 cache->set(EntryToIndex(entry) + 1, *value);
17726 cache->ElementAdded();
17730 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
17731 Handle<CompilationCacheTable> cache, Handle<String> src,
17732 Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
17733 Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
17735 Isolate* isolate = native_context->GetIsolate();
17736 src = String::Flatten(isolate, src);
17737 StringSharedKey key(src, outer_info, value->language_mode(), position);
17739 Handle<Object> k = key.AsHandle(isolate);
17740 int entry = cache->FindEntry(isolate, &key);
17741 if (entry != kNotFound) {
17742 cache->set(EntryToIndex(entry), *k);
17743 cache->set(EntryToIndex(entry) + 1, *value);
17747 AddToFeedbackCellsMap(cache, EntryToIndex(entry) + 2, native_context,
17753 cache = EnsureCapacity(isolate, cache, 1);
17754 int entry = cache->FindInsertionEntry(key.Hash());
17756 isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
17757 cache->set(EntryToIndex(entry), *k);
17758 cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
17759 cache->ElementAdded();
17763 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
17764 Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
17765 JSRegExp::Flags flags, Handle<FixedArray> value) {
17766 RegExpKey key(src, flags);
17767 cache = EnsureCapacity(isolate, cache, 1);
17768 int entry = cache->FindInsertionEntry(key.Hash());
17771 cache->set(EntryToIndex(entry), *value);
17772 cache->set(EntryToIndex(entry) + 1, *value);
17773 cache->ElementAdded();
17778 void CompilationCacheTable::Age() {
17779 DisallowHeapAllocation no_allocation;
17780 Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
17781 for (
int entry = 0, size = Capacity(); entry < size; entry++) {
17782 int entry_index = EntryToIndex(entry);
17783 int value_index = entry_index + 1;
17785 if (
get(entry_index)->IsNumber()) {
17786 Smi count = Smi::cast(
get(value_index));
17787 count = Smi::FromInt(count->value() - 1);
17788 if (count->value() == 0) {
17789 NoWriteBarrierSet(*
this, entry_index, the_hole_value);
17790 NoWriteBarrierSet(*
this, value_index, the_hole_value);
17793 NoWriteBarrierSet(*
this, value_index, count);
17795 }
else if (
get(entry_index)->IsFixedArray()) {
17796 SharedFunctionInfo* info = SharedFunctionInfo::cast(
get(value_index));
17797 if (info->IsInterpreted() && info->GetBytecodeArray()->IsOld()) {
17798 for (
int i = 0;
i < kEntrySize;
i++) {
17799 NoWriteBarrierSet(*
this, entry_index +
i, the_hole_value);
17808 void CompilationCacheTable::Remove(Object* value) {
17809 DisallowHeapAllocation no_allocation;
17810 Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
17811 for (
int entry = 0, size = Capacity(); entry < size; entry++) {
17812 int entry_index = EntryToIndex(entry);
17813 int value_index = entry_index + 1;
17814 if (
get(value_index) == value) {
17815 for (
int i = 0;
i < kEntrySize;
i++) {
17816 NoWriteBarrierSet(*
this, entry_index +
i, the_hole_value);
17824 template <
typename Derived,
typename Shape>
17825 Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
17826 Isolate* isolate,
int at_least_space_for, PretenureFlag pretenure,
17827 MinimumCapacity capacity_option) {
17828 DCHECK_LE(0, at_least_space_for);
17829 Handle<Derived> dict = Dictionary<Derived, Shape>::New(
17830 isolate, at_least_space_for, pretenure, capacity_option);
17831 dict->SetHash(PropertyArray::kNoHashSentinel);
17832 dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
17836 template <
typename Derived,
typename Shape>
17837 Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
17838 Isolate* isolate, Handle<Derived> dictionary,
int n) {
17840 if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
17842 int length = dictionary->NumberOfElements();
17844 Handle<FixedArray> iteration_order = IterationIndices(isolate, dictionary);
17845 DCHECK_EQ(length, iteration_order->length());
17849 for (
int i = 0;
i < length;
i++) {
17850 int index = Smi::ToInt(iteration_order->get(
i));
17851 DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
17852 dictionary->KeyAt(index)));
17854 int enum_index = PropertyDetails::kInitialIndex +
i;
17856 PropertyDetails details = dictionary->DetailsAt(index);
17857 PropertyDetails new_details = details.set_index(enum_index);
17858 dictionary->DetailsAtPut(isolate, index, new_details);
17862 dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
17865 return HashTable<Derived, Shape>::EnsureCapacity(isolate, dictionary, n);
17868 template <
typename Derived,
typename Shape>
17869 Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
17870 Isolate* isolate, Handle<Derived> dictionary,
int entry) {
17871 DCHECK(Shape::kEntrySize != 3 ||
17872 dictionary->DetailsAt(entry).IsConfigurable());
17873 dictionary->ClearEntry(isolate, entry);
17874 dictionary->ElementRemoved();
17875 return Shrink(isolate, dictionary);
17878 template <
typename Derived,
typename Shape>
17879 Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
17880 Handle<Derived> dictionary,
17881 Key key, Handle<Object> value,
17882 PropertyDetails details) {
17883 int entry = dictionary->FindEntry(isolate, key);
17886 if (entry == Dictionary::kNotFound) {
17887 return Derived::Add(isolate, dictionary, key, value, details);
17891 dictionary->ValueAtPut(entry, *value);
17892 if (Shape::kEntrySize == 3) dictionary->DetailsAtPut(isolate, entry, details);
17896 template <
typename Derived,
typename Shape>
17898 BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
17899 Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
17900 PropertyDetails details,
int* entry_out) {
17902 return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
17903 details, entry_out);
17908 template Handle<NameDictionary>
17909 BaseNameDictionary<NameDictionary, NameDictionaryShape>::
17910 AddNoUpdateNextEnumerationIndex(Isolate* isolate, Handle<NameDictionary>,
17911 Handle<Name>, Handle<Object>,
17912 PropertyDetails,
int*);
17914 template <
typename Derived,
typename Shape>
17915 Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
17916 Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
17917 PropertyDetails details,
int* entry_out) {
17919 DCHECK_EQ(0, details.dictionary_index());
17922 int index = dictionary->NextEnumerationIndex();
17923 details = details.set_index(index);
17924 dictionary = AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
17925 details, entry_out);
17928 dictionary->SetNextEnumerationIndex(index + 1);
17932 template <
typename Derived,
typename Shape>
17933 Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
17934 Handle<Derived> dictionary,
17935 Key key, Handle<Object> value,
17936 PropertyDetails details,
17938 uint32_t hash = Shape::Hash(isolate, key);
17940 SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
17942 dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
17945 Handle<Object> k = Shape::AsHandle(isolate, key);
17947 uint32_t entry = dictionary->FindInsertionEntry(hash);
17948 dictionary->SetEntry(isolate, entry, *k, *value, details);
17949 DCHECK(dictionary->KeyAt(entry)->IsNumber() ||
17950 Shape::Unwrap(dictionary->KeyAt(entry))->IsUniqueName());
17951 dictionary->ElementAdded();
17952 if (entry_out) *entry_out = entry;
17957 Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
17958 Isolate* isolate, Handle<SimpleNumberDictionary> dictionary,
uint32_t key,
17959 Handle<Object> value) {
17960 return AtPut(isolate, dictionary, key, value, PropertyDetails::Empty());
17963 bool NumberDictionary::HasComplexElements() {
17964 if (!requires_slow_elements())
return false;
17965 ReadOnlyRoots roots = GetReadOnlyRoots();
17966 int capacity = this->Capacity();
17967 for (
int i = 0;
i < capacity;
i++) {
17969 if (!this->ToKey(roots,
i, &k))
continue;
17970 PropertyDetails details = this->DetailsAt(
i);
17971 if (details.kind() == kAccessor)
return true;
17972 PropertyAttributes attr = details.attributes();
17973 if (attr & ALL_ATTRIBUTES_MASK)
return true;
17978 void NumberDictionary::UpdateMaxNumberKey(
uint32_t key,
17979 Handle<JSObject> dictionary_holder) {
17980 DisallowHeapAllocation no_allocation;
17983 if (requires_slow_elements())
return;
17986 if (key > kRequiresSlowElementsLimit) {
17987 if (!dictionary_holder.is_null()) {
17988 dictionary_holder->RequireSlowElements(*
this);
17990 set_requires_slow_elements();
17994 Object* max_index_object =
get(kMaxNumberKeyIndex);
17995 if (!max_index_object->IsSmi() || max_number_key() < key) {
17996 FixedArray::set(kMaxNumberKeyIndex,
17997 Smi::FromInt(key << kRequiresSlowElementsTagSize));
18001 Handle<NumberDictionary> NumberDictionary::Set(
18002 Isolate* isolate, Handle<NumberDictionary> dictionary,
uint32_t key,
18003 Handle<Object> value, Handle<JSObject> dictionary_holder,
18004 PropertyDetails details) {
18005 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18006 return AtPut(isolate, dictionary, key, value, details);
18009 void NumberDictionary::CopyValuesTo(FixedArray elements) {
18010 ReadOnlyRoots roots = GetReadOnlyRoots();
18012 int capacity = this->Capacity();
18013 DisallowHeapAllocation no_gc;
18014 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
18015 for (
int i = 0;
i < capacity;
i++) {
18017 if (this->ToKey(roots,
i, &k)) {
18018 elements->set(pos++, this->ValueAt(
i), mode);
18021 DCHECK_EQ(pos, elements->length());
18024 template <
typename Derived,
typename Shape>
18025 int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
18026 ReadOnlyRoots roots = this->GetReadOnlyRoots();
18027 int capacity = this->Capacity();
18029 for (
int i = 0;
i < capacity;
i++) {
18031 if (!this->ToKey(roots,
i, &k))
continue;
18032 if (k->FilterKey(ENUMERABLE_STRINGS))
continue;
18033 PropertyDetails details = this->DetailsAt(
i);
18034 PropertyAttributes attr = details.attributes();
18035 if ((attr & ONLY_ENUMERABLE) == 0) result++;
18041 template <
typename Dictionary>
18046 STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
18049 return da.dictionary_index() < db.dictionary_index();
18054 template <
typename Derived,
typename Shape>
18058 DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator !=
nullptr);
18059 int length = storage->length();
18060 int capacity = dictionary->Capacity();
18061 int properties = 0;
18063 for (
int i = 0;
i < capacity;
i++) {
18065 if (!dictionary->ToKey(roots,
i, &key))
continue;
18066 bool is_shadowing_key =
false;
18067 if (key->IsSymbol())
continue;
18069 if (details.IsDontEnum()) {
18070 if (mode == KeyCollectionMode::kIncludePrototypes) {
18071 is_shadowing_key =
true;
18076 if (is_shadowing_key) {
18077 accumulator->AddShadowingKey(key);
18080 storage->set(properties, Smi::FromInt(
i));
18083 if (mode == KeyCollectionMode::kOwnOnly && properties == length)
break;
18086 CHECK_EQ(length, properties);
18087 DisallowHeapAllocation no_gc;
18088 Derived raw_dictionary = *dictionary;
18089 FixedArray raw_storage = *storage;
18090 EnumIndexComparator<Derived> cmp(raw_dictionary);
18093 AtomicSlot start(storage->GetFirstElementAddress());
18094 std::sort(start, start + length, cmp);
18095 for (
int i = 0;
i < length;
i++) {
18096 int index = Smi::ToInt(raw_storage->get(
i));
18097 raw_storage->set(
i, raw_dictionary->NameAt(index));
18101 template <
typename Derived,
typename Shape>
18102 Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
18103 Isolate* isolate, Handle<Derived> dictionary) {
18104 int capacity = dictionary->Capacity();
18105 int length = dictionary->NumberOfElements();
18106 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
18107 ReadOnlyRoots roots(isolate);
18108 int array_size = 0;
18110 DisallowHeapAllocation no_gc;
18111 Derived raw_dictionary = *dictionary;
18112 for (
int i = 0;
i < capacity;
i++) {
18114 if (!raw_dictionary->ToKey(roots,
i, &k))
continue;
18115 array->set(array_size++, Smi::FromInt(
i));
18118 DCHECK_EQ(array_size, length);
18120 EnumIndexComparator<Derived> cmp(raw_dictionary);
18123 AtomicSlot start(array->GetFirstElementAddress());
18124 std::sort(start, start + array_size, cmp);
18126 return FixedArray::ShrinkOrEmpty(isolate, array, array_size);
18129 template <
typename Derived,
typename Shape>
18130 void BaseNameDictionary<Derived, Shape>::CollectKeysTo(
18131 Handle<Derived> dictionary, KeyAccumulator* keys) {
18132 Isolate* isolate = keys->isolate();
18133 ReadOnlyRoots roots(isolate);
18134 int capacity = dictionary->Capacity();
18135 Handle<FixedArray> array =
18136 isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
18137 int array_size = 0;
18140 DisallowHeapAllocation no_gc;
18141 Derived raw_dictionary = *dictionary;
18142 for (
int i = 0;
i < capacity;
i++) {
18144 if (!raw_dictionary->ToKey(roots,
i, &k))
continue;
18145 if (k->FilterKey(filter))
continue;
18146 PropertyDetails details = raw_dictionary->DetailsAt(
i);
18147 if ((details.attributes() & filter) != 0) {
18148 keys->AddShadowingKey(k);
18151 if (filter & ONLY_ALL_CAN_READ) {
18152 if (details.kind() != kAccessor)
continue;
18153 Object* accessors = raw_dictionary->ValueAt(
i);
18154 if (!accessors->IsAccessorInfo())
continue;
18155 if (!AccessorInfo::cast(accessors)->all_can_read())
continue;
18157 array->set(array_size++, Smi::FromInt(
i));
18160 EnumIndexComparator<Derived> cmp(raw_dictionary);
18163 AtomicSlot start(array->GetFirstElementAddress());
18164 std::sort(start, start + array_size, cmp);
18167 bool has_seen_symbol =
false;
18168 for (
int i = 0;
i < array_size;
i++) {
18169 int index = Smi::ToInt(array->get(
i));
18170 Object* key = dictionary->NameAt(index);
18171 if (key->IsSymbol()) {
18172 has_seen_symbol =
true;
18175 keys->AddKey(key, DO_NOT_CONVERT);
18177 if (has_seen_symbol) {
18178 for (
int i = 0;
i < array_size;
i++) {
18179 int index = Smi::ToInt(array->get(
i));
18180 Object* key = dictionary->NameAt(index);
18181 if (!key->IsSymbol())
continue;
18182 keys->AddKey(key, DO_NOT_CONVERT);
18188 template <
typename Derived,
typename Shape>
18189 Object* Dictionary<Derived, Shape>::SlowReverseLookup(Object* value) {
18190 Derived dictionary = Derived::cast(*
this);
18191 ReadOnlyRoots roots = dictionary->GetReadOnlyRoots();
18192 int capacity = dictionary->Capacity();
18193 for (
int i = 0;
i < capacity;
i++) {
18195 if (!dictionary->ToKey(roots,
i, &k))
continue;
18196 Object* e = dictionary->ValueAt(
i);
18197 if (e == value)
return k;
18199 return roots.undefined_value();
18202 template <
typename Derived,
typename Shape>
18203 void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
18204 Handle<Derived> table) {
18205 int length = table->length();
18206 for (
int i = Derived::EntryToIndex(0);
i < length;
i++) {
18207 table->set_the_hole(
i);
18211 template <
typename Derived,
typename Shape>
18212 Object* ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
18213 Handle<Object> key,
18215 DisallowHeapAllocation no_gc;
18216 DCHECK(this->IsKey(roots, *key));
18218 int entry = this->FindEntry(roots, key, hash);
18219 if (entry == kNotFound)
return roots.the_hole_value();
18220 return this->
get(Derived::EntryToIndex(entry) + 1);
18223 template <
typename Derived,
typename Shape>
18224 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key) {
18225 DisallowHeapAllocation no_gc;
18227 ReadOnlyRoots roots = this->GetReadOnlyRoots();
18228 DCHECK(this->IsKey(roots, *key));
18231 Object* hash = key->GetHash();
18232 if (hash->IsUndefined(roots)) {
18233 return roots.the_hole_value();
18235 return Lookup(roots, key, Smi::ToInt(hash));
18238 template <
typename Derived,
typename Shape>
18239 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
18241 return Lookup(this->GetReadOnlyRoots(), key, hash);
18244 template <
typename Derived,
typename Shape>
18245 Object* ObjectHashTableBase<Derived, Shape>::ValueAt(
int entry) {
18246 return this->
get(EntryToValueIndex(entry));
18249 template <
typename Derived,
typename Shape>
18250 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Handle<Derived> table,
18251 Handle<Object> key,
18252 Handle<Object> value) {
18253 Isolate* isolate = Heap::FromWritableHeapObject(*table)->isolate();
18254 DCHECK(table->IsKey(ReadOnlyRoots(isolate), *key));
18255 DCHECK(!value->IsTheHole(ReadOnlyRoots(isolate)));
18258 int32_t hash = key->GetOrCreateHash(isolate)->value();
18260 return ObjectHashTableBase<Derived, Shape>::Put(isolate, table, key, value,
18264 template <
typename Derived,
typename Shape>
18265 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
18266 Handle<Derived> table,
18267 Handle<Object> key,
18268 Handle<Object> value,
18270 ReadOnlyRoots roots(isolate);
18271 DCHECK(table->IsKey(roots, *key));
18272 DCHECK(!value->IsTheHole(roots));
18274 int entry = table->FindEntry(roots, key, hash);
18277 if (entry != kNotFound) {
18278 table->set(Derived::EntryToIndex(entry) + 1, *value);
18284 if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
18285 table->Rehash(isolate);
18289 if (!table->HasSufficientCapacityToAdd(1)) {
18290 int nof = table->NumberOfElements() + 1;
18291 int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
18292 if (capacity > ObjectHashTable::kMaxCapacity) {
18293 for (
size_t i = 0;
i < 2; ++
i) {
18294 isolate->heap()->CollectAllGarbage(
18295 Heap::kNoGCFlags, GarbageCollectionReason::kFullHashtable);
18297 table->Rehash(isolate);
18302 table = Derived::EnsureCapacity(isolate, table, 1);
18303 table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
18307 template <
typename Derived,
typename Shape>
18308 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
18309 Isolate* isolate, Handle<Derived> table, Handle<Object> key,
18310 bool* was_present) {
18311 DCHECK(table->IsKey(table->GetReadOnlyRoots(), *key));
18313 Object* hash = key->GetHash();
18314 if (hash->IsUndefined()) {
18315 *was_present =
false;
18319 return Remove(isolate, table, key, was_present, Smi::ToInt(hash));
18322 template <
typename Derived,
typename Shape>
18323 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
18324 Isolate* isolate, Handle<Derived> table, Handle<Object> key,
18325 bool* was_present, int32_t hash) {
18326 ReadOnlyRoots roots = table->GetReadOnlyRoots();
18327 DCHECK(table->IsKey(roots, *key));
18329 int entry = table->FindEntry(roots, key, hash);
18330 if (entry == kNotFound) {
18331 *was_present =
false;
18335 *was_present =
true;
18336 table->RemoveEntry(entry);
18337 return Derived::Shrink(isolate, table);
18340 template <
typename Derived,
typename Shape>
18341 void ObjectHashTableBase<Derived, Shape>::AddEntry(
int entry, Object* key,
18343 this->
set(Derived::EntryToIndex(entry), key);
18344 this->
set(Derived::EntryToIndex(entry) + 1, value);
18345 this->ElementAdded();
18348 template <
typename Derived,
typename Shape>
18349 void ObjectHashTableBase<Derived, Shape>::RemoveEntry(
int entry) {
18350 this->set_the_hole(Derived::EntryToIndex(entry));
18351 this->set_the_hole(Derived::EntryToIndex(entry) + 1);
18352 this->ElementRemoved();
18356 void JSSet::Initialize(Handle<JSSet>
set, Isolate* isolate) {
18357 Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
18358 set->set_table(*table);
18361 void JSSet::Clear(Isolate* isolate, Handle<JSSet>
set) {
18362 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
18363 table = OrderedHashSet::Clear(isolate, table);
18364 set->set_table(*table);
18368 void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
18369 Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
18370 map->set_table(*table);
18373 void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
18374 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
18375 table = OrderedHashMap::Clear(isolate, table);
18376 map->set_table(*table);
18380 void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
18381 Isolate* isolate) {
18382 Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);
18383 weak_collection->set_table(*table);
18387 void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
18388 Handle<Object> key, Handle<Object> value,
18390 DCHECK(key->IsJSReceiver() || key->IsSymbol());
18391 Handle<EphemeronHashTable> table(
18392 EphemeronHashTable::cast(weak_collection->table()),
18393 weak_collection->GetIsolate());
18394 DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
18395 Handle<EphemeronHashTable> new_table = EphemeronHashTable::Put(
18396 weak_collection->GetIsolate(), table, key, value, hash);
18397 weak_collection->set_table(*new_table);
18398 if (*table != *new_table) {
18400 EphemeronHashTable::FillEntriesWithHoles(table);
18405 bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
18406 Handle<Object> key, int32_t hash) {
18407 DCHECK(key->IsJSReceiver() || key->IsSymbol());
18408 Handle<EphemeronHashTable> table(
18409 EphemeronHashTable::cast(weak_collection->table()),
18410 weak_collection->GetIsolate());
18411 DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
18412 bool was_present =
false;
18413 Handle<EphemeronHashTable> new_table = EphemeronHashTable::Remove(
18414 weak_collection->GetIsolate(), table, key, &was_present, hash);
18415 weak_collection->set_table(*new_table);
18416 if (*table != *new_table) {
18418 EphemeronHashTable::FillEntriesWithHoles(table);
18420 return was_present;
18423 Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
18425 Isolate* isolate = holder->GetIsolate();
18426 Handle<EphemeronHashTable> table(EphemeronHashTable::cast(holder->table()),
18428 if (max_entries == 0 || max_entries > table->NumberOfElements()) {
18429 max_entries = table->NumberOfElements();
18431 int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
18432 Handle<FixedArray> entries =
18433 isolate->factory()->NewFixedArray(max_entries * values_per_entry);
18435 if (max_entries > table->NumberOfElements()) {
18436 max_entries = table->NumberOfElements();
18440 DisallowHeapAllocation no_gc;
18441 ReadOnlyRoots roots = ReadOnlyRoots(isolate);
18444 count / values_per_entry < max_entries &&
i < table->Capacity();
i++) {
18446 if (table->ToKey(roots,
i, &key)) {
18447 entries->set(count++, key);
18448 if (values_per_entry > 1) {
18449 Object* value = table->Lookup(handle(key, isolate));
18450 entries->set(count++, value);
18454 DCHECK_EQ(max_entries * values_per_entry, count);
18456 return isolate->factory()->NewJSArrayWithElements(entries);
18460 MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
18461 Handle<JSReceiver> new_target,
double tv) {
18462 Isolate*
const isolate = constructor->GetIsolate();
18463 Handle<JSObject> result;
18464 ASSIGN_RETURN_ON_EXCEPTION(
18466 JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
18468 if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
18469 tv = DoubleToInteger(tv) + 0.0;
18471 tv = std::numeric_limits<double>::quiet_NaN();
18473 Handle<Object> value = isolate->factory()->NewNumber(tv);
18474 Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
18475 return Handle<JSDate>::cast(result);
18480 double JSDate::CurrentTimeValue(Isolate* isolate) {
18481 if (FLAG_log_internal_timer_events) LOG(isolate, CurrentTimeEvent());
18487 return Floor(V8::GetCurrentPlatform()->CurrentClockTimeMillis());
18492 Object* JSDate::GetField(Object*
object, Address smi_index) {
18493 Smi index(smi_index);
18494 return JSDate::cast(
object)->DoGetField(
18495 static_cast<FieldIndex>(index->value()));
18499 Object* JSDate::DoGetField(FieldIndex index) {
18500 DCHECK_NE(index, kDateValue);
18502 DateCache* date_cache = GetIsolate()->date_cache();
18504 if (index < kFirstUncachedField) {
18505 Object* stamp = cache_stamp();
18506 if (stamp != date_cache->stamp() && stamp->IsSmi()) {
18509 date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
18510 SetCachedFields(local_time_ms, date_cache);
18513 case kYear:
return year();
18514 case kMonth:
return month();
18515 case kDay:
return day();
18516 case kWeekday:
return weekday();
18517 case kHour:
return hour();
18518 case kMinute:
return min();
18519 case kSecond:
return sec();
18520 default: UNREACHABLE();
18524 if (index >= kFirstUTCField) {
18525 return GetUTCField(index, value()->Number(), date_cache);
18528 double time = value()->Number();
18529 if (std::isnan(time))
return GetReadOnlyRoots().nan_value();
18531 int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
18532 int days = DateCache::DaysFromTime(local_time_ms);
18534 if (index == kDays)
return Smi::FromInt(days);
18536 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18537 if (index == kMillisecond)
return Smi::FromInt(time_in_day_ms % 1000);
18538 DCHECK_EQ(index, kTimeInDay);
18539 return Smi::FromInt(time_in_day_ms);
18543 Object* JSDate::GetUTCField(FieldIndex index,
18545 DateCache* date_cache) {
18546 DCHECK_GE(index, kFirstUTCField);
18548 if (std::isnan(value))
return GetReadOnlyRoots().nan_value();
18552 if (index == kTimezoneOffset) {
18553 return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
18556 int days = DateCache::DaysFromTime(time_ms);
18558 if (index == kWeekdayUTC)
return Smi::FromInt(date_cache->Weekday(days));
18560 if (index <= kDayUTC) {
18561 int year, month, day;
18562 date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18563 if (index == kYearUTC)
return Smi::FromInt(year);
18564 if (index == kMonthUTC)
return Smi::FromInt(month);
18565 DCHECK_EQ(index, kDayUTC);
18566 return Smi::FromInt(day);
18569 int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
18571 case kHourUTC:
return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
18572 case kMinuteUTC:
return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
18573 case kSecondUTC:
return Smi::FromInt((time_in_day_ms / 1000) % 60);
18574 case kMillisecondUTC:
return Smi::FromInt(time_in_day_ms % 1000);
18575 case kDaysUTC:
return Smi::FromInt(days);
18576 case kTimeInDayUTC:
return Smi::FromInt(time_in_day_ms);
18577 default: UNREACHABLE();
18585 Handle<Object> JSDate::SetValue(Handle<JSDate> date,
double v) {
18586 Isolate*
const isolate = date->GetIsolate();
18587 Handle<Object> value = isolate->factory()->NewNumber(v);
18588 bool value_is_nan = std::isnan(v);
18589 date->SetValue(*value, value_is_nan);
18594 void JSDate::SetValue(Object* value,
bool is_value_nan) {
18596 if (is_value_nan) {
18597 HeapNumber* nan = GetReadOnlyRoots().nan_value();
18598 set_cache_stamp(nan, SKIP_WRITE_BARRIER);
18599 set_year(nan, SKIP_WRITE_BARRIER);
18600 set_month(nan, SKIP_WRITE_BARRIER);
18601 set_day(nan, SKIP_WRITE_BARRIER);
18602 set_hour(nan, SKIP_WRITE_BARRIER);
18603 set_min(nan, SKIP_WRITE_BARRIER);
18604 set_sec(nan, SKIP_WRITE_BARRIER);
18605 set_weekday(nan, SKIP_WRITE_BARRIER);
18607 set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
18612 void JSDate::SetCachedFields(
int64_t local_time_ms, DateCache* date_cache) {
18613 int days = DateCache::DaysFromTime(local_time_ms);
18614 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18615 int year, month, day;
18616 date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18617 int weekday = date_cache->Weekday(days);
18618 int hour = time_in_day_ms / (60 * 60 * 1000);
18619 int min = (time_in_day_ms / (60 * 1000)) % 60;
18620 int sec = (time_in_day_ms / 1000) % 60;
18621 set_cache_stamp(date_cache->stamp());
18622 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
18623 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
18624 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
18625 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
18626 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
18627 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
18628 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
18631 int JSMessageObject::GetLineNumber()
const {
18632 if (start_position() == -1)
return Message::kNoLineNumberInfo;
18634 Handle<Script> the_script(script(), GetIsolate());
18636 Script::PositionInfo info;
18637 const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18638 if (!Script::GetPositionInfo(the_script, start_position(), &info,
18640 return Message::kNoLineNumberInfo;
18643 return info.line + 1;
18646 int JSMessageObject::GetColumnNumber()
const {
18647 if (start_position() == -1)
return -1;
18649 Handle<Script> the_script(script(), GetIsolate());
18651 Script::PositionInfo info;
18652 const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18653 if (!Script::GetPositionInfo(the_script, start_position(), &info,
18658 return info.column;
18661 Handle<String> JSMessageObject::GetSourceLine()
const {
18662 Isolate* isolate = GetIsolate();
18663 Handle<Script> the_script(script(), isolate);
18665 if (the_script->type() == Script::TYPE_WASM) {
18666 return isolate->factory()->empty_string();
18669 Script::PositionInfo info;
18670 const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18671 if (!Script::GetPositionInfo(the_script, start_position(), &info,
18673 return isolate->factory()->empty_string();
18676 Handle<String> src = handle(String::cast(the_script->source()), isolate);
18677 return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
18680 Handle<PropertyCell> PropertyCell::InvalidateEntry(
18681 Isolate* isolate, Handle<GlobalDictionary> dictionary,
int entry) {
18683 Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
18684 Handle<Name> name(cell->name(), isolate);
18685 Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(name);
18686 new_cell->set_value(cell->value());
18687 dictionary->ValueAtPut(entry, *new_cell);
18688 bool is_the_hole = cell->value()->IsTheHole(isolate);
18690 PropertyDetails details = cell->property_details();
18691 details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
18692 : PropertyCellType::kMutable);
18693 new_cell->set_property_details(details);
18696 cell->set_value(ReadOnlyRoots(isolate).undefined_value());
18698 cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
18700 details = details.set_cell_type(PropertyCellType::kInvalidated);
18701 cell->set_property_details(details);
18702 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18703 isolate, DependentCode::kPropertyCellChangedGroup);
18708 PropertyCellConstantType PropertyCell::GetConstantType() {
18709 if (value()->IsSmi())
return PropertyCellConstantType::kSmi;
18710 return PropertyCellConstantType::kStableMap;
18714 static bool RemainsConstantType(Handle<PropertyCell> cell,
18715 Handle<Object> value) {
18717 if (cell->value()->IsSmi() && value->IsSmi()) {
18719 }
else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
18720 return HeapObject::cast(cell->value())->map() ==
18721 HeapObject::cast(*value)->map() &&
18722 HeapObject::cast(*value)->map()->is_stable();
18727 PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
18728 Handle<PropertyCell> cell,
18729 Handle<Object> value,
18730 PropertyDetails details) {
18731 PropertyCellType type = details.cell_type();
18732 DCHECK(!value->IsTheHole(isolate));
18733 if (cell->value()->IsTheHole(isolate)) {
18736 case PropertyCellType::kUninitialized:
18737 if (value->IsUndefined(isolate))
return PropertyCellType::kUndefined;
18738 return PropertyCellType::kConstant;
18739 case PropertyCellType::kInvalidated:
18740 return PropertyCellType::kMutable;
18746 case PropertyCellType::kUndefined:
18747 return PropertyCellType::kConstant;
18748 case PropertyCellType::kConstant:
18749 if (*value == cell->value())
return PropertyCellType::kConstant;
18751 case PropertyCellType::kConstantType:
18752 if (RemainsConstantType(cell, value)) {
18753 return PropertyCellType::kConstantType;
18756 case PropertyCellType::kMutable:
18757 return PropertyCellType::kMutable;
18762 Handle<PropertyCell> PropertyCell::PrepareForValue(
18763 Isolate* isolate, Handle<GlobalDictionary> dictionary,
int entry,
18764 Handle<Object> value, PropertyDetails details) {
18765 DCHECK(!value->IsTheHole(isolate));
18766 Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
18767 const PropertyDetails original_details = cell->property_details();
18770 (original_details.kind() == kData && details.kind() == kAccessor) ||
18771 (!original_details.IsReadOnly() && details.IsReadOnly());
18773 PropertyCellType old_type = original_details.cell_type();
18776 if (cell->value()->IsTheHole(isolate)) {
18777 index = dictionary->NextEnumerationIndex();
18778 dictionary->SetNextEnumerationIndex(index + 1);
18780 index = original_details.dictionary_index();
18782 DCHECK_LT(0, index);
18783 details = details.set_index(index);
18785 PropertyCellType new_type =
18786 UpdatedType(isolate, cell, value, original_details);
18788 cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
18792 details = details.set_cell_type(new_type);
18793 cell->set_property_details(details);
18795 if (new_type == PropertyCellType::kConstant ||
18796 new_type == PropertyCellType::kConstantType) {
18800 cell->set_value(*value);
18804 if (!invalidate && (old_type != new_type ||
18805 original_details.IsReadOnly() != details.IsReadOnly())) {
18806 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18807 isolate, DependentCode::kPropertyCellChangedGroup);
18814 void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
18815 Handle<PropertyCell> cell,
18816 Handle<Object> new_value) {
18817 if (cell->value() != *new_value) {
18818 cell->set_value(*new_value);
18819 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18820 isolate, DependentCode::kPropertyCellChangedGroup);
18824 int JSGeneratorObject::source_position()
const {
18825 CHECK(is_suspended());
18826 DCHECK(
function()->shared()->HasBytecodeArray());
18828 int code_offset = Smi::ToInt(input_or_debug_pos());
18832 code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
18833 AbstractCode code =
18834 AbstractCode::cast(
function()->shared()->GetBytecodeArray());
18835 return code->SourcePosition(code_offset);
18839 AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
18840 Handle<JSObject> receiver) {
18841 DisallowHeapAllocation no_gc;
18842 DCHECK(receiver->map()->is_access_check_needed());
18843 Object* maybe_constructor = receiver->map()->GetConstructor();
18844 if (maybe_constructor->IsFunctionTemplateInfo()) {
18846 FunctionTemplateInfo::cast(maybe_constructor)->GetAccessCheckInfo();
18847 if (data_obj->IsUndefined(isolate))
return nullptr;
18848 return AccessCheckInfo::cast(data_obj);
18851 if (!maybe_constructor->IsJSFunction())
return nullptr;
18852 JSFunction* constructor = JSFunction::cast(maybe_constructor);
18854 if (!constructor->shared()->IsApiFunction())
return nullptr;
18857 constructor->shared()->get_api_func_data()->GetAccessCheckInfo();
18858 if (data_obj->IsUndefined(isolate))
return nullptr;
18860 return AccessCheckInfo::cast(data_obj);
18863 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
18864 for (PrototypeIterator iter(isolate,
this, kStartAtReceiver,
18865 PrototypeIterator::END_AT_NULL);
18866 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
18867 if (iter.GetCurrent<Object>()->IsJSProxy())
return true;
18872 bool JSReceiver::HasComplexElements() {
18873 if (IsJSProxy())
return true;
18874 JSObject* this_object = JSObject::cast(
this);
18875 if (this_object->HasIndexedInterceptor()) {
18878 if (!this_object->HasDictionaryElements())
return false;
18879 return this_object->element_dictionary()->HasComplexElements();
18882 MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
18883 Isolate* isolate, Handle<Object> getter) {
18884 if (getter->IsFunctionTemplateInfo()) {
18885 Handle<FunctionTemplateInfo> fti =
18886 Handle<FunctionTemplateInfo>::cast(getter);
18888 if (!fti->cached_property_name()->IsTheHole(isolate)) {
18889 return handle(Name::cast(fti->cached_property_name()), isolate);
18892 return MaybeHandle<Name>();
18895 Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
18896 DisallowHeapAllocation no_allocation;
18897 DisallowJavascriptExecution no_js(isolate);
18899 int x_value = Smi::ToInt(x);
18900 int y_value = Smi::ToInt(y);
18903 if (x_value == y_value)
return Smi::FromInt(0).ptr();
18907 if (x_value == 0 || y_value == 0) {
18908 return Smi::FromInt(x_value < y_value ? -1 : 1).ptr();
18919 if (x_value < 0 || y_value < 0) {
18920 if (y_value >= 0)
return Smi::FromInt(-1).ptr();
18921 if (x_value >= 0)
return Smi::FromInt(1).ptr();
18922 x_scaled = -x_value;
18923 y_scaled = -y_value;
18927 static const uint32_t kPowersOf10[] = {
18929 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000,
18930 100 * 1000 * 1000, 1000 * 1000 * 1000};
18941 int x_log2 = 31 - base::bits::CountLeadingZeros(x_scaled);
18942 int x_log10 = ((x_log2 + 1) * 1233) >> 12;
18943 x_log10 -= x_scaled < kPowersOf10[x_log10];
18945 int y_log2 = 31 - base::bits::CountLeadingZeros(y_scaled);
18946 int y_log10 = ((y_log2 + 1) * 1233) >> 12;
18947 y_log10 -= y_scaled < kPowersOf10[y_log10];
18951 if (x_log10 < y_log10) {
18958 x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
18961 }
else if (y_log10 < x_log10) {
18962 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
18967 if (x_scaled < y_scaled)
return Smi::FromInt(-1).ptr();
18968 if (x_scaled > y_scaled)
return Smi::FromInt(1).ptr();
18969 return Smi::FromInt(tie).ptr();
18976 template class HashTable<StringTable, StringTableShape>;
18978 template class HashTable<CompilationCacheTable, CompilationCacheShape>;
18980 template class HashTable<ObjectHashTable, ObjectHashTableShape>;
18982 template class HashTable<EphemeronHashTable, EphemeronHashTableShape>;
18984 template class ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>;
18986 template class ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
18988 template class Dictionary<NameDictionary, NameDictionaryShape>;
18990 template class Dictionary<GlobalDictionary, GlobalDictionaryShape>;
18992 template class EXPORT_TEMPLATE_DEFINE(
18993 V8_EXPORT_PRIVATE) HashTable<NumberDictionary, NumberDictionaryShape>;
18995 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
18996 Dictionary<NumberDictionary, NumberDictionaryShape>;
18998 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
18999 HashTable<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
19001 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
19002 Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
19004 template Handle<NameDictionary>
19005 BaseNameDictionary<NameDictionary, NameDictionaryShape>::New(
19006 Isolate*,
int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
19008 template Handle<GlobalDictionary>
19009 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::New(
19010 Isolate*,
int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
19012 template Handle<NameDictionary>
19013 HashTable<NameDictionary, NameDictionaryShape>::New(Isolate*,
int,
19017 template Handle<ObjectHashSet>
19018 HashTable<ObjectHashSet, ObjectHashSetShape>::New(Isolate*,
int n,
19022 template Handle<NameDictionary>
19023 HashTable<NameDictionary, NameDictionaryShape>::Shrink(Isolate* isolate,
19024 Handle<NameDictionary>,
19025 int additionalCapacity);
19027 template Handle<NameDictionary>
19028 BaseNameDictionary<NameDictionary, NameDictionaryShape>::Add(
19029 Isolate* isolate, Handle<NameDictionary>, Handle<Name>, Handle<Object>,
19030 PropertyDetails,
int*);
19032 template Handle<GlobalDictionary>
19033 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::Add(
19034 Isolate* isolate, Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
19035 PropertyDetails,
int*);
19037 template void HashTable<GlobalDictionary, GlobalDictionaryShape>::Rehash(
19040 template Handle<NameDictionary>
19041 BaseNameDictionary<NameDictionary, NameDictionaryShape>::EnsureCapacity(
19042 Isolate* isolate, Handle<NameDictionary>,
int);
19045 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CopyEnumKeysTo(
19046 Isolate* isolate, Handle<GlobalDictionary> dictionary,
19048 KeyAccumulator* accumulator);
19051 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CopyEnumKeysTo(
19052 Isolate* isolate, Handle<NameDictionary> dictionary,
19054 KeyAccumulator* accumulator);
19056 template Handle<FixedArray>
19057 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::IterationIndices(
19058 Isolate* isolate, Handle<GlobalDictionary> dictionary);
19060 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CollectKeysTo(
19061 Handle<GlobalDictionary> dictionary, KeyAccumulator* keys);
19063 template Handle<FixedArray>
19064 BaseNameDictionary<NameDictionary, NameDictionaryShape>::IterationIndices(
19065 Isolate* isolate, Handle<NameDictionary> dictionary);
19067 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CollectKeysTo(
19068 Handle<NameDictionary> dictionary, KeyAccumulator* keys);
19070 void JSWeakFactory::Cleanup(Handle<JSWeakFactory> weak_factory,
19071 Isolate* isolate) {
19075 if (!weak_factory->cleared_cells()->IsUndefined(isolate)) {
19077 Handle<JSWeakFactoryCleanupIterator> iterator;
19079 Handle<Map> cleanup_iterator_map(
19080 isolate->native_context()->js_weak_factory_cleanup_iterator_map(),
19082 iterator = Handle<JSWeakFactoryCleanupIterator>::cast(
19083 isolate->factory()->NewJSObjectFromMap(
19084 cleanup_iterator_map, NOT_TENURED,
19085 Handle<AllocationSite>::null()));
19086 iterator->set_factory(*weak_factory);
19088 Handle<Object> cleanup(weak_factory->cleanup(), isolate);
19090 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
19092 MaybeHandle<Object> exception;
19093 Handle<Object> args[] = {iterator};
19094 bool has_pending_exception = !ToLocal<Value>(
19095 Execution::TryCall(
19097 handle(ReadOnlyRoots(isolate).undefined_value(), isolate), 1, args,
19098 Execution::MessageHandling::kReport, &exception,
19099 Execution::Target::kCallable),
19102 USE(has_pending_exception);
virtual const uint16_t * data() const =0
virtual bool IsCacheable() const
virtual const char * data() const =0
virtual size_t length() const =0
virtual size_t length() const =0