Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/objects.h"
6 :
7 : #include <algorithm>
8 : #include <cmath>
9 : #include <memory>
10 : #include <sstream>
11 : #include <vector>
12 :
13 : #include "src/objects-inl.h"
14 :
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"
19 : #include "src/api.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/overflowing-math.h"
25 : #include "src/base/utils/random-number-generator.h"
26 : #include "src/bootstrapper.h"
27 : #include "src/builtins/builtins.h"
28 : #include "src/compiler.h"
29 : #include "src/counters-inl.h"
30 : #include "src/counters.h"
31 : #include "src/date.h"
32 : #include "src/debug/debug.h"
33 : #include "src/elements.h"
34 : #include "src/execution.h"
35 : #include "src/field-index-inl.h"
36 : #include "src/field-index.h"
37 : #include "src/field-type.h"
38 : #include "src/frames-inl.h"
39 : #include "src/function-kind.h"
40 : #include "src/globals.h"
41 : #include "src/heap/heap-inl.h"
42 : #include "src/ic/ic.h"
43 : #include "src/identity-map.h"
44 : #include "src/isolate-inl.h"
45 : #include "src/keys.h"
46 : #include "src/log.h"
47 : #include "src/lookup-inl.h"
48 : #include "src/map-updater.h"
49 : #include "src/message-template.h"
50 : #include "src/microtask-queue.h"
51 : #include "src/objects-body-descriptors-inl.h"
52 : #include "src/objects/allocation-site-inl.h"
53 : #include "src/objects/api-callbacks.h"
54 : #include "src/objects/arguments-inl.h"
55 : #include "src/objects/bigint.h"
56 : #include "src/objects/cell-inl.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/embedder-data-array-inl.h"
61 : #include "src/objects/foreign.h"
62 : #include "src/objects/frame-array-inl.h"
63 : #include "src/objects/free-space-inl.h"
64 : #include "src/objects/hash-table-inl.h"
65 : #include "src/objects/js-array-inl.h"
66 : #ifdef V8_INTL_SUPPORT
67 : #include "src/objects/js-break-iterator.h"
68 : #include "src/objects/js-collator.h"
69 : #endif // V8_INTL_SUPPORT
70 : #include "src/objects/js-collection-inl.h"
71 : #ifdef V8_INTL_SUPPORT
72 : #include "src/objects/js-date-time-format.h"
73 : #endif // V8_INTL_SUPPORT
74 : #include "src/objects/js-generator-inl.h"
75 : #ifdef V8_INTL_SUPPORT
76 : #include "src/objects/js-list-format.h"
77 : #include "src/objects/js-locale.h"
78 : #include "src/objects/js-number-format.h"
79 : #include "src/objects/js-plural-rules.h"
80 : #endif // V8_INTL_SUPPORT
81 : #include "src/objects/js-regexp-inl.h"
82 : #include "src/objects/js-regexp-string-iterator.h"
83 : #ifdef V8_INTL_SUPPORT
84 : #include "src/objects/js-relative-time-format.h"
85 : #include "src/objects/js-segment-iterator.h"
86 : #include "src/objects/js-segmenter.h"
87 : #endif // V8_INTL_SUPPORT
88 : #include "src/objects/js-weak-refs-inl.h"
89 : #include "src/objects/literal-objects-inl.h"
90 : #include "src/objects/map-inl.h"
91 : #include "src/objects/map.h"
92 : #include "src/objects/microtask-inl.h"
93 : #include "src/objects/module-inl.h"
94 : #include "src/objects/promise-inl.h"
95 : #include "src/objects/slots-atomic-inl.h"
96 : #include "src/objects/stack-frame-info-inl.h"
97 : #include "src/objects/string-comparator.h"
98 : #include "src/objects/struct-inl.h"
99 : #include "src/ostreams.h"
100 : #include "src/parsing/preparse-data.h"
101 : #include "src/property-descriptor.h"
102 : #include "src/prototype.h"
103 : #include "src/regexp/jsregexp.h"
104 : #include "src/source-position-table.h"
105 : #include "src/string-builder-inl.h"
106 : #include "src/string-search.h"
107 : #include "src/string-stream.h"
108 : #include "src/transitions-inl.h"
109 : #include "src/unicode-decoder.h"
110 : #include "src/unicode-inl.h"
111 : #include "src/utils-inl.h"
112 : #include "src/wasm/wasm-engine.h"
113 : #include "src/wasm/wasm-objects.h"
114 : #include "src/zone/zone.h"
115 :
116 : namespace v8 {
117 : namespace internal {
118 :
119 205673 : ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw) {
120 211098 : if (should_throw.IsJust()) return should_throw.FromJust();
121 :
122 200248 : LanguageMode mode = isolate->context()->scope_info()->language_mode();
123 200248 : if (mode == LanguageMode::kStrict) return kThrowOnError;
124 :
125 582564 : for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
126 1130772 : if (!(it.frame()->is_optimized() || it.frame()->is_interpreted())) {
127 383962 : continue;
128 : }
129 : // Get the language mode from closure.
130 198577 : JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(it.frame());
131 : std::vector<SharedFunctionInfo> functions;
132 198577 : js_frame->GetFunctions(&functions);
133 198577 : LanguageMode closure_language_mode = functions.back()->language_mode();
134 198577 : if (closure_language_mode > mode) {
135 : mode = closure_language_mode;
136 : }
137 : break;
138 : }
139 :
140 198602 : return is_sloppy(mode) ? kDontThrow : kThrowOnError;
141 : }
142 :
143 4425393 : bool ComparisonResultToBool(Operation op, ComparisonResult result) {
144 4425393 : switch (op) {
145 : case Operation::kLessThan:
146 17519 : return result == ComparisonResult::kLessThan;
147 : case Operation::kLessThanOrEqual:
148 3121442 : return result == ComparisonResult::kLessThan ||
149 3121442 : result == ComparisonResult::kEqual;
150 : case Operation::kGreaterThan:
151 981 : return result == ComparisonResult::kGreaterThan;
152 : case Operation::kGreaterThanOrEqual:
153 1285451 : return result == ComparisonResult::kGreaterThan ||
154 1285451 : result == ComparisonResult::kEqual;
155 : default:
156 : break;
157 : }
158 0 : UNREACHABLE();
159 : }
160 :
161 39133 : std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
162 39133 : switch (instance_type) {
163 : #define WRITE_TYPE(TYPE) \
164 : case TYPE: \
165 : return os << #TYPE;
166 17 : INSTANCE_TYPE_LIST(WRITE_TYPE)
167 : #undef WRITE_TYPE
168 : }
169 0 : UNREACHABLE();
170 : }
171 :
172 16178688 : Handle<FieldType> Object::OptimalType(Isolate* isolate,
173 : Representation representation) {
174 16178688 : if (representation.IsNone()) return FieldType::None(isolate);
175 15963632 : if (FLAG_track_field_types) {
176 27403997 : if (representation.IsHeapObject() && IsHeapObject()) {
177 : // We can track only JavaScript objects with stable maps.
178 : Handle<Map> map(HeapObject::cast(*this)->map(), isolate);
179 19878514 : if (map->is_stable() && map->IsJSReceiverMap()) {
180 6123474 : return FieldType::Class(map, isolate);
181 : }
182 : }
183 : }
184 9840160 : return FieldType::Any(isolate);
185 : }
186 :
187 2018 : Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
188 : Representation representation) {
189 2018 : if (!representation.IsDouble()) return object;
190 : auto result = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
191 4036 : if (object->IsUninitialized(isolate)) {
192 : result->set_value_as_bits(kHoleNanInt64);
193 2716 : } else if (object->IsMutableHeapNumber()) {
194 : // Ensure that all bits of the double value are preserved.
195 : result->set_value_as_bits(
196 : MutableHeapNumber::cast(*object)->value_as_bits());
197 : } else {
198 2706 : result->set_value(object->Number());
199 : }
200 2018 : return result;
201 : }
202 :
203 15132994 : Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
204 : Representation representation) {
205 : DCHECK(!object->IsUninitialized(isolate));
206 15132994 : if (!representation.IsDouble()) {
207 : DCHECK(object->FitsRepresentation(representation));
208 15122362 : return object;
209 : }
210 : return isolate->factory()->NewHeapNumber(
211 10632 : MutableHeapNumber::cast(*object)->value());
212 : }
213 :
214 7102 : MaybeHandle<JSReceiver> Object::ToObjectImpl(Isolate* isolate,
215 : Handle<Object> object,
216 : const char* method_name) {
217 : DCHECK(!object->IsJSReceiver()); // Use ToObject() for fast path.
218 7102 : Handle<Context> native_context = isolate->native_context();
219 : Handle<JSFunction> constructor;
220 14204 : if (object->IsSmi()) {
221 1056 : constructor = handle(native_context->number_function(), isolate);
222 : } else {
223 : int constructor_function_index =
224 13148 : Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
225 6574 : if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
226 1698 : if (method_name != nullptr) {
227 900 : THROW_NEW_ERROR(
228 : isolate,
229 : NewTypeError(
230 : MessageTemplate::kCalledOnNullOrUndefined,
231 : isolate->factory()->NewStringFromAsciiChecked(method_name)),
232 : JSReceiver);
233 : }
234 1248 : THROW_NEW_ERROR(isolate,
235 : NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
236 : JSReceiver);
237 : }
238 : constructor = handle(
239 : JSFunction::cast(native_context->get(constructor_function_index)),
240 9752 : isolate);
241 : }
242 5404 : Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
243 10808 : Handle<JSValue>::cast(result)->set_value(*object);
244 5404 : return result;
245 : }
246 :
247 : // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
248 : // static
249 180 : MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
250 : Handle<Object> object) {
251 360 : if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
252 360 : if (object->IsNullOrUndefined(isolate)) {
253 6 : return isolate->global_proxy();
254 : }
255 174 : return Object::ToObject(isolate, object);
256 : }
257 :
258 : // static
259 3229488 : MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
260 : Handle<Object> input,
261 : Conversion mode) {
262 : while (true) {
263 6470062 : if (input->IsNumber()) {
264 106005 : return input;
265 : }
266 6258052 : if (input->IsString()) {
267 3214 : return String::ToNumber(isolate, Handle<String>::cast(input));
268 : }
269 6251624 : if (input->IsOddball()) {
270 3115314 : return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
271 : }
272 20996 : if (input->IsSymbol()) {
273 3773 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
274 : Object);
275 : }
276 13450 : if (input->IsBigInt()) {
277 581 : if (mode == Conversion::kToNumeric) return input;
278 : DCHECK_EQ(mode, Conversion::kToNumber);
279 581 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
280 : Object);
281 : }
282 12288 : ASSIGN_RETURN_ON_EXCEPTION(
283 : isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
284 : ToPrimitiveHint::kNumber),
285 : Object);
286 : }
287 : }
288 :
289 : // static
290 105511 : MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
291 : Handle<Object> input) {
292 211022 : ASSIGN_RETURN_ON_EXCEPTION(
293 : isolate, input,
294 : ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
295 210590 : if (input->IsSmi()) return input;
296 104395 : return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
297 : }
298 :
299 : // static
300 1316 : MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
301 : Handle<Object> input) {
302 2632 : ASSIGN_RETURN_ON_EXCEPTION(
303 : isolate, input,
304 : ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
305 2608 : if (input->IsSmi()) return input;
306 1118 : return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
307 : }
308 :
309 : // static
310 432509 : MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
311 : Handle<Object> input) {
312 865018 : ASSIGN_RETURN_ON_EXCEPTION(
313 : isolate, input,
314 : ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
315 1297317 : if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
316 294 : return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
317 : }
318 :
319 : // static
320 77523 : MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
321 : Handle<Object> input) {
322 155046 : ASSIGN_RETURN_ON_EXCEPTION(
323 : isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
324 : Name);
325 154574 : if (input->IsName()) return Handle<Name>::cast(input);
326 71650 : return ToString(isolate, input);
327 : }
328 :
329 : // ES6 7.1.14
330 : // static
331 486 : MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
332 : Handle<Object> value) {
333 : // 1. Let key be ToPrimitive(argument, hint String).
334 : MaybeHandle<Object> maybe_key =
335 486 : Object::ToPrimitive(value, ToPrimitiveHint::kString);
336 : // 2. ReturnIfAbrupt(key).
337 : Handle<Object> key;
338 486 : if (!maybe_key.ToHandle(&key)) return key;
339 : // 3. If Type(key) is Symbol, then return key.
340 972 : if (key->IsSymbol()) return key;
341 : // 4. Return ToString(key).
342 : // Extending spec'ed behavior, we'd be happy to return an element index.
343 972 : if (key->IsSmi()) return key;
344 972 : if (key->IsHeapNumber()) {
345 : uint32_t uint_value;
346 45 : if (value->ToArrayLength(&uint_value) &&
347 9 : uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
348 0 : return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
349 : }
350 : }
351 486 : return Object::ToString(isolate, key);
352 : }
353 :
354 : // static
355 8268076 : MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
356 : Handle<Object> input) {
357 : while (true) {
358 16903758 : if (input->IsOddball()) {
359 7981596 : return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
360 : }
361 11582694 : if (input->IsNumber()) {
362 262671 : return isolate->factory()->NumberToString(input);
363 : }
364 11057352 : if (input->IsSymbol()) {
365 2071 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
366 : String);
367 : }
368 11053210 : if (input->IsBigInt()) {
369 8842 : return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
370 : }
371 11035526 : ASSIGN_RETURN_ON_EXCEPTION(
372 : isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
373 : ToPrimitiveHint::kString),
374 : String);
375 : // The previous isString() check happened in Object::ToString and thus we
376 : // put it at the end of the loop in this helper.
377 11018972 : if (input->IsString()) {
378 5325683 : return Handle<String>::cast(input);
379 : }
380 : }
381 : }
382 :
383 : namespace {
384 :
385 32044 : bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
386 64088 : if (!object->IsJSReceiver()) return false;
387 : Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
388 64088 : return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
389 64088 : .FromMaybe(false);
390 : }
391 :
392 29579 : Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
393 59158 : return object->IsString() ? Handle<String>::cast(object)
394 59158 : : isolate->factory()->empty_string();
395 : }
396 :
397 5811 : Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
398 : Handle<Object> input) {
399 5811 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
400 :
401 : Handle<Name> name_key = isolate->factory()->name_string();
402 5811 : Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
403 5811 : Handle<String> name_str = AsStringOrEmpty(isolate, name);
404 :
405 : Handle<Name> msg_key = isolate->factory()->message_string();
406 5811 : Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
407 5811 : Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
408 :
409 5811 : if (name_str->length() == 0) return msg_str;
410 5793 : if (msg_str->length() == 0) return name_str;
411 :
412 5626 : IncrementalStringBuilder builder(isolate);
413 5626 : builder.AppendString(name_str);
414 : builder.AppendCString(": ");
415 5626 : builder.AppendString(msg_str);
416 :
417 11252 : return builder.Finish().ToHandleChecked();
418 : }
419 :
420 : } // namespace
421 :
422 : // static
423 3466798 : Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
424 : Handle<Object> input) {
425 3466798 : DisallowJavascriptExecution no_js(isolate);
426 :
427 17597028 : if (input->IsString() || input->IsNumber() || input->IsOddball()) {
428 6864806 : return Object::ToString(isolate, input).ToHandleChecked();
429 68790 : } else if (input->IsBigInt()) {
430 : MaybeHandle<String> maybe_string =
431 14 : BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
432 : Handle<String> result;
433 14 : if (maybe_string.ToHandle(&result)) return result;
434 : // BigInt-to-String conversion can fail on 32-bit platforms where
435 : // String::kMaxLength is too small to fit this BigInt.
436 : return isolate->factory()->NewStringFromStaticChars(
437 0 : "<a very large BigInt>");
438 68762 : } else if (input->IsFunction()) {
439 : // -- F u n c t i o n
440 : Handle<String> fun_str;
441 1044 : if (input->IsJSBoundFunction()) {
442 0 : fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
443 : } else {
444 : DCHECK(input->IsJSFunction());
445 522 : fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
446 : }
447 :
448 522 : if (fun_str->length() > 128) {
449 9 : IncrementalStringBuilder builder(isolate);
450 9 : builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
451 : builder.AppendCString("...<omitted>...");
452 : builder.AppendString(isolate->factory()->NewSubString(
453 9 : fun_str, fun_str->length() - 2, fun_str->length()));
454 :
455 18 : return builder.Finish().ToHandleChecked();
456 : }
457 513 : return fun_str;
458 67718 : } else if (input->IsSymbol()) {
459 : // -- S y m b o l
460 1815 : Handle<Symbol> symbol = Handle<Symbol>::cast(input);
461 :
462 1815 : IncrementalStringBuilder builder(isolate);
463 : builder.AppendCString("Symbol(");
464 3630 : if (symbol->name()->IsString()) {
465 1275 : builder.AppendString(handle(String::cast(symbol->name()), isolate));
466 : }
467 : builder.AppendCharacter(')');
468 :
469 3630 : return builder.Finish().ToHandleChecked();
470 64088 : } else if (input->IsJSReceiver()) {
471 : // -- J S R e c e i v e r
472 32044 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
473 : Handle<Object> to_string = JSReceiver::GetDataProperty(
474 32044 : receiver, isolate->factory()->toString_string());
475 :
476 96132 : if (IsErrorObject(isolate, input) ||
477 84528 : *to_string == *isolate->error_to_string()) {
478 : // When internally formatting error objects, use a side-effects-free
479 : // version of Error.prototype.toString independent of the actually
480 : // installed toString method.
481 28839 : return NoSideEffectsErrorToString(isolate, input);
482 52466 : } else if (*to_string == *isolate->object_to_string()) {
483 : Handle<Object> ctor = JSReceiver::GetDataProperty(
484 18182 : receiver, isolate->factory()->constructor_string());
485 36364 : if (ctor->IsFunction()) {
486 : Handle<String> ctor_name;
487 35914 : if (ctor->IsJSBoundFunction()) {
488 : ctor_name = JSBoundFunction::GetName(
489 0 : isolate, Handle<JSBoundFunction>::cast(ctor))
490 0 : .ToHandleChecked();
491 35914 : } else if (ctor->IsJSFunction()) {
492 : Handle<Object> ctor_name_obj =
493 17957 : JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
494 17957 : ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
495 : }
496 :
497 17957 : if (ctor_name->length() != 0) {
498 17217 : IncrementalStringBuilder builder(isolate);
499 : builder.AppendCString("#<");
500 17217 : builder.AppendString(ctor_name);
501 : builder.AppendCString(">");
502 :
503 34434 : return builder.Finish().ToHandleChecked();
504 : }
505 : }
506 : }
507 : }
508 :
509 : // At this point, input is either none of the above or a JSReceiver.
510 :
511 : Handle<JSReceiver> receiver;
512 18032 : if (input->IsJSReceiver()) {
513 9016 : receiver = Handle<JSReceiver>::cast(input);
514 : } else {
515 : // This is the only case where Object::ToObject throws.
516 : DCHECK(!input->IsSmi());
517 : int constructor_function_index =
518 0 : Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
519 0 : if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
520 0 : return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
521 : }
522 :
523 0 : receiver = Object::ToObjectImpl(isolate, input).ToHandleChecked();
524 : }
525 :
526 18032 : Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
527 : Handle<Object> tag_obj = JSReceiver::GetDataProperty(
528 9016 : receiver, isolate->factory()->to_string_tag_symbol());
529 : Handle<String> tag =
530 18032 : tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
531 :
532 9016 : IncrementalStringBuilder builder(isolate);
533 : builder.AppendCString("[object ");
534 9016 : builder.AppendString(tag);
535 : builder.AppendCString("]");
536 :
537 18032 : return builder.Finish().ToHandleChecked();
538 : }
539 :
540 : // static
541 2322 : MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
542 : Handle<Object> input) {
543 4644 : ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
544 4302 : if (input->IsSmi()) {
545 1647 : int value = std::max(Smi::ToInt(*input), 0);
546 549 : return handle(Smi::FromInt(value), isolate);
547 : }
548 1602 : double len = DoubleToInteger(input->Number());
549 1602 : if (len <= 0.0) {
550 1179 : return handle(Smi::kZero, isolate);
551 423 : } else if (len >= kMaxSafeInteger) {
552 : len = kMaxSafeInteger;
553 : }
554 423 : return isolate->factory()->NewNumber(len);
555 : }
556 :
557 : // static
558 1273 : MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
559 : Handle<Object> input,
560 : MessageTemplate error_index) {
561 3351 : if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
562 936 : ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
563 1012 : if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
564 396 : double len = DoubleToInteger(input->Number()) + 0.0;
565 396 : auto js_len = isolate->factory()->NewNumber(len);
566 396 : if (len < 0.0 || len > kMaxSafeInteger) {
567 108 : THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
568 : }
569 288 : return js_len;
570 : }
571 :
572 90195168 : bool Object::BooleanValue(Isolate* isolate) {
573 90195240 : if (IsSmi()) return Smi::ToInt(*this) != 0;
574 : DCHECK(IsHeapObject());
575 91472990 : if (IsBoolean()) return IsTrue(isolate);
576 88905953 : if (IsNullOrUndefined(isolate)) return false;
577 87923673 : if (IsUndetectable()) return false; // Undetectable object is false.
578 95424891 : if (IsString()) return String::cast(*this)->length() != 0;
579 80885347 : if (IsHeapNumber()) return DoubleToBoolean(HeapNumber::cast(*this)->value());
580 79965030 : if (IsBigInt()) return BigInt::cast(*this)->ToBoolean();
581 : return true;
582 : }
583 :
584 0 : Object Object::ToBoolean(Isolate* isolate) {
585 0 : if (IsBoolean()) return *this;
586 0 : return isolate->heap()->ToBoolean(BooleanValue(isolate));
587 : }
588 :
589 : namespace {
590 :
591 : // TODO(bmeurer): Maybe we should introduce a marker interface Number,
592 : // where we put all these methods at some point?
593 : ComparisonResult NumberCompare(double x, double y) {
594 528 : if (std::isnan(x) || std::isnan(y)) {
595 : return ComparisonResult::kUndefined;
596 384 : } else if (x < y) {
597 : return ComparisonResult::kLessThan;
598 208 : } else if (x > y) {
599 : return ComparisonResult::kGreaterThan;
600 : } else {
601 : return ComparisonResult::kEqual;
602 : }
603 : }
604 :
605 : bool NumberEquals(double x, double y) {
606 : // Must check explicitly for NaN's on Windows, but -0 works fine.
607 10110 : if (std::isnan(x)) return false;
608 10028 : if (std::isnan(y)) return false;
609 9969 : return x == y;
610 : }
611 :
612 10110 : bool NumberEquals(const Object x, const Object y) {
613 20220 : return NumberEquals(x->Number(), y->Number());
614 : }
615 :
616 4156 : bool NumberEquals(Handle<Object> x, Handle<Object> y) {
617 4156 : return NumberEquals(*x, *y);
618 : }
619 :
620 : ComparisonResult Reverse(ComparisonResult result) {
621 153 : if (result == ComparisonResult::kLessThan) {
622 : return ComparisonResult::kGreaterThan;
623 : }
624 135 : if (result == ComparisonResult::kGreaterThan) {
625 : return ComparisonResult::kLessThan;
626 : }
627 : return result;
628 : }
629 :
630 : } // anonymous namespace
631 :
632 : // static
633 929 : Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
634 : Handle<Object> y) {
635 : // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
636 3716 : if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
637 1858 : !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
638 : return Nothing<ComparisonResult>();
639 : }
640 2208 : if (x->IsString() && y->IsString()) {
641 : // ES6 section 7.2.11 Abstract Relational Comparison step 5.
642 : return Just(String::Compare(isolate, Handle<String>::cast(x),
643 32 : Handle<String>::cast(y)));
644 : }
645 2208 : if (x->IsBigInt() && y->IsString()) {
646 : return Just(BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
647 63 : Handle<String>::cast(y)));
648 : }
649 1954 : if (x->IsString() && y->IsBigInt()) {
650 : return Just(Reverse(BigInt::CompareToString(
651 63 : isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x))));
652 : }
653 : // ES6 section 7.2.11 Abstract Relational Comparison step 6.
654 3075 : if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
655 1533 : !Object::ToNumeric(isolate, y).ToHandle(&y)) {
656 : return Nothing<ComparisonResult>();
657 : }
658 :
659 1506 : bool x_is_number = x->IsNumber();
660 1506 : bool y_is_number = y->IsNumber();
661 753 : if (x_is_number && y_is_number) {
662 1584 : return Just(NumberCompare(x->Number(), y->Number()));
663 225 : } else if (!x_is_number && !y_is_number) {
664 : return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
665 45 : Handle<BigInt>::cast(y)));
666 180 : } else if (x_is_number) {
667 90 : return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
668 : } else {
669 90 : return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
670 : }
671 : }
672 :
673 :
674 : // static
675 156815 : Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
676 : Handle<Object> y) {
677 : // This is the generic version of Abstract Equality Comparison. Must be in
678 : // sync with CodeStubAssembler::Equal.
679 : while (true) {
680 313786 : if (x->IsNumber()) {
681 8978 : if (y->IsNumber()) {
682 4047 : return Just(NumberEquals(x, y));
683 884 : } else if (y->IsBoolean()) {
684 0 : return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
685 884 : } else if (y->IsString()) {
686 : return Just(NumberEquals(
687 64 : x, String::ToNumber(isolate, Handle<String>::cast(y))));
688 756 : } else if (y->IsBigInt()) {
689 378 : return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
690 0 : } else if (y->IsJSReceiver()) {
691 0 : if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
692 0 : .ToHandle(&y)) {
693 : return Nothing<bool>();
694 : }
695 : } else {
696 : return Just(false);
697 : }
698 304808 : } else if (x->IsString()) {
699 273802 : if (y->IsString()) {
700 : return Just(String::Equals(isolate, Handle<String>::cast(x),
701 136694 : Handle<String>::cast(y)));
702 414 : } else if (y->IsNumber()) {
703 45 : x = String::ToNumber(isolate, Handle<String>::cast(x));
704 45 : return Just(NumberEquals(x, y));
705 324 : } else if (y->IsBoolean()) {
706 0 : x = String::ToNumber(isolate, Handle<String>::cast(x));
707 0 : return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
708 324 : } else if (y->IsBigInt()) {
709 : return Just(BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
710 162 : Handle<String>::cast(x)));
711 0 : } else if (y->IsJSReceiver()) {
712 0 : if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
713 0 : .ToHandle(&y)) {
714 : return Nothing<bool>();
715 : }
716 : } else {
717 : return Just(false);
718 : }
719 31006 : } else if (x->IsBoolean()) {
720 1632 : if (y->IsOddball()) {
721 : return Just(x.is_identical_to(y));
722 432 : } else if (y->IsNumber()) {
723 0 : return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
724 432 : } else if (y->IsString()) {
725 0 : y = String::ToNumber(isolate, Handle<String>::cast(y));
726 0 : return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
727 432 : } else if (y->IsBigInt()) {
728 216 : x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
729 216 : return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
730 0 : } else if (y->IsJSReceiver()) {
731 0 : if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
732 0 : .ToHandle(&y)) {
733 : return Nothing<bool>();
734 : }
735 0 : x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
736 : } else {
737 : return Just(false);
738 : }
739 29374 : } else if (x->IsSymbol()) {
740 180 : if (y->IsSymbol()) {
741 : return Just(x.is_identical_to(y));
742 72 : } else if (y->IsJSReceiver()) {
743 0 : if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
744 0 : .ToHandle(&y)) {
745 : return Nothing<bool>();
746 : }
747 : } else {
748 : return Just(false);
749 : }
750 29194 : } else if (x->IsBigInt()) {
751 954 : if (y->IsBigInt()) {
752 81 : return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
753 : }
754 396 : return Equals(isolate, y, x);
755 28240 : } else if (x->IsJSReceiver()) {
756 28046 : if (y->IsJSReceiver()) {
757 : return Just(x.is_identical_to(y));
758 156 : } else if (y->IsUndetectable()) {
759 0 : return Just(x->IsUndetectable());
760 156 : } else if (y->IsBoolean()) {
761 0 : y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
762 156 : } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
763 156 : .ToHandle(&x)) {
764 : return Nothing<bool>();
765 : }
766 : } else {
767 485 : return Just(x->IsUndetectable() && y->IsUndetectable());
768 : }
769 : }
770 : }
771 :
772 9067 : bool Object::StrictEquals(Object that) {
773 9067 : if (this->IsNumber()) {
774 6495 : if (!that->IsNumber()) return false;
775 5954 : return NumberEquals(*this, that);
776 2572 : } else if (this->IsString()) {
777 1323 : if (!that->IsString()) return false;
778 1268 : return String::cast(*this)->Equals(String::cast(that));
779 1249 : } else if (this->IsBigInt()) {
780 90 : if (!that->IsBigInt()) return false;
781 72 : return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(that));
782 : }
783 1159 : return *this == that;
784 : }
785 :
786 : // static
787 12728 : Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
788 25456 : if (object->IsNumber()) return isolate->factory()->number_string();
789 24804 : if (object->IsOddball())
790 3130 : return handle(Oddball::cast(*object)->type_of(), isolate);
791 21674 : if (object->IsUndetectable()) {
792 : return isolate->factory()->undefined_string();
793 : }
794 21674 : if (object->IsString()) return isolate->factory()->string_string();
795 21228 : if (object->IsSymbol()) return isolate->factory()->symbol_string();
796 21130 : if (object->IsBigInt()) return isolate->factory()->bigint_string();
797 21094 : if (object->IsCallable()) return isolate->factory()->function_string();
798 : return isolate->factory()->object_string();
799 : }
800 :
801 :
802 : // static
803 36 : MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
804 : Handle<Object> rhs) {
805 144 : if (lhs->IsNumber() && rhs->IsNumber()) {
806 72 : return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
807 0 : } else if (lhs->IsString() && rhs->IsString()) {
808 : return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
809 0 : Handle<String>::cast(rhs));
810 : }
811 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
812 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
813 0 : if (lhs->IsString() || rhs->IsString()) {
814 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
815 : Object);
816 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
817 : Object);
818 : return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
819 0 : Handle<String>::cast(rhs));
820 : }
821 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
822 : Object);
823 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
824 : Object);
825 0 : return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
826 : }
827 :
828 :
829 : // static
830 107475 : MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
831 : Handle<Object> callable,
832 : Handle<Object> object) {
833 : // The {callable} must have a [[Call]] internal method.
834 214988 : if (!callable->IsCallable()) return isolate->factory()->false_value();
835 :
836 : // Check if {callable} is a bound function, and if so retrieve its
837 : // [[BoundTargetFunction]] and use that instead of {callable}.
838 214874 : if (callable->IsJSBoundFunction()) {
839 : Handle<Object> bound_callable(
840 882 : Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
841 588 : isolate);
842 294 : return Object::InstanceOf(isolate, object, bound_callable);
843 : }
844 :
845 : // If {object} is not a receiver, return false.
846 221484 : if (!object->IsJSReceiver()) return isolate->factory()->false_value();
847 :
848 : // Get the "prototype" of {callable}; raise an error if it's not a receiver.
849 : Handle<Object> prototype;
850 199890 : ASSIGN_RETURN_ON_EXCEPTION(
851 : isolate, prototype,
852 : Object::GetProperty(isolate, callable,
853 : isolate->factory()->prototype_string()),
854 : Object);
855 199890 : if (!prototype->IsJSReceiver()) {
856 99603 : THROW_NEW_ERROR(
857 : isolate,
858 : NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
859 : Object);
860 : }
861 :
862 : // Return whether or not {prototype} is in the prototype chain of {object}.
863 : Maybe<bool> result = JSReceiver::HasInPrototypeChain(
864 342 : isolate, Handle<JSReceiver>::cast(object), prototype);
865 342 : if (result.IsNothing()) return MaybeHandle<Object>();
866 342 : return isolate->factory()->ToBoolean(result.FromJust());
867 : }
868 :
869 : // static
870 10852 : MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
871 : Handle<Object> callable) {
872 : // The {callable} must be a receiver.
873 21704 : if (!callable->IsJSReceiver()) {
874 0 : THROW_NEW_ERROR(isolate,
875 : NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
876 : Object);
877 : }
878 :
879 : // Lookup the @@hasInstance method on {callable}.
880 : Handle<Object> inst_of_handler;
881 21704 : ASSIGN_RETURN_ON_EXCEPTION(
882 : isolate, inst_of_handler,
883 : Object::GetMethod(Handle<JSReceiver>::cast(callable),
884 : isolate->factory()->has_instance_symbol()),
885 : Object);
886 21704 : if (!inst_of_handler->IsUndefined(isolate)) {
887 : // Call the {inst_of_handler} on the {callable}.
888 : Handle<Object> result;
889 21692 : ASSIGN_RETURN_ON_EXCEPTION(
890 : isolate, result,
891 : Execution::Call(isolate, inst_of_handler, callable, 1, &object),
892 : Object);
893 10840 : return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
894 : }
895 :
896 : // The {callable} must have a [[Call]] internal method.
897 12 : if (!callable->IsCallable()) {
898 6 : THROW_NEW_ERROR(
899 : isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
900 : Object);
901 : }
902 :
903 : // Fall back to OrdinaryHasInstance with {callable} and {object}.
904 : Handle<Object> result;
905 0 : ASSIGN_RETURN_ON_EXCEPTION(
906 : isolate, result, Object::OrdinaryHasInstance(isolate, callable, object),
907 : Object);
908 0 : return result;
909 : }
910 :
911 : // static
912 10792484 : MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
913 : Handle<Name> name) {
914 : Handle<Object> func;
915 : Isolate* isolate = receiver->GetIsolate();
916 21584968 : ASSIGN_RETURN_ON_EXCEPTION(
917 : isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
918 21536980 : if (func->IsNullOrUndefined(isolate)) {
919 9715775 : return isolate->factory()->undefined_value();
920 : }
921 2105430 : if (!func->IsCallable()) {
922 249 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
923 : func, name, receiver),
924 : Object);
925 : }
926 1052466 : return func;
927 : }
928 :
929 : namespace {
930 :
931 17652 : MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
932 : Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
933 17652 : if (element_types == ElementTypes::kAll) {
934 32964 : if (object->IsJSArray()) {
935 392 : Handle<JSArray> array = Handle<JSArray>::cast(object);
936 : uint32_t length;
937 1176 : if (!array->HasArrayPrototype(isolate) ||
938 2172 : !array->length()->ToUint32(&length) || !array->HasFastElements() ||
939 604 : !JSObject::PrototypeHasNoElements(isolate, *array)) {
940 276 : return MaybeHandle<FixedArray>();
941 : }
942 232 : return array->GetElementsAccessor()->CreateListFromArrayLike(
943 232 : isolate, array, length);
944 32180 : } else if (object->IsJSTypedArray()) {
945 595 : Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
946 : size_t length = array->length_value();
947 595 : if (array->WasDetached() ||
948 : length > static_cast<size_t>(FixedArray::kMaxLength)) {
949 0 : return MaybeHandle<FixedArray>();
950 : }
951 1190 : return array->GetElementsAccessor()->CreateListFromArrayLike(
952 1190 : isolate, array, static_cast<uint32_t>(length));
953 : }
954 : }
955 16665 : return MaybeHandle<FixedArray>();
956 : }
957 :
958 : } // namespace
959 :
960 : // static
961 17652 : MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
962 : Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
963 : // Fast-path for JSArray and JSTypedArray.
964 : MaybeHandle<FixedArray> fast_result =
965 17652 : CreateListFromArrayLikeFastPath(isolate, object, element_types);
966 17652 : if (!fast_result.is_null()) return fast_result;
967 : // 1. ReturnIfAbrupt(object).
968 : // 2. (default elementTypes -- not applicable.)
969 : // 3. If Type(obj) is not Object, throw a TypeError exception.
970 33882 : if (!object->IsJSReceiver()) {
971 918 : THROW_NEW_ERROR(isolate,
972 : NewTypeError(MessageTemplate::kCalledOnNonObject,
973 : isolate->factory()->NewStringFromAsciiChecked(
974 : "CreateListFromArrayLike")),
975 : FixedArray);
976 : }
977 :
978 : // 4. Let len be ? ToLength(? Get(obj, "length")).
979 16482 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
980 : Handle<Object> raw_length_number;
981 32964 : ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
982 : Object::GetLengthFromArrayLike(isolate, receiver),
983 : FixedArray);
984 : uint32_t len;
985 32883 : if (!raw_length_number->ToUint32(&len) ||
986 16437 : len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
987 27 : THROW_NEW_ERROR(isolate,
988 : NewRangeError(MessageTemplate::kInvalidArrayLength),
989 : FixedArray);
990 : }
991 : // 5. Let list be an empty List.
992 16419 : Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
993 : // 6. Let index be 0.
994 : // 7. Repeat while index < len:
995 40159851 : for (uint32_t index = 0; index < len; ++index) {
996 : // 7a. Let indexName be ToString(index).
997 : // 7b. Let next be ? Get(obj, indexName).
998 : Handle<Object> next;
999 80287008 : ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
1000 : JSReceiver::GetElement(isolate, receiver, index),
1001 : FixedArray);
1002 40143468 : switch (element_types) {
1003 : case ElementTypes::kAll:
1004 : // Nothing to do.
1005 : break;
1006 : case ElementTypes::kStringAndSymbol: {
1007 : // 7c. If Type(next) is not an element of elementTypes, throw a
1008 : // TypeError exception.
1009 6084 : if (!next->IsName()) {
1010 36 : THROW_NEW_ERROR(isolate,
1011 : NewTypeError(MessageTemplate::kNotPropertyName, next),
1012 : FixedArray);
1013 : }
1014 : // 7d. Append next as the last element of list.
1015 : // Internalize on the fly so we can use pointer identity later.
1016 3006 : next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
1017 3006 : break;
1018 : }
1019 : }
1020 80286864 : list->set(index, *next);
1021 : // 7e. Set index to index + 1. (See loop header.)
1022 : }
1023 : // 8. Return list.
1024 16347 : return list;
1025 : }
1026 :
1027 :
1028 : // static
1029 54516 : MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
1030 : Handle<JSReceiver> object) {
1031 : Handle<Object> val;
1032 : Handle<Name> key = isolate->factory()->length_string();
1033 109032 : ASSIGN_RETURN_ON_EXCEPTION(
1034 : isolate, val, JSReceiver::GetProperty(isolate, object, key), Object);
1035 54417 : return Object::ToLength(isolate, val);
1036 : }
1037 :
1038 : // static
1039 114636842 : MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
1040 : OnNonExistent on_non_existent) {
1041 93146552 : for (; it->IsFound(); it->Next()) {
1042 24479576 : switch (it->state()) {
1043 : case LookupIterator::NOT_FOUND:
1044 : case LookupIterator::TRANSITION:
1045 0 : UNREACHABLE();
1046 : case LookupIterator::JSPROXY: {
1047 : bool was_found;
1048 : Handle<Object> receiver = it->GetReceiver();
1049 : // In case of global IC, the receiver is the global object. Replace by
1050 : // the global proxy.
1051 346602 : if (receiver->IsJSGlobalObject()) {
1052 : receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(),
1053 200 : it->isolate());
1054 : }
1055 : MaybeHandle<Object> result =
1056 : JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
1057 346602 : it->GetName(), receiver, &was_found);
1058 173301 : if (!was_found) it->NotFound();
1059 173301 : return result;
1060 : }
1061 : case LookupIterator::INTERCEPTOR: {
1062 : bool done;
1063 : Handle<Object> result;
1064 228256 : ASSIGN_RETURN_ON_EXCEPTION(
1065 : it->isolate(), result,
1066 : JSObject::GetPropertyWithInterceptor(it, &done), Object);
1067 114110 : if (done) return result;
1068 110916 : break;
1069 : }
1070 : case LookupIterator::ACCESS_CHECK:
1071 669867 : if (it->HasAccess()) break;
1072 1174 : return JSObject::GetPropertyWithFailedAccessCheck(it);
1073 : case LookupIterator::ACCESSOR:
1074 896441 : return GetPropertyWithAccessor(it);
1075 : case LookupIterator::INTEGER_INDEXED_EXOTIC:
1076 2780 : return it->isolate()->factory()->undefined_value();
1077 : case LookupIterator::DATA:
1078 22623070 : return it->GetDataValue();
1079 : }
1080 : }
1081 :
1082 22093707 : if (on_non_existent == OnNonExistent::kThrowReferenceError) {
1083 35 : THROW_NEW_ERROR(it->isolate(),
1084 : NewReferenceError(MessageTemplate::kNotDefined, it->name()),
1085 : Object);
1086 : }
1087 22093672 : return it->isolate()->factory()->undefined_value();
1088 : }
1089 :
1090 :
1091 : // static
1092 173301 : MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
1093 : Handle<JSProxy> proxy,
1094 : Handle<Name> name,
1095 : Handle<Object> receiver,
1096 : bool* was_found) {
1097 173301 : *was_found = true;
1098 :
1099 : DCHECK(!name->IsPrivate());
1100 173301 : STACK_CHECK(isolate, MaybeHandle<Object>());
1101 : Handle<Name> trap_name = isolate->factory()->get_string();
1102 : // 1. Assert: IsPropertyKey(P) is true.
1103 : // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1104 : Handle<Object> handler(proxy->handler(), isolate);
1105 : // 3. If handler is null, throw a TypeError exception.
1106 : // 4. Assert: Type(handler) is Object.
1107 346276 : if (proxy->IsRevoked()) {
1108 36 : THROW_NEW_ERROR(isolate,
1109 : NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1110 : Object);
1111 : }
1112 : // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
1113 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1114 : // 6. Let trap be ? GetMethod(handler, "get").
1115 : Handle<Object> trap;
1116 346204 : ASSIGN_RETURN_ON_EXCEPTION(
1117 : isolate, trap,
1118 : Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
1119 : // 7. If trap is undefined, then
1120 298964 : if (trap->IsUndefined(isolate)) {
1121 : // 7.a Return target.[[Get]](P, Receiver).
1122 : LookupIterator it =
1123 117800 : LookupIterator::PropertyOrElement(isolate, receiver, name, target);
1124 117800 : MaybeHandle<Object> result = Object::GetProperty(&it);
1125 235600 : *was_found = it.IsFound();
1126 117800 : return result;
1127 : }
1128 : // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
1129 : Handle<Object> trap_result;
1130 31682 : Handle<Object> args[] = {target, name, receiver};
1131 63364 : ASSIGN_RETURN_ON_EXCEPTION(
1132 : isolate, trap_result,
1133 : Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
1134 :
1135 : MaybeHandle<Object> result =
1136 24513 : JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
1137 24513 : if (result.is_null()) {
1138 45 : return result;
1139 : }
1140 :
1141 : // 11. Return trap_result
1142 24468 : return trap_result;
1143 : }
1144 :
1145 : // static
1146 26898 : MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
1147 : Handle<Name> name,
1148 : Handle<JSReceiver> target,
1149 : Handle<Object> trap_result,
1150 : AccessKind access_kind) {
1151 : // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
1152 : PropertyDescriptor target_desc;
1153 : Maybe<bool> target_found =
1154 26898 : JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
1155 26898 : MAYBE_RETURN_NULL(target_found);
1156 : // 10. If targetDesc is not undefined, then
1157 26889 : if (target_found.FromJust()) {
1158 : // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
1159 : // false and targetDesc.[[Writable]] is false, then
1160 : // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
1161 : // throw a TypeError exception.
1162 7794 : bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
1163 2430 : !target_desc.configurable() &&
1164 9828 : !target_desc.writable() &&
1165 9828 : !trap_result->SameValue(*target_desc.value());
1166 8172 : if (inconsistent) {
1167 234 : if (access_kind == kGet) {
1168 54 : THROW_NEW_ERROR(
1169 : isolate,
1170 : NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
1171 : target_desc.value(), trap_result),
1172 : Object);
1173 : } else {
1174 : isolate->Throw(*isolate->factory()->NewTypeError(
1175 360 : MessageTemplate::kProxySetFrozenData, name));
1176 180 : return MaybeHandle<Object>();
1177 : }
1178 : }
1179 : // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
1180 : // is false and targetDesc.[[Get]] is undefined, then
1181 : // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
1182 7938 : if (access_kind == kGet) {
1183 0 : inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1184 0 : !target_desc.configurable() &&
1185 13104 : target_desc.get()->IsUndefined(isolate) &&
1186 6552 : !trap_result->IsUndefined(isolate);
1187 : } else {
1188 378 : inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1189 1575 : !target_desc.configurable() &&
1190 1575 : target_desc.set()->IsUndefined(isolate);
1191 : }
1192 7938 : if (inconsistent) {
1193 189 : if (access_kind == kGet) {
1194 0 : THROW_NEW_ERROR(
1195 : isolate,
1196 : NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
1197 : name, trap_result),
1198 : Object);
1199 : } else {
1200 : isolate->Throw(*isolate->factory()->NewTypeError(
1201 378 : MessageTemplate::kProxySetFrozenAccessor, name));
1202 189 : return MaybeHandle<Object>();
1203 : }
1204 : }
1205 : }
1206 26466 : return isolate->factory()->undefined_value();
1207 : }
1208 :
1209 :
1210 :
1211 8377826 : bool Object::ToInt32(int32_t* value) {
1212 8377828 : if (IsSmi()) {
1213 8377657 : *value = Smi::ToInt(*this);
1214 8377658 : return true;
1215 : }
1216 171 : if (IsHeapNumber()) {
1217 : double num = HeapNumber::cast(*this)->value();
1218 : // Check range before conversion to avoid undefined behavior.
1219 135 : if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1220 0 : *value = FastD2I(num);
1221 0 : return true;
1222 : }
1223 : }
1224 : return false;
1225 : }
1226 :
1227 : // static constexpr object declarations need a definition to make the
1228 : // compiler happy.
1229 : constexpr Object Smi::kZero;
1230 : constexpr Object SharedFunctionInfo::kNoSharedNameSentinel;
1231 :
1232 3624110 : Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
1233 : Isolate* isolate, Handle<FunctionTemplateInfo> info,
1234 : MaybeHandle<Name> maybe_name) {
1235 3624110 : Object current_info = info->shared_function_info();
1236 3624109 : if (current_info->IsSharedFunctionInfo()) {
1237 : return handle(SharedFunctionInfo::cast(current_info), isolate);
1238 : }
1239 : Handle<Name> name;
1240 : Handle<String> name_string;
1241 10296349 : if (maybe_name.ToHandle(&name) && name->IsString()) {
1242 3391490 : name_string = Handle<String>::cast(name);
1243 243738 : } else if (info->class_name()->IsString()) {
1244 : name_string = handle(String::cast(info->class_name()), isolate);
1245 : } else {
1246 : name_string = isolate->factory()->empty_string();
1247 : }
1248 : FunctionKind function_kind;
1249 3513359 : if (info->remove_prototype()) {
1250 : function_kind = kConciseMethod;
1251 : } else {
1252 : function_kind = kNormalFunction;
1253 : }
1254 : Handle<SharedFunctionInfo> result =
1255 : isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info,
1256 7026718 : function_kind);
1257 :
1258 : result->set_length(info->length());
1259 : result->DontAdaptArguments();
1260 : DCHECK(result->IsApiFunction());
1261 :
1262 7026715 : info->set_shared_function_info(*result);
1263 3513357 : return result;
1264 : }
1265 :
1266 5343 : bool FunctionTemplateInfo::IsTemplateFor(Map map) {
1267 : // There is a constraint on the object; check.
1268 5343 : if (!map->IsJSObjectMap()) return false;
1269 : // Fetch the constructor function of the object.
1270 5343 : Object cons_obj = map->GetConstructor();
1271 5343 : Object type;
1272 5343 : if (cons_obj->IsJSFunction()) {
1273 5329 : JSFunction fun = JSFunction::cast(cons_obj);
1274 10658 : type = fun->shared()->function_data();
1275 14 : } else if (cons_obj->IsFunctionTemplateInfo()) {
1276 14 : type = FunctionTemplateInfo::cast(cons_obj);
1277 : } else {
1278 : return false;
1279 : }
1280 : // Iterate through the chain of inheriting function templates to
1281 : // see if the required one occurs.
1282 6420 : while (type->IsFunctionTemplateInfo()) {
1283 5255 : if (type == *this) return true;
1284 1077 : type = FunctionTemplateInfo::cast(type)->GetParentTemplate();
1285 : }
1286 : // Didn't find the required type in the inheritance chain.
1287 : return false;
1288 : }
1289 :
1290 : // static
1291 564226 : FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData(
1292 : Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
1293 : DCHECK(function_template_info->rare_data()->IsUndefined(isolate));
1294 : Handle<Struct> struct_obj =
1295 564226 : isolate->factory()->NewStruct(FUNCTION_TEMPLATE_RARE_DATA_TYPE, TENURED);
1296 : Handle<FunctionTemplateRareData> rare_data =
1297 564226 : i::Handle<FunctionTemplateRareData>::cast(struct_obj);
1298 1128452 : function_template_info->set_rare_data(*rare_data);
1299 564226 : return *rare_data;
1300 : }
1301 :
1302 : // static
1303 372033 : Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
1304 : Handle<FixedArray> list =
1305 372033 : isolate->factory()->NewFixedArray(kLengthIndex + size);
1306 372033 : list->set(kLengthIndex, Smi::kZero);
1307 372033 : return Handle<TemplateList>::cast(list);
1308 : }
1309 :
1310 : // static
1311 6053116 : Handle<TemplateList> TemplateList::Add(Isolate* isolate,
1312 : Handle<TemplateList> list,
1313 : Handle<i::Object> value) {
1314 : STATIC_ASSERT(kFirstElementIndex == 1);
1315 6053116 : int index = list->length() + 1;
1316 6053116 : Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
1317 6053116 : fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
1318 : fixed_array->set(kLengthIndex, Smi::FromInt(index));
1319 6053116 : return Handle<TemplateList>::cast(fixed_array);
1320 : }
1321 :
1322 :
1323 : // ES6 9.5.1
1324 : // static
1325 3711961 : MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1326 : Isolate* isolate = proxy->GetIsolate();
1327 : Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1328 :
1329 3711961 : STACK_CHECK(isolate, MaybeHandle<Object>());
1330 :
1331 : // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1332 : // 2. If handler is null, throw a TypeError exception.
1333 : // 3. Assert: Type(handler) is Object.
1334 : // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1335 7423904 : if (proxy->IsRevoked()) {
1336 18 : THROW_NEW_ERROR(isolate,
1337 : NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1338 : Object);
1339 : }
1340 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1341 : Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1342 :
1343 : // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1344 : Handle<Object> trap;
1345 7423868 : ASSIGN_RETURN_ON_EXCEPTION(isolate, trap,
1346 : Object::GetMethod(handler, trap_name), Object);
1347 : // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1348 7423868 : if (trap->IsUndefined(isolate)) {
1349 2789956 : return JSReceiver::GetPrototype(isolate, target);
1350 : }
1351 : // 7. Let handlerProto be ? Call(trap, handler, «target»).
1352 : Handle<Object> argv[] = {target};
1353 : Handle<Object> handler_proto;
1354 1843956 : ASSIGN_RETURN_ON_EXCEPTION(
1355 : isolate, handler_proto,
1356 : Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
1357 : // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1358 1843812 : if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1359 9 : THROW_NEW_ERROR(isolate,
1360 : NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1361 : Object);
1362 : }
1363 : // 9. Let extensibleTarget be ? IsExtensible(target).
1364 921870 : Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1365 921870 : MAYBE_RETURN_NULL(is_extensible);
1366 : // 10. If extensibleTarget is true, return handlerProto.
1367 921870 : if (is_extensible.FromJust()) return handler_proto;
1368 : // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1369 : Handle<Object> target_proto;
1370 0 : ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1371 : JSReceiver::GetPrototype(isolate, target), Object);
1372 : // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1373 0 : if (!handler_proto->SameValue(*target_proto)) {
1374 0 : THROW_NEW_ERROR(
1375 : isolate,
1376 : NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1377 : Object);
1378 : }
1379 : // 13. Return handlerProto.
1380 0 : return handler_proto;
1381 : }
1382 :
1383 896780 : MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1384 : Isolate* isolate = it->isolate();
1385 896780 : Handle<Object> structure = it->GetAccessors();
1386 : Handle<Object> receiver = it->GetReceiver();
1387 : // In case of global IC, the receiver is the global object. Replace by the
1388 : // global proxy.
1389 1793561 : if (receiver->IsJSGlobalObject()) {
1390 4064 : receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1391 : }
1392 :
1393 : // We should never get here to initialize a const with the hole value since a
1394 : // const declaration would conflict with the getter.
1395 : DCHECK(!structure->IsForeign());
1396 :
1397 : // API style callbacks.
1398 : Handle<JSObject> holder = it->GetHolder<JSObject>();
1399 1793558 : if (structure->IsAccessorInfo()) {
1400 633744 : Handle<Name> name = it->GetName();
1401 633743 : Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1402 633744 : if (!info->IsCompatibleReceiver(*receiver)) {
1403 90 : THROW_NEW_ERROR(isolate,
1404 : NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1405 : name, receiver),
1406 : Object);
1407 : }
1408 :
1409 633775 : if (!info->has_getter()) return isolate->factory()->undefined_value();
1410 :
1411 862861 : if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1412 30 : ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1413 : Object::ConvertReceiver(isolate, receiver),
1414 : Object);
1415 : }
1416 :
1417 : PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1418 633535 : Just(kDontThrow));
1419 633535 : Handle<Object> result = args.CallAccessorGetter(info, name);
1420 633535 : RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1421 640973 : if (result.is_null()) return isolate->factory()->undefined_value();
1422 : Handle<Object> reboxed_result = handle(*result, isolate);
1423 624917 : if (info->replace_on_access() && receiver->IsJSReceiver()) {
1424 30 : RETURN_ON_EXCEPTION(isolate,
1425 : Accessors::ReplaceAccessorWithDataProperty(
1426 : receiver, holder, name, result),
1427 : Object);
1428 : }
1429 624886 : return reboxed_result;
1430 : }
1431 :
1432 : // AccessorPair with 'cached' private property.
1433 263035 : if (it->TryLookupCachedProperty()) {
1434 45 : return Object::GetProperty(it);
1435 : }
1436 :
1437 : // Regular accessor.
1438 : Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1439 525981 : if (getter->IsFunctionTemplateInfo()) {
1440 201676 : SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
1441 : return Builtins::InvokeApiFunction(
1442 : isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1443 201676 : nullptr, isolate->factory()->undefined_value());
1444 324302 : } else if (getter->IsCallable()) {
1445 : // TODO(rossberg): nicer would be to cast to some JSCallable here...
1446 : return Object::GetPropertyWithDefinedGetter(
1447 157839 : receiver, Handle<JSReceiver>::cast(getter));
1448 : }
1449 : // Getter is not a function.
1450 4313 : return isolate->factory()->undefined_value();
1451 : }
1452 :
1453 : // static
1454 0 : Address AccessorInfo::redirect(Address address, AccessorComponent component) {
1455 : ApiFunction fun(address);
1456 : DCHECK_EQ(ACCESSOR_GETTER, component);
1457 : ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1458 183928 : return ExternalReference::Create(&fun, type).address();
1459 : }
1460 :
1461 92966 : Address AccessorInfo::redirected_getter() const {
1462 92966 : Address accessor = v8::ToCData<Address>(getter());
1463 92966 : if (accessor == kNullAddress) return kNullAddress;
1464 91964 : return redirect(accessor, ACCESSOR_GETTER);
1465 : }
1466 :
1467 3401256 : Address CallHandlerInfo::redirected_callback() const {
1468 3401256 : Address address = v8::ToCData<Address>(callback());
1469 : ApiFunction fun(address);
1470 : ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
1471 6802512 : return ExternalReference::Create(&fun, type).address();
1472 : }
1473 :
1474 97382 : bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
1475 : Handle<Map> map) {
1476 97382 : if (!info->HasExpectedReceiverType()) return true;
1477 60 : if (!map->IsJSObjectMap()) return false;
1478 : return FunctionTemplateInfo::cast(info->expected_receiver_type())
1479 60 : ->IsTemplateFor(*map);
1480 : }
1481 :
1482 489199 : Maybe<bool> Object::SetPropertyWithAccessor(
1483 489199 : LookupIterator* it, Handle<Object> value,
1484 : Maybe<ShouldThrow> maybe_should_throw) {
1485 : Isolate* isolate = it->isolate();
1486 489199 : Handle<Object> structure = it->GetAccessors();
1487 : Handle<Object> receiver = it->GetReceiver();
1488 : // In case of global IC, the receiver is the global object. Replace by the
1489 : // global proxy.
1490 978398 : if (receiver->IsJSGlobalObject()) {
1491 15044 : receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1492 : }
1493 :
1494 : // We should never get here to initialize a const with the hole value since a
1495 : // const declaration would conflict with the setter.
1496 : DCHECK(!structure->IsForeign());
1497 :
1498 : // API style callbacks.
1499 : Handle<JSObject> holder = it->GetHolder<JSObject>();
1500 978398 : if (structure->IsAccessorInfo()) {
1501 247530 : Handle<Name> name = it->GetName();
1502 247530 : Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1503 247530 : if (!info->IsCompatibleReceiver(*receiver)) {
1504 : isolate->Throw(*isolate->factory()->NewTypeError(
1505 180 : MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1506 : return Nothing<bool>();
1507 : }
1508 :
1509 247440 : if (!info->has_setter()) {
1510 : // TODO(verwaest): We should not get here anymore once all AccessorInfos
1511 : // are marked as special_data_property. They cannot both be writable and
1512 : // not have a setter.
1513 : return Just(true);
1514 : }
1515 :
1516 488816 : if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1517 0 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1518 : isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1519 : Nothing<bool>());
1520 : }
1521 :
1522 : // The actual type of setter callback is either
1523 : // v8::AccessorNameSetterCallback or
1524 : // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
1525 : // AccessorInfo was created by the API or internally (see accessors.cc).
1526 : // Here we handle both cases using GenericNamedPropertySetterCallback and
1527 : // its Call method.
1528 : PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1529 247374 : maybe_should_throw);
1530 247374 : Handle<Object> result = args.CallAccessorSetter(info, name, value);
1531 : // In the case of AccessorNameSetterCallback, we know that the result value
1532 : // cannot have been set, so the result of Call will be null. In the case of
1533 : // AccessorNameBooleanSetterCallback, the result will either be null
1534 : // (signalling an exception) or a boolean Oddball.
1535 247374 : RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1536 247155 : if (result.is_null()) return Just(true);
1537 : DCHECK(result->BooleanValue(isolate) ||
1538 : GetShouldThrow(isolate, maybe_should_throw) == kDontThrow);
1539 253010 : return Just(result->BooleanValue(isolate));
1540 : }
1541 :
1542 : // Regular accessor.
1543 : Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1544 483338 : if (setter->IsFunctionTemplateInfo()) {
1545 1314 : SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
1546 657 : Handle<Object> argv[] = {value};
1547 1971 : RETURN_ON_EXCEPTION_VALUE(
1548 : isolate, Builtins::InvokeApiFunction(
1549 : isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
1550 : receiver, arraysize(argv), argv,
1551 : isolate->factory()->undefined_value()),
1552 : Nothing<bool>());
1553 : return Just(true);
1554 482024 : } else if (setter->IsCallable()) {
1555 : // TODO(rossberg): nicer would be to cast to some JSCallable here...
1556 : return SetPropertyWithDefinedSetter(
1557 229451 : receiver, Handle<JSReceiver>::cast(setter), value, maybe_should_throw);
1558 : }
1559 :
1560 28790 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, maybe_should_throw),
1561 : NewTypeError(MessageTemplate::kNoSetterInCallback,
1562 : it->GetName(), it->GetHolder<JSObject>()));
1563 : }
1564 :
1565 157838 : MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1566 : Handle<Object> receiver,
1567 : Handle<JSReceiver> getter) {
1568 : Isolate* isolate = getter->GetIsolate();
1569 :
1570 : // Platforms with simulators like arm/arm64 expose a funny issue. If the
1571 : // simulator has a separate JS stack pointer from the C++ stack pointer, it
1572 : // can miss C++ stack overflows in the stack guard at the start of JavaScript
1573 : // functions. It would be very expensive to check the C++ stack pointer at
1574 : // that location. The best solution seems to be to break the impasse by
1575 : // adding checks at possible recursion points. What's more, we don't put
1576 : // this stack check behind the USE_SIMULATOR define in order to keep
1577 : // behavior the same between hardware and simulators.
1578 : StackLimitCheck check(isolate);
1579 157838 : if (check.JsHasOverflowed()) {
1580 18 : isolate->StackOverflow();
1581 18 : return MaybeHandle<Object>();
1582 : }
1583 :
1584 157820 : return Execution::Call(isolate, getter, receiver, 0, nullptr);
1585 : }
1586 :
1587 229451 : Maybe<bool> Object::SetPropertyWithDefinedSetter(
1588 : Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value,
1589 : Maybe<ShouldThrow> should_throw) {
1590 : Isolate* isolate = setter->GetIsolate();
1591 :
1592 229451 : Handle<Object> argv[] = { value };
1593 458902 : RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1594 : arraysize(argv), argv),
1595 : Nothing<bool>());
1596 : return Just(true);
1597 : }
1598 :
1599 365296 : Map Object::GetPrototypeChainRootMap(Isolate* isolate) const {
1600 : DisallowHeapAllocation no_alloc;
1601 365296 : if (IsSmi()) {
1602 24937 : Context native_context = isolate->context()->native_context();
1603 24937 : return native_context->number_function()->initial_map();
1604 : }
1605 :
1606 : const HeapObject heap_object = HeapObject::cast(*this);
1607 340357 : return heap_object->map()->GetPrototypeChainRootMap(isolate);
1608 : }
1609 :
1610 10211465 : Smi Object::GetOrCreateHash(Isolate* isolate) {
1611 : DisallowHeapAllocation no_gc;
1612 10211465 : Object hash = Object::GetSimpleHash(*this);
1613 10211465 : if (hash->IsSmi()) return Smi::cast(hash);
1614 :
1615 : DCHECK(IsJSReceiver());
1616 20460 : return JSReceiver::cast(*this)->GetOrCreateIdentityHash(isolate);
1617 : }
1618 :
1619 726183 : bool Object::SameValue(Object other) {
1620 726183 : if (other == *this) return true;
1621 :
1622 171607 : if (IsNumber() && other->IsNumber()) {
1623 21016 : double this_value = Number();
1624 21016 : double other_value = other->Number();
1625 : // SameValue(NaN, NaN) is true.
1626 21016 : if (this_value != other_value) {
1627 18670 : return std::isnan(this_value) && std::isnan(other_value);
1628 : }
1629 : // SameValue(0.0, -0.0) is false.
1630 2346 : return (std::signbit(this_value) == std::signbit(other_value));
1631 : }
1632 212971 : if (IsString() && other->IsString()) {
1633 91386 : return String::cast(*this)->Equals(String::cast(other));
1634 : }
1635 29079 : if (IsBigInt() && other->IsBigInt()) {
1636 27 : return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1637 : }
1638 : return false;
1639 : }
1640 :
1641 23046573 : bool Object::SameValueZero(Object other) {
1642 23046573 : if (other == *this) return true;
1643 :
1644 27083580 : if (IsNumber() && other->IsNumber()) {
1645 9289070 : double this_value = Number();
1646 9289070 : double other_value = other->Number();
1647 : // +0 == -0 is true
1648 9289070 : return this_value == other_value ||
1649 0 : (std::isnan(this_value) && std::isnan(other_value));
1650 : }
1651 16994740 : if (IsString() && other->IsString()) {
1652 8187867 : return String::cast(*this)->Equals(String::cast(other));
1653 : }
1654 314726 : if (IsBigInt() && other->IsBigInt()) {
1655 0 : return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1656 : }
1657 : return false;
1658 : }
1659 :
1660 14529 : MaybeHandle<Object> Object::ArraySpeciesConstructor(
1661 : Isolate* isolate, Handle<Object> original_array) {
1662 14529 : Handle<Object> default_species = isolate->array_function();
1663 40152 : if (original_array->IsJSArray() &&
1664 35420 : Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
1665 9797 : isolate->IsArraySpeciesLookupChainIntact()) {
1666 8835 : return default_species;
1667 : }
1668 : Handle<Object> constructor = isolate->factory()->undefined_value();
1669 : Maybe<bool> is_array = Object::IsArray(original_array);
1670 5694 : MAYBE_RETURN_NULL(is_array);
1671 5694 : if (is_array.FromJust()) {
1672 4626 : ASSIGN_RETURN_ON_EXCEPTION(
1673 : isolate, constructor,
1674 : Object::GetProperty(isolate, original_array,
1675 : isolate->factory()->constructor_string()),
1676 : Object);
1677 4608 : if (constructor->IsConstructor()) {
1678 : Handle<Context> constructor_context;
1679 3984 : ASSIGN_RETURN_ON_EXCEPTION(
1680 : isolate, constructor_context,
1681 : JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
1682 : Object);
1683 5994 : if (*constructor_context != *isolate->native_context() &&
1684 2010 : *constructor == constructor_context->array_function()) {
1685 : constructor = isolate->factory()->undefined_value();
1686 : }
1687 : }
1688 4608 : if (constructor->IsJSReceiver()) {
1689 4020 : ASSIGN_RETURN_ON_EXCEPTION(
1690 : isolate, constructor,
1691 : JSReceiver::GetProperty(isolate,
1692 : Handle<JSReceiver>::cast(constructor),
1693 : isolate->factory()->species_symbol()),
1694 : Object);
1695 4002 : if (constructor->IsNull(isolate)) {
1696 : constructor = isolate->factory()->undefined_value();
1697 : }
1698 : }
1699 : }
1700 11352 : if (constructor->IsUndefined(isolate)) {
1701 3702 : return default_species;
1702 : } else {
1703 3948 : if (!constructor->IsConstructor()) {
1704 0 : THROW_NEW_ERROR(isolate,
1705 : NewTypeError(MessageTemplate::kSpeciesNotConstructor),
1706 : Object);
1707 : }
1708 1974 : return constructor;
1709 : }
1710 : }
1711 :
1712 : // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
1713 781 : V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
1714 : Isolate* isolate, Handle<JSReceiver> recv,
1715 : Handle<JSFunction> default_ctor) {
1716 : Handle<Object> ctor_obj;
1717 1562 : ASSIGN_RETURN_ON_EXCEPTION(
1718 : isolate, ctor_obj,
1719 : JSObject::GetProperty(isolate, recv,
1720 : isolate->factory()->constructor_string()),
1721 : Object);
1722 :
1723 1562 : if (ctor_obj->IsUndefined(isolate)) return default_ctor;
1724 :
1725 1544 : if (!ctor_obj->IsJSReceiver()) {
1726 0 : THROW_NEW_ERROR(isolate,
1727 : NewTypeError(MessageTemplate::kConstructorNotReceiver),
1728 : Object);
1729 : }
1730 :
1731 772 : Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
1732 :
1733 : Handle<Object> species;
1734 1544 : ASSIGN_RETURN_ON_EXCEPTION(
1735 : isolate, species,
1736 : JSObject::GetProperty(isolate, ctor,
1737 : isolate->factory()->species_symbol()),
1738 : Object);
1739 :
1740 1544 : if (species->IsNullOrUndefined(isolate)) {
1741 0 : return default_ctor;
1742 : }
1743 :
1744 1544 : if (species->IsConstructor()) return species;
1745 :
1746 0 : THROW_NEW_ERROR(
1747 : isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
1748 : }
1749 :
1750 0 : bool Object::IterationHasObservableEffects() {
1751 : // Check that this object is an array.
1752 0 : if (!IsJSArray()) return true;
1753 0 : JSArray array = JSArray::cast(*this);
1754 : Isolate* isolate = array->GetIsolate();
1755 :
1756 : #ifdef V8_ENABLE_FORCE_SLOW_PATH
1757 : if (isolate->force_slow_path()) return true;
1758 : #endif
1759 :
1760 : // Check that we have the original ArrayPrototype.
1761 0 : if (!array->map()->prototype()->IsJSObject()) return true;
1762 0 : JSObject array_proto = JSObject::cast(array->map()->prototype());
1763 0 : if (!isolate->is_initial_array_prototype(array_proto)) return true;
1764 :
1765 : // Check that the ArrayPrototype hasn't been modified in a way that would
1766 : // affect iteration.
1767 0 : if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
1768 :
1769 : // For FastPacked kinds, iteration will have the same effect as simply
1770 : // accessing each property in order.
1771 0 : ElementsKind array_kind = array->GetElementsKind();
1772 0 : if (IsFastPackedElementsKind(array_kind)) return false;
1773 :
1774 : // For FastHoley kinds, an element access on a hole would cause a lookup on
1775 : // the prototype. This could have different results if the prototype has been
1776 : // changed.
1777 0 : if (IsHoleyElementsKind(array_kind) &&
1778 0 : isolate->IsNoElementsProtectorIntact()) {
1779 : return false;
1780 : }
1781 0 : return true;
1782 : }
1783 :
1784 6817 : void Object::ShortPrint(FILE* out) const {
1785 6817 : OFStream os(out);
1786 6817 : os << Brief(*this);
1787 6817 : }
1788 :
1789 13506 : void Object::ShortPrint(StringStream* accumulator) const {
1790 13506 : std::ostringstream os;
1791 13506 : os << Brief(*this);
1792 27012 : accumulator->Add(os.str().c_str());
1793 13506 : }
1794 :
1795 110132 : void Object::ShortPrint(std::ostream& os) const { os << Brief(*this); }
1796 :
1797 2 : std::ostream& operator<<(std::ostream& os, const Object& obj) {
1798 : obj.ShortPrint(os);
1799 2 : return os;
1800 : }
1801 :
1802 0 : void MaybeObject::ShortPrint(FILE* out) {
1803 0 : OFStream os(out);
1804 0 : os << Brief(*this);
1805 0 : }
1806 :
1807 0 : void MaybeObject::ShortPrint(StringStream* accumulator) {
1808 0 : std::ostringstream os;
1809 0 : os << Brief(*this);
1810 0 : accumulator->Add(os.str().c_str());
1811 0 : }
1812 :
1813 0 : void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(*this); }
1814 :
1815 290368 : Brief::Brief(const Object v) : value(v->ptr()) {}
1816 0 : Brief::Brief(const MaybeObject v) : value(v.ptr()) {}
1817 :
1818 182879 : std::ostream& operator<<(std::ostream& os, const Brief& v) {
1819 182879 : MaybeObject maybe_object(v.value);
1820 182879 : Smi smi;
1821 182879 : HeapObject heap_object;
1822 182879 : if (maybe_object->ToSmi(&smi)) {
1823 : smi->SmiPrint(os);
1824 149678 : } else if (maybe_object->IsCleared()) {
1825 0 : os << "[cleared]";
1826 149678 : } else if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
1827 0 : os << "[weak] ";
1828 0 : heap_object->HeapObjectShortPrint(os);
1829 149678 : } else if (maybe_object->GetHeapObjectIfStrong(&heap_object)) {
1830 149678 : heap_object->HeapObjectShortPrint(os);
1831 : } else {
1832 0 : UNREACHABLE();
1833 : }
1834 182879 : return os;
1835 : }
1836 :
1837 725 : void Smi::SmiPrint(std::ostream& os) const { // NOLINT
1838 33926 : os << value();
1839 725 : }
1840 :
1841 :
1842 :
1843 149678 : void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
1844 149678 : os << AsHex(this->ptr(), kSystemPointerHexDigits, true) << " ";
1845 :
1846 149678 : if (IsString()) {
1847 : HeapStringAllocator allocator;
1848 : StringStream accumulator(&allocator);
1849 36064 : String::cast(*this)->StringShortPrint(&accumulator);
1850 108192 : os << accumulator.ToCString().get();
1851 : return;
1852 : }
1853 113614 : if (IsJSObject()) {
1854 : HeapStringAllocator allocator;
1855 : StringStream accumulator(&allocator);
1856 32568 : JSObject::cast(*this)->JSObjectShortPrint(&accumulator);
1857 97704 : os << accumulator.ToCString().get();
1858 : return;
1859 : }
1860 81046 : switch (map()->instance_type()) {
1861 : case MAP_TYPE: {
1862 1754 : os << "<Map";
1863 : Map mapInstance = Map::cast(*this);
1864 1754 : if (mapInstance->IsJSObjectMap()) {
1865 1754 : os << "(" << ElementsKindToString(mapInstance->elements_kind()) << ")";
1866 0 : } else if (mapInstance->instance_size() != kVariableSizeSentinel) {
1867 0 : os << "[" << mapInstance->instance_size() << "]";
1868 : }
1869 1754 : os << ">";
1870 1754 : } break;
1871 : case AWAIT_CONTEXT_TYPE: {
1872 0 : os << "<AwaitContext generator= ";
1873 : HeapStringAllocator allocator;
1874 : StringStream accumulator(&allocator);
1875 0 : Context::cast(*this)->extension()->ShortPrint(&accumulator);
1876 0 : os << accumulator.ToCString().get();
1877 : os << '>';
1878 : break;
1879 : }
1880 : case BLOCK_CONTEXT_TYPE:
1881 0 : os << "<BlockContext[" << Context::cast(*this)->length() << "]>";
1882 0 : break;
1883 : case CATCH_CONTEXT_TYPE:
1884 0 : os << "<CatchContext[" << Context::cast(*this)->length() << "]>";
1885 0 : break;
1886 : case DEBUG_EVALUATE_CONTEXT_TYPE:
1887 0 : os << "<DebugEvaluateContext[" << Context::cast(*this)->length() << "]>";
1888 0 : break;
1889 : case EVAL_CONTEXT_TYPE:
1890 0 : os << "<EvalContext[" << Context::cast(*this)->length() << "]>";
1891 0 : break;
1892 : case FUNCTION_CONTEXT_TYPE:
1893 0 : os << "<FunctionContext[" << Context::cast(*this)->length() << "]>";
1894 0 : break;
1895 : case MODULE_CONTEXT_TYPE:
1896 0 : os << "<ModuleContext[" << Context::cast(*this)->length() << "]>";
1897 0 : break;
1898 : case NATIVE_CONTEXT_TYPE:
1899 1148 : os << "<NativeContext[" << Context::cast(*this)->length() << "]>";
1900 574 : break;
1901 : case SCRIPT_CONTEXT_TYPE:
1902 0 : os << "<ScriptContext[" << Context::cast(*this)->length() << "]>";
1903 0 : break;
1904 : case WITH_CONTEXT_TYPE:
1905 0 : os << "<WithContext[" << Context::cast(*this)->length() << "]>";
1906 0 : break;
1907 : case SCRIPT_CONTEXT_TABLE_TYPE:
1908 0 : os << "<ScriptContextTable[" << FixedArray::cast(*this)->length() << "]>";
1909 0 : break;
1910 : case HASH_TABLE_TYPE:
1911 0 : os << "<HashTable[" << FixedArray::cast(*this)->length() << "]>";
1912 0 : break;
1913 : case ORDERED_HASH_MAP_TYPE:
1914 0 : os << "<OrderedHashMap[" << FixedArray::cast(*this)->length() << "]>";
1915 0 : break;
1916 : case ORDERED_HASH_SET_TYPE:
1917 0 : os << "<OrderedHashSet[" << FixedArray::cast(*this)->length() << "]>";
1918 0 : break;
1919 : case ORDERED_NAME_DICTIONARY_TYPE:
1920 0 : os << "<OrderedNameDictionary[" << FixedArray::cast(*this)->length()
1921 0 : << "]>";
1922 0 : break;
1923 : case NAME_DICTIONARY_TYPE:
1924 0 : os << "<NameDictionary[" << FixedArray::cast(*this)->length() << "]>";
1925 0 : break;
1926 : case GLOBAL_DICTIONARY_TYPE:
1927 0 : os << "<GlobalDictionary[" << FixedArray::cast(*this)->length() << "]>";
1928 0 : break;
1929 : case NUMBER_DICTIONARY_TYPE:
1930 0 : os << "<NumberDictionary[" << FixedArray::cast(*this)->length() << "]>";
1931 0 : break;
1932 : case SIMPLE_NUMBER_DICTIONARY_TYPE:
1933 0 : os << "<SimpleNumberDictionary[" << FixedArray::cast(*this)->length()
1934 0 : << "]>";
1935 0 : break;
1936 : case STRING_TABLE_TYPE:
1937 0 : os << "<StringTable[" << FixedArray::cast(*this)->length() << "]>";
1938 0 : break;
1939 : case FIXED_ARRAY_TYPE:
1940 0 : os << "<FixedArray[" << FixedArray::cast(*this)->length() << "]>";
1941 0 : break;
1942 : case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
1943 28 : os << "<ObjectBoilerplateDescription["
1944 28 : << FixedArray::cast(*this)->length() << "]>";
1945 28 : break;
1946 : case FIXED_DOUBLE_ARRAY_TYPE:
1947 0 : os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this)->length()
1948 0 : << "]>";
1949 0 : break;
1950 : case BYTE_ARRAY_TYPE:
1951 0 : os << "<ByteArray[" << ByteArray::cast(*this)->length() << "]>";
1952 0 : break;
1953 : case BYTECODE_ARRAY_TYPE:
1954 240 : os << "<BytecodeArray[" << BytecodeArray::cast(*this)->length() << "]>";
1955 240 : break;
1956 : case DESCRIPTOR_ARRAY_TYPE:
1957 15364 : os << "<DescriptorArray["
1958 30728 : << DescriptorArray::cast(*this)->number_of_descriptors() << "]>";
1959 15364 : break;
1960 : case TRANSITION_ARRAY_TYPE:
1961 125 : os << "<TransitionArray[" << TransitionArray::cast(*this)->length()
1962 125 : << "]>";
1963 125 : break;
1964 : case PROPERTY_ARRAY_TYPE:
1965 0 : os << "<PropertyArray[" << PropertyArray::cast(*this)->length() << "]>";
1966 0 : break;
1967 : case FEEDBACK_CELL_TYPE: {
1968 : {
1969 0 : ReadOnlyRoots roots = GetReadOnlyRoots();
1970 0 : os << "<FeedbackCell[";
1971 0 : if (map() == roots.no_closures_cell_map()) {
1972 0 : os << "no feedback";
1973 0 : } else if (map() == roots.no_closures_cell_map()) {
1974 0 : os << "no closures";
1975 0 : } else if (map() == roots.one_closure_cell_map()) {
1976 0 : os << "one closure";
1977 0 : } else if (map() == roots.many_closures_cell_map()) {
1978 0 : os << "many closures";
1979 : } else {
1980 0 : os << "!!!INVALID MAP!!!";
1981 : }
1982 0 : os << "]>";
1983 : }
1984 0 : break;
1985 : }
1986 : case FEEDBACK_VECTOR_TYPE:
1987 0 : os << "<FeedbackVector[" << FeedbackVector::cast(*this)->length() << "]>";
1988 0 : break;
1989 : case FREE_SPACE_TYPE:
1990 0 : os << "<FreeSpace[" << FreeSpace::cast(*this)->size() << "]>";
1991 0 : break;
1992 : #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype) \
1993 : case FIXED_##TYPE##_ARRAY_TYPE: \
1994 : os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(*this)->length() \
1995 : << "]>"; \
1996 : break;
1997 :
1998 0 : TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1999 : #undef TYPED_ARRAY_SHORT_PRINT
2000 :
2001 : case PREPARSE_DATA_TYPE: {
2002 : PreparseData data = PreparseData::cast(*this);
2003 0 : os << "<PreparseData[data=" << data->data_length()
2004 0 : << " children=" << data->children_length() << "]>";
2005 : break;
2006 : }
2007 :
2008 : case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE: {
2009 : UncompiledDataWithoutPreparseData data =
2010 : UncompiledDataWithoutPreparseData::cast(*this);
2011 0 : os << "<UncompiledDataWithoutPreparseData (" << data->start_position()
2012 0 : << ", " << data->end_position() << ")]>";
2013 : break;
2014 : }
2015 :
2016 : case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE: {
2017 : UncompiledDataWithPreparseData data =
2018 0 : UncompiledDataWithPreparseData::cast(*this);
2019 0 : os << "<UncompiledDataWithPreparseData (" << data->start_position()
2020 0 : << ", " << data->end_position()
2021 0 : << ") preparsed=" << Brief(data->preparse_data()) << ">";
2022 : break;
2023 : }
2024 :
2025 : case SHARED_FUNCTION_INFO_TYPE: {
2026 74 : SharedFunctionInfo shared = SharedFunctionInfo::cast(*this);
2027 74 : std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
2028 74 : if (debug_name[0] != 0) {
2029 74 : os << "<SharedFunctionInfo " << debug_name.get() << ">";
2030 : } else {
2031 0 : os << "<SharedFunctionInfo>";
2032 : }
2033 : break;
2034 : }
2035 : case JS_MESSAGE_OBJECT_TYPE:
2036 0 : os << "<JSMessageObject>";
2037 0 : break;
2038 : #define MAKE_STRUCT_CASE(TYPE, Name, name) \
2039 : case TYPE: \
2040 : os << "<" #Name; \
2041 : Name::cast(*this)->BriefPrintDetails(os); \
2042 : os << ">"; \
2043 : break;
2044 11234 : STRUCT_LIST(MAKE_STRUCT_CASE)
2045 : #undef MAKE_STRUCT_CASE
2046 : case ALLOCATION_SITE_TYPE: {
2047 0 : os << "<AllocationSite";
2048 : AllocationSite::cast(*this)->BriefPrintDetails(os);
2049 0 : os << ">";
2050 0 : break;
2051 : }
2052 : case SCOPE_INFO_TYPE: {
2053 0 : ScopeInfo scope = ScopeInfo::cast(*this);
2054 0 : os << "<ScopeInfo";
2055 0 : if (scope->length()) os << " " << scope->scope_type() << " ";
2056 0 : os << "[" << scope->length() << "]>";
2057 : break;
2058 : }
2059 : case CODE_TYPE: {
2060 : Code code = Code::cast(*this);
2061 50 : os << "<Code " << Code::Kind2String(code->kind());
2062 50 : if (code->is_builtin()) {
2063 50 : os << " " << Builtins::name(code->builtin_index());
2064 : }
2065 50 : os << ">";
2066 : break;
2067 : }
2068 : case ODDBALL_TYPE: {
2069 19596 : if (IsUndefined()) {
2070 10854 : os << "<undefined>";
2071 8742 : } else if (IsTheHole()) {
2072 0 : os << "<the_hole>";
2073 8742 : } else if (IsNull()) {
2074 6395 : os << "<null>";
2075 2347 : } else if (IsTrue()) {
2076 105 : os << "<true>";
2077 2242 : } else if (IsFalse()) {
2078 34 : os << "<false>";
2079 : } else {
2080 2208 : os << "<Odd Oddball: ";
2081 6624 : os << Oddball::cast(*this)->to_string()->ToCString().get();
2082 2208 : os << ">";
2083 : }
2084 : break;
2085 : }
2086 : case SYMBOL_TYPE: {
2087 3901 : Symbol symbol = Symbol::cast(*this);
2088 3901 : symbol->SymbolShortPrint(os);
2089 : break;
2090 : }
2091 : case HEAP_NUMBER_TYPE: {
2092 79 : os << "<HeapNumber ";
2093 79 : HeapNumber::cast(*this)->HeapNumberPrint(os);
2094 79 : os << ">";
2095 79 : break;
2096 : }
2097 : case MUTABLE_HEAP_NUMBER_TYPE: {
2098 0 : os << "<MutableHeapNumber ";
2099 0 : MutableHeapNumber::cast(*this)->MutableHeapNumberPrint(os);
2100 : os << '>';
2101 : break;
2102 : }
2103 : case BIGINT_TYPE: {
2104 0 : os << "<BigInt ";
2105 0 : BigInt::cast(*this)->BigIntShortPrint(os);
2106 0 : os << ">";
2107 0 : break;
2108 : }
2109 : case JS_PROXY_TYPE:
2110 9 : os << "<JSProxy>";
2111 9 : break;
2112 : case FOREIGN_TYPE:
2113 0 : os << "<Foreign>";
2114 0 : break;
2115 : case CELL_TYPE: {
2116 12654 : os << "<Cell value= ";
2117 : HeapStringAllocator allocator;
2118 : StringStream accumulator(&allocator);
2119 12654 : Cell::cast(*this)->value()->ShortPrint(&accumulator);
2120 37962 : os << accumulator.ToCString().get();
2121 : os << '>';
2122 : break;
2123 : }
2124 : case PROPERTY_CELL_TYPE: {
2125 0 : PropertyCell cell = PropertyCell::cast(*this);
2126 0 : os << "<PropertyCell name=";
2127 0 : cell->name()->ShortPrint(os);
2128 0 : os << " value=";
2129 : HeapStringAllocator allocator;
2130 : StringStream accumulator(&allocator);
2131 0 : cell->value()->ShortPrint(&accumulator);
2132 0 : os << accumulator.ToCString().get();
2133 : os << '>';
2134 : break;
2135 : }
2136 : case CALL_HANDLER_INFO_TYPE: {
2137 0 : CallHandlerInfo info = CallHandlerInfo::cast(*this);
2138 0 : os << "<CallHandlerInfo ";
2139 0 : os << "callback= " << Brief(info->callback());
2140 0 : os << ", js_callback= " << Brief(info->js_callback());
2141 0 : os << ", data= " << Brief(info->data());
2142 0 : if (info->IsSideEffectFreeCallHandlerInfo()) {
2143 0 : os << ", side_effect_free= true>";
2144 : } else {
2145 0 : os << ", side_effect_free= false>";
2146 : }
2147 : break;
2148 : }
2149 : default:
2150 15364 : os << "<Other heap object (" << map()->instance_type() << ")>";
2151 15364 : break;
2152 : }
2153 : }
2154 :
2155 0 : void Struct::BriefPrintDetails(std::ostream& os) {}
2156 :
2157 0 : void Tuple2::BriefPrintDetails(std::ostream& os) {
2158 0 : os << " " << Brief(value1()) << ", " << Brief(value2());
2159 0 : }
2160 :
2161 0 : void Tuple3::BriefPrintDetails(std::ostream& os) {
2162 0 : os << " " << Brief(value1()) << ", " << Brief(value2()) << ", "
2163 0 : << Brief(value3());
2164 0 : }
2165 :
2166 0 : void ClassPositions::BriefPrintDetails(std::ostream& os) {
2167 0 : os << " " << start() << ", " << end();
2168 0 : }
2169 :
2170 0 : void ArrayBoilerplateDescription::BriefPrintDetails(std::ostream& os) {
2171 0 : os << " " << elements_kind() << ", " << Brief(constant_elements());
2172 0 : }
2173 :
2174 0 : void CallableTask::BriefPrintDetails(std::ostream& os) {
2175 0 : os << " callable=" << Brief(callable());
2176 0 : }
2177 :
2178 13340673 : void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
2179 :
2180 :
2181 0 : void HeapObject::IterateBody(ObjectVisitor* v) {
2182 : Map m = map();
2183 0 : IterateBodyFast<ObjectVisitor>(m, SizeFromMap(m), v);
2184 0 : }
2185 :
2186 1888958 : void HeapObject::IterateBody(Map map, int object_size, ObjectVisitor* v) {
2187 : IterateBodyFast<ObjectVisitor>(map, object_size, v);
2188 1888958 : }
2189 :
2190 :
2191 : struct CallIsValidSlot {
2192 : template <typename BodyDescriptor>
2193 0 : static bool apply(Map map, HeapObject obj, int offset, int) {
2194 0 : return BodyDescriptor::IsValidSlot(map, obj, offset);
2195 : }
2196 : };
2197 :
2198 767200 : bool HeapObject::IsValidSlot(Map map, int offset) {
2199 : DCHECK_NE(0, offset);
2200 : return BodyDescriptorApply<CallIsValidSlot, bool>(map->instance_type(), map,
2201 767200 : *this, offset, 0);
2202 : }
2203 :
2204 2279344921 : int HeapObject::SizeFromMap(Map map) const {
2205 : int instance_size = map->instance_size();
2206 2279344921 : if (instance_size != kVariableSizeSentinel) return instance_size;
2207 : // Only inline the most frequent cases.
2208 : InstanceType instance_type = map->instance_type();
2209 1000145413 : if (IsInRange(instance_type, FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE)) {
2210 : return FixedArray::SizeFor(
2211 142569102 : FixedArray::unchecked_cast(*this)->synchronized_length());
2212 : }
2213 928858950 : if (IsInRange(instance_type, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE)) {
2214 : // Native context has fixed size.
2215 : DCHECK_NE(instance_type, NATIVE_CONTEXT_TYPE);
2216 8929657 : return Context::SizeFor(Context::unchecked_cast(*this)->length());
2217 : }
2218 1848788300 : if (instance_type == ONE_BYTE_STRING_TYPE ||
2219 924394150 : instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
2220 : // Strings may get concurrently truncated, hence we have to access its
2221 : // length synchronized.
2222 : return SeqOneByteString::SizeFor(
2223 : SeqOneByteString::unchecked_cast(*this)->synchronized_length());
2224 : }
2225 700697702 : if (instance_type == BYTE_ARRAY_TYPE) {
2226 : return ByteArray::SizeFor(
2227 41314441 : ByteArray::unchecked_cast(*this)->synchronized_length());
2228 : }
2229 680038672 : if (instance_type == BYTECODE_ARRAY_TYPE) {
2230 : return BytecodeArray::SizeFor(
2231 17711851 : BytecodeArray::unchecked_cast(*this)->synchronized_length());
2232 : }
2233 671182091 : if (instance_type == FREE_SPACE_TYPE) {
2234 1088703 : return FreeSpace::unchecked_cast(*this)->relaxed_read_size();
2235 : }
2236 1340186776 : if (instance_type == STRING_TYPE ||
2237 670093388 : instance_type == INTERNALIZED_STRING_TYPE) {
2238 : // Strings may get concurrently truncated, hence we have to access its
2239 : // length synchronized.
2240 : return SeqTwoByteString::SizeFor(
2241 : SeqTwoByteString::unchecked_cast(*this)->synchronized_length());
2242 : }
2243 527178082 : if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2244 : return FixedDoubleArray::SizeFor(
2245 1324619 : FixedDoubleArray::unchecked_cast(*this)->synchronized_length());
2246 : }
2247 526515764 : if (instance_type == FEEDBACK_METADATA_TYPE) {
2248 : return FeedbackMetadata::SizeFor(
2249 : FeedbackMetadata::unchecked_cast(*this)->synchronized_slot_count());
2250 : }
2251 521070292 : if (instance_type == DESCRIPTOR_ARRAY_TYPE) {
2252 : return DescriptorArray::SizeFor(
2253 75427325 : DescriptorArray::unchecked_cast(*this)->number_of_all_descriptors());
2254 : }
2255 445642967 : if (IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
2256 : LAST_WEAK_FIXED_ARRAY_TYPE)) {
2257 : return WeakFixedArray::SizeFor(
2258 23033073 : WeakFixedArray::unchecked_cast(*this)->synchronized_length());
2259 : }
2260 434125336 : if (instance_type == WEAK_ARRAY_LIST_TYPE) {
2261 : return WeakArrayList::SizeForCapacity(
2262 7798991 : WeakArrayList::unchecked_cast(*this)->synchronized_capacity());
2263 : }
2264 430225768 : if (IsInRange(instance_type, FIRST_FIXED_TYPED_ARRAY_TYPE,
2265 : LAST_FIXED_TYPED_ARRAY_TYPE)) {
2266 : return FixedTypedArrayBase::unchecked_cast(*this)->TypedArraySize(
2267 1100834 : instance_type);
2268 : }
2269 429675335 : if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
2270 : return SmallOrderedHashSet::SizeFor(
2271 : SmallOrderedHashSet::unchecked_cast(*this)->Capacity());
2272 : }
2273 429675335 : if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) {
2274 : return SmallOrderedHashMap::SizeFor(
2275 : SmallOrderedHashMap::unchecked_cast(*this)->Capacity());
2276 : }
2277 429675335 : if (instance_type == SMALL_ORDERED_NAME_DICTIONARY_TYPE) {
2278 : return SmallOrderedNameDictionary::SizeFor(
2279 : SmallOrderedNameDictionary::unchecked_cast(*this)->Capacity());
2280 : }
2281 429675335 : if (instance_type == PROPERTY_ARRAY_TYPE) {
2282 : return PropertyArray::SizeFor(
2283 87230809 : PropertyArray::cast(*this)->synchronized_length());
2284 : }
2285 386047908 : if (instance_type == FEEDBACK_VECTOR_TYPE) {
2286 : return FeedbackVector::SizeFor(
2287 : FeedbackVector::unchecked_cast(*this)->length());
2288 : }
2289 370563279 : if (instance_type == BIGINT_TYPE) {
2290 : return BigInt::SizeFor(BigInt::unchecked_cast(*this)->length());
2291 : }
2292 370554499 : if (instance_type == PREPARSE_DATA_TYPE) {
2293 : PreparseData data = PreparseData::unchecked_cast(*this);
2294 : return PreparseData::SizeFor(data->data_length(), data->children_length());
2295 : }
2296 370360244 : if (instance_type == CODE_TYPE) {
2297 739830316 : return Code::unchecked_cast(*this)->CodeSize();
2298 : }
2299 : DCHECK_EQ(instance_type, EMBEDDER_DATA_ARRAY_TYPE);
2300 : return EmbedderDataArray::SizeFor(
2301 834012 : EmbedderDataArray::unchecked_cast(*this)->length());
2302 : }
2303 :
2304 373548327 : bool HeapObject::NeedsRehashing() const {
2305 373548327 : switch (map()->instance_type()) {
2306 : case DESCRIPTOR_ARRAY_TYPE:
2307 16335790 : return DescriptorArray::cast(*this)->number_of_descriptors() > 1;
2308 : case TRANSITION_ARRAY_TYPE:
2309 1258858 : return TransitionArray::cast(*this)->number_of_entries() > 1;
2310 : case ORDERED_HASH_MAP_TYPE:
2311 61194 : return OrderedHashMap::cast(*this)->NumberOfElements() > 0;
2312 : case ORDERED_HASH_SET_TYPE:
2313 61189 : return OrderedHashSet::cast(*this)->NumberOfElements() > 0;
2314 : case NAME_DICTIONARY_TYPE:
2315 : case GLOBAL_DICTIONARY_TYPE:
2316 : case NUMBER_DICTIONARY_TYPE:
2317 : case SIMPLE_NUMBER_DICTIONARY_TYPE:
2318 : case STRING_TABLE_TYPE:
2319 : case HASH_TABLE_TYPE:
2320 : case SMALL_ORDERED_HASH_MAP_TYPE:
2321 : case SMALL_ORDERED_HASH_SET_TYPE:
2322 : case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2323 : return true;
2324 : default:
2325 356097751 : return false;
2326 : }
2327 : }
2328 :
2329 37384 : bool HeapObject::CanBeRehashed() const {
2330 : DCHECK(NeedsRehashing());
2331 37384 : switch (map()->instance_type()) {
2332 : case ORDERED_HASH_MAP_TYPE:
2333 : case ORDERED_HASH_SET_TYPE:
2334 : case ORDERED_NAME_DICTIONARY_TYPE:
2335 : // TODO(yangguo): actually support rehashing OrderedHash{Map,Set}.
2336 : return false;
2337 : case NAME_DICTIONARY_TYPE:
2338 : case GLOBAL_DICTIONARY_TYPE:
2339 : case NUMBER_DICTIONARY_TYPE:
2340 : case SIMPLE_NUMBER_DICTIONARY_TYPE:
2341 : case STRING_TABLE_TYPE:
2342 1290 : return true;
2343 : case DESCRIPTOR_ARRAY_TYPE:
2344 36084 : return true;
2345 : case TRANSITION_ARRAY_TYPE:
2346 5 : return true;
2347 : case SMALL_ORDERED_HASH_MAP_TYPE:
2348 0 : return SmallOrderedHashMap::cast(*this)->NumberOfElements() == 0;
2349 : case SMALL_ORDERED_HASH_SET_TYPE:
2350 0 : return SmallOrderedHashMap::cast(*this)->NumberOfElements() == 0;
2351 : case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2352 0 : return SmallOrderedNameDictionary::cast(*this)->NumberOfElements() == 0;
2353 : default:
2354 : return false;
2355 : }
2356 : return false;
2357 : }
2358 :
2359 14262817 : void HeapObject::RehashBasedOnMap(Isolate* isolate) {
2360 14262817 : switch (map()->instance_type()) {
2361 : case HASH_TABLE_TYPE:
2362 0 : UNREACHABLE();
2363 : break;
2364 : case NAME_DICTIONARY_TYPE:
2365 60988 : NameDictionary::cast(*this)->Rehash(isolate);
2366 60988 : break;
2367 : case GLOBAL_DICTIONARY_TYPE:
2368 89681 : GlobalDictionary::cast(*this)->Rehash(isolate);
2369 89681 : break;
2370 : case NUMBER_DICTIONARY_TYPE:
2371 60937 : NumberDictionary::cast(*this)->Rehash(isolate);
2372 60938 : break;
2373 : case SIMPLE_NUMBER_DICTIONARY_TYPE:
2374 89681 : SimpleNumberDictionary::cast(*this)->Rehash(isolate);
2375 89681 : break;
2376 : case STRING_TABLE_TYPE:
2377 60932 : StringTable::cast(*this)->Rehash(isolate);
2378 60933 : break;
2379 : case DESCRIPTOR_ARRAY_TYPE:
2380 : DCHECK_LE(1, DescriptorArray::cast(*this)->number_of_descriptors());
2381 13900597 : DescriptorArray::cast(*this)->Sort();
2382 13900594 : break;
2383 : case TRANSITION_ARRAY_TYPE:
2384 5 : TransitionArray::cast(*this)->Sort();
2385 5 : break;
2386 : case SMALL_ORDERED_HASH_MAP_TYPE:
2387 : DCHECK_EQ(0, SmallOrderedHashMap::cast(*this)->NumberOfElements());
2388 : break;
2389 : case SMALL_ORDERED_HASH_SET_TYPE:
2390 : DCHECK_EQ(0, SmallOrderedHashSet::cast(*this)->NumberOfElements());
2391 : break;
2392 : case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
2393 : DCHECK_EQ(0, SmallOrderedNameDictionary::cast(*this)->NumberOfElements());
2394 : break;
2395 : default:
2396 : break;
2397 : }
2398 14262817 : }
2399 :
2400 299379 : bool HeapObject::IsExternal(Isolate* isolate) const {
2401 898137 : return map()->FindRootMap(isolate) == isolate->heap()->external_map();
2402 : }
2403 :
2404 30301 : const char* Representation::Mnemonic() const {
2405 30301 : switch (kind_) {
2406 : case kNone: return "v";
2407 4914 : case kTagged: return "t";
2408 5758 : case kSmi: return "s";
2409 508 : case kDouble: return "d";
2410 0 : case kInteger32: return "i";
2411 19121 : case kHeapObject: return "h";
2412 0 : case kExternal: return "x";
2413 : default:
2414 0 : UNREACHABLE();
2415 : }
2416 : }
2417 :
2418 5381645 : void DescriptorArray::GeneralizeAllFields() {
2419 5381645 : int length = number_of_descriptors();
2420 9948270 : for (int i = 0; i < length; i++) {
2421 4566624 : PropertyDetails details = GetDetails(i);
2422 : details = details.CopyWithRepresentation(Representation::Tagged());
2423 4566625 : if (details.location() == kField) {
2424 : DCHECK_EQ(kData, details.kind());
2425 : details = details.CopyWithConstness(PropertyConstness::kMutable);
2426 7784380 : SetValue(i, FieldType::Any());
2427 : }
2428 4566625 : set(ToDetailsIndex(i), MaybeObject::FromObject(details.AsSmi()));
2429 : }
2430 5381646 : }
2431 :
2432 3822851 : MaybeHandle<Object> Object::SetProperty(Isolate* isolate, Handle<Object> object,
2433 : Handle<Name> name, Handle<Object> value,
2434 : StoreOrigin store_origin,
2435 : Maybe<ShouldThrow> should_throw) {
2436 3822851 : LookupIterator it(isolate, object, name);
2437 3822851 : MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
2438 3822242 : return value;
2439 : }
2440 :
2441 12435225 : Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
2442 : Handle<Object> value,
2443 : Maybe<ShouldThrow> should_throw,
2444 : StoreOrigin store_origin, bool* found) {
2445 6008003 : it->UpdateProtector();
2446 : DCHECK(it->IsFound());
2447 :
2448 : // Make sure that the top context does not change when doing callbacks or
2449 : // interceptor calls.
2450 : AssertNoContextChange ncc(it->isolate());
2451 :
2452 273291 : do {
2453 6151651 : switch (it->state()) {
2454 : case LookupIterator::NOT_FOUND:
2455 0 : UNREACHABLE();
2456 :
2457 : case LookupIterator::ACCESS_CHECK:
2458 80491 : if (it->HasAccess()) break;
2459 : // Check whether it makes sense to reuse the lookup iterator. Here it
2460 : // might still call into setters up the prototype chain.
2461 : return JSObject::SetPropertyWithFailedAccessCheck(it, value,
2462 103 : should_throw);
2463 :
2464 : case LookupIterator::JSPROXY: {
2465 : Handle<Object> receiver = it->GetReceiver();
2466 : // In case of global IC, the receiver is the global object. Replace by
2467 : // the global proxy.
2468 105556 : if (receiver->IsJSGlobalObject()) {
2469 : receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(),
2470 234 : it->isolate());
2471 : }
2472 : return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
2473 105556 : value, receiver, should_throw);
2474 : }
2475 :
2476 : case LookupIterator::INTERCEPTOR: {
2477 202314 : if (it->HolderIsReceiverOrHiddenPrototype()) {
2478 : Maybe<bool> result =
2479 193061 : JSObject::SetPropertyWithInterceptor(it, should_throw, value);
2480 386122 : if (result.IsNothing() || result.FromJust()) return result;
2481 : } else {
2482 : Maybe<PropertyAttributes> maybe_attributes =
2483 9253 : JSObject::GetPropertyAttributesWithInterceptor(it);
2484 18396 : if (maybe_attributes.IsNothing()) return Nothing<bool>();
2485 9253 : if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
2486 0 : return WriteToReadOnlyProperty(it, value, should_throw);
2487 : }
2488 9253 : if (maybe_attributes.FromJust() == ABSENT) break;
2489 9143 : *found = false;
2490 : return Nothing<bool>();
2491 : }
2492 : break;
2493 : }
2494 :
2495 : case LookupIterator::ACCESSOR: {
2496 486416 : if (it->IsReadOnly()) {
2497 1482 : return WriteToReadOnlyProperty(it, value, should_throw);
2498 : }
2499 484934 : Handle<Object> accessors = it->GetAccessors();
2500 1213133 : if (accessors->IsAccessorInfo() &&
2501 605614 : !it->HolderIsReceiverOrHiddenPrototype() &&
2502 605614 : AccessorInfo::cast(*accessors)->is_special_data_property()) {
2503 442 : *found = false;
2504 : return Nothing<bool>();
2505 : }
2506 484492 : return SetPropertyWithAccessor(it, value, should_throw);
2507 : }
2508 : case LookupIterator::INTEGER_INDEXED_EXOTIC: {
2509 : // IntegerIndexedElementSet converts value to a Number/BigInt prior to
2510 : // the bounds check. The bounds check has already happened here, but
2511 : // perform the possibly effectful ToNumber (or ToBigInt) operation
2512 : // anyways.
2513 : auto holder = it->GetHolder<JSTypedArray>();
2514 : Handle<Object> throwaway_value;
2515 6489 : if (holder->type() == kExternalBigInt64Array ||
2516 4326 : holder->type() == kExternalBigUint64Array) {
2517 36 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2518 : it->isolate(), throwaway_value,
2519 : BigInt::FromObject(it->isolate(), value), Nothing<bool>());
2520 : } else {
2521 4290 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2522 : it->isolate(), throwaway_value,
2523 : Object::ToNumber(it->isolate(), value), Nothing<bool>());
2524 : }
2525 :
2526 : // FIXME: Throw a TypeError if the holder is detached here
2527 : // (IntegerIndexedElementSpec step 5).
2528 :
2529 : // TODO(verwaest): Per spec, we should return false here (steps 6-9
2530 : // in IntegerIndexedElementSpec), resulting in an exception being thrown
2531 : // on OOB accesses in strict code. Historically, v8 has not done made
2532 : // this change due to uncertainty about web compat. (v8:4901)
2533 : return Just(true);
2534 : }
2535 :
2536 : case LookupIterator::DATA:
2537 4858020 : if (it->IsReadOnly()) {
2538 26639 : return WriteToReadOnlyProperty(it, value, should_throw);
2539 : }
2540 4831381 : if (it->HolderIsReceiverOrHiddenPrototype()) {
2541 4772194 : return SetDataProperty(it, value);
2542 : }
2543 : V8_FALLTHROUGH;
2544 : case LookupIterator::TRANSITION:
2545 528657 : *found = false;
2546 : return Nothing<bool>();
2547 : }
2548 273291 : it->Next();
2549 : } while (it->IsFound());
2550 :
2551 129643 : *found = false;
2552 : return Nothing<bool>();
2553 : }
2554 :
2555 10807231 : Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
2556 : StoreOrigin store_origin,
2557 : Maybe<ShouldThrow> should_throw) {
2558 10764859 : if (it->IsFound()) {
2559 5951870 : bool found = true;
2560 : Maybe<bool> result =
2561 5951870 : SetPropertyInternal(it, value, should_throw, store_origin, &found);
2562 5951867 : if (found) return result;
2563 : }
2564 :
2565 : // If the receiver is the JSGlobalObject, the store was contextual. In case
2566 : // the property did not exist yet on the global object itself, we have to
2567 : // throw a reference error in strict mode. In sloppy mode, we continue.
2568 10998618 : if (it->GetReceiver()->IsJSGlobalObject() &&
2569 41256 : (GetShouldThrow(it->isolate(), should_throw) ==
2570 : ShouldThrow::kThrowOnError)) {
2571 : it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
2572 1116 : MessageTemplate::kNotDefined, it->name()));
2573 : return Nothing<bool>();
2574 : }
2575 :
2576 5478123 : return AddDataProperty(it, value, NONE, should_throw, store_origin);
2577 : }
2578 :
2579 66114 : Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
2580 : StoreOrigin store_origin,
2581 : Maybe<ShouldThrow> should_throw) {
2582 : Isolate* isolate = it->isolate();
2583 :
2584 60392 : if (it->IsFound()) {
2585 56137 : bool found = true;
2586 : Maybe<bool> result =
2587 56137 : SetPropertyInternal(it, value, should_throw, store_origin, &found);
2588 56137 : if (found) return result;
2589 : }
2590 :
2591 6451 : it->UpdateProtector();
2592 :
2593 : // The property either doesn't exist on the holder or exists there as a data
2594 : // property.
2595 :
2596 :
2597 12902 : if (!it->GetReceiver()->IsJSReceiver()) {
2598 729 : return WriteToReadOnlyProperty(it, value, should_throw);
2599 : }
2600 5722 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
2601 :
2602 : LookupIterator::Configuration c = LookupIterator::OWN;
2603 : LookupIterator own_lookup =
2604 : it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
2605 11444 : : LookupIterator(isolate, receiver, it->name(), c);
2606 :
2607 36 : for (; own_lookup.IsFound(); own_lookup.Next()) {
2608 4358 : switch (own_lookup.state()) {
2609 : case LookupIterator::ACCESS_CHECK:
2610 41 : if (!own_lookup.HasAccess()) {
2611 : return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
2612 5 : should_throw);
2613 : }
2614 : break;
2615 :
2616 : case LookupIterator::ACCESSOR:
2617 2943 : if (own_lookup.GetAccessors()->IsAccessorInfo()) {
2618 9 : if (own_lookup.IsReadOnly()) {
2619 0 : return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
2620 : }
2621 : return Object::SetPropertyWithAccessor(&own_lookup, value,
2622 9 : should_throw);
2623 : }
2624 : V8_FALLTHROUGH;
2625 : case LookupIterator::INTEGER_INDEXED_EXOTIC:
2626 : return RedefineIncompatibleProperty(isolate, it->GetName(), value,
2627 1944 : should_throw);
2628 :
2629 : case LookupIterator::DATA: {
2630 981 : if (own_lookup.IsReadOnly()) {
2631 297 : return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
2632 : }
2633 684 : return SetDataProperty(&own_lookup, value);
2634 : }
2635 :
2636 : case LookupIterator::INTERCEPTOR:
2637 : case LookupIterator::JSPROXY: {
2638 : PropertyDescriptor desc;
2639 : Maybe<bool> owned =
2640 2355 : JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
2641 2355 : MAYBE_RETURN(owned, Nothing<bool>());
2642 1905 : if (!owned.FromJust()) {
2643 : return JSReceiver::CreateDataProperty(&own_lookup, value,
2644 1005 : should_throw);
2645 : }
2646 1800 : if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
2647 : !desc.writable()) {
2648 : return RedefineIncompatibleProperty(isolate, it->GetName(), value,
2649 0 : should_throw);
2650 : }
2651 :
2652 : PropertyDescriptor value_desc;
2653 : value_desc.set_value(value);
2654 : return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
2655 1800 : &value_desc, should_throw);
2656 : }
2657 :
2658 : case LookupIterator::NOT_FOUND:
2659 : case LookupIterator::TRANSITION:
2660 0 : UNREACHABLE();
2661 : }
2662 : }
2663 :
2664 1400 : return AddDataProperty(&own_lookup, value, NONE, should_throw, store_origin);
2665 : }
2666 :
2667 5990 : Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
2668 : Handle<Object> receiver,
2669 : Handle<Object> name,
2670 : Handle<Object> value,
2671 : Maybe<ShouldThrow> should_throw) {
2672 6224 : RETURN_FAILURE(
2673 : isolate, GetShouldThrow(isolate, should_throw),
2674 : NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
2675 : Object::TypeOf(isolate, receiver), receiver));
2676 : }
2677 :
2678 29147 : Maybe<bool> Object::WriteToReadOnlyProperty(
2679 98930 : LookupIterator* it, Handle<Object> value,
2680 : Maybe<ShouldThrow> maybe_should_throw) {
2681 29147 : ShouldThrow should_throw = GetShouldThrow(it->isolate(), maybe_should_throw);
2682 29147 : if (it->IsFound() && !it->HolderIsReceiver()) {
2683 : // "Override mistake" attempted, record a use count to track this per
2684 : // v8:8175
2685 : v8::Isolate::UseCounterFeature feature =
2686 : should_throw == kThrowOnError
2687 : ? v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeStrict
2688 11489 : : v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeSloppy;
2689 11489 : it->isolate()->CountUsage(feature);
2690 : }
2691 : return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
2692 58294 : it->GetName(), value, should_throw);
2693 : }
2694 :
2695 29147 : Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
2696 : Handle<Object> receiver,
2697 : Handle<Object> name,
2698 : Handle<Object> value,
2699 : ShouldThrow should_throw) {
2700 47015 : RETURN_FAILURE(isolate, should_throw,
2701 : NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
2702 : Object::TypeOf(isolate, receiver), receiver));
2703 : }
2704 :
2705 981 : Maybe<bool> Object::RedefineIncompatibleProperty(
2706 : Isolate* isolate, Handle<Object> name, Handle<Object> value,
2707 : Maybe<ShouldThrow> should_throw) {
2708 1215 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
2709 : NewTypeError(MessageTemplate::kRedefineDisallowed, name));
2710 : }
2711 :
2712 10551879 : Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
2713 : DCHECK_IMPLIES(it->GetReceiver()->IsJSProxy(),
2714 : it->GetName()->IsPrivateName());
2715 : DCHECK_IMPLIES(!it->IsElement() && it->GetName()->IsPrivateName(),
2716 : it->state() == LookupIterator::DATA);
2717 5274944 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
2718 :
2719 : // Store on the holder which may be hidden behind the receiver.
2720 : DCHECK(it->HolderIsReceiverOrHiddenPrototype());
2721 :
2722 5274946 : Handle<Object> to_assign = value;
2723 : // Convert the incoming value to a number for storing into typed arrays.
2724 13244883 : if (it->IsElement() && receiver->IsJSObject() &&
2725 6173280 : JSObject::cast(*receiver)->HasFixedTypedArrayElements()) {
2726 699969 : ElementsKind elements_kind = JSObject::cast(*receiver)->GetElementsKind();
2727 699969 : if (elements_kind == BIGINT64_ELEMENTS ||
2728 : elements_kind == BIGUINT64_ELEMENTS) {
2729 126 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
2730 : BigInt::FromObject(it->isolate(), value),
2731 : Nothing<bool>());
2732 : // We have to recheck the length. However, it can only change if the
2733 : // underlying buffer was detached, so just check that.
2734 126 : if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
2735 : return Just(true);
2736 : // TODO(neis): According to the spec, this should throw a TypeError.
2737 : }
2738 1401918 : } else if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
2739 1746 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
2740 : Object::ToNumber(it->isolate(), value),
2741 : Nothing<bool>());
2742 : // We have to recheck the length. However, it can only change if the
2743 : // underlying buffer was detached, so just check that.
2744 1746 : if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
2745 : return Just(true);
2746 : // TODO(neis): According to the spec, this should throw a TypeError.
2747 : }
2748 : }
2749 : }
2750 :
2751 : // Possibly migrate to the most up-to-date map that will be able to store
2752 : // |value| under it->name().
2753 5274949 : it->PrepareForDataProperty(to_assign);
2754 :
2755 : // Write the property value.
2756 5274946 : it->WriteDataValue(to_assign, false);
2757 :
2758 : #if VERIFY_HEAP
2759 : if (FLAG_verify_heap) {
2760 : receiver->HeapObjectVerify(it->isolate());
2761 : }
2762 : #endif
2763 : return Just(true);
2764 : }
2765 :
2766 122568521 : Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
2767 : PropertyAttributes attributes,
2768 : Maybe<ShouldThrow> should_throw,
2769 : StoreOrigin store_origin) {
2770 75703101 : if (!it->GetReceiver()->IsJSReceiver()) {
2771 : return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
2772 11980 : value, should_throw);
2773 : }
2774 :
2775 : // Private symbols should be installed on JSProxy using
2776 : // JSProxy::SetPrivateSymbol.
2777 113536765 : if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate() &&
2778 37845647 : !it->GetName()->IsPrivateName()) {
2779 45 : RETURN_FAILURE(it->isolate(), GetShouldThrow(it->isolate(), should_throw),
2780 : NewTypeError(MessageTemplate::kProxyPrivate));
2781 : }
2782 :
2783 : DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
2784 :
2785 37845530 : Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
2786 : DCHECK_IMPLIES(receiver->IsJSProxy(), it->GetName()->IsPrivateName());
2787 : DCHECK_IMPLIES(receiver->IsJSProxy(),
2788 : it->state() == LookupIterator::NOT_FOUND);
2789 :
2790 : // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
2791 : // instead. If the prototype is Null, the proxy is detached.
2792 75691058 : if (receiver->IsJSGlobalProxy()) return Just(true);
2793 :
2794 : Isolate* isolate = it->isolate();
2795 :
2796 37845527 : if (it->ExtendingNonExtensible(receiver)) {
2797 364945 : RETURN_FAILURE(
2798 : isolate, GetShouldThrow(it->isolate(), should_throw),
2799 : NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
2800 : }
2801 :
2802 37752150 : if (it->IsElement()) {
2803 12363746 : if (receiver->IsJSArray()) {
2804 2838014 : Handle<JSArray> array = Handle<JSArray>::cast(receiver);
2805 2838012 : if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
2806 1035 : RETURN_FAILURE(isolate, GetShouldThrow(it->isolate(), should_throw),
2807 : NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
2808 : isolate->factory()->length_string(),
2809 : Object::TypeOf(isolate, array), array));
2810 : }
2811 :
2812 8513199 : if (FLAG_trace_external_array_abuse &&
2813 2837733 : array->HasFixedTypedArrayElements()) {
2814 0 : CheckArrayAbuse(array, "typed elements write", it->index(), true);
2815 : }
2816 :
2817 2837733 : if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
2818 0 : CheckArrayAbuse(array, "elements write", it->index(), false);
2819 : }
2820 : }
2821 :
2822 6181592 : Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
2823 6181593 : JSObject::AddDataElement(receiver_obj, it->index(), value, attributes);
2824 6181595 : JSObject::ValidateElements(*receiver_obj);
2825 : return Just(true);
2826 : } else {
2827 31570276 : it->UpdateProtector();
2828 : // Migrate to the most up-to-date map that will be able to store |value|
2829 : // under it->name() with |attributes|.
2830 : it->PrepareTransitionToDataProperty(receiver, value, attributes,
2831 31570275 : store_origin);
2832 : DCHECK_EQ(LookupIterator::TRANSITION, it->state());
2833 31570279 : it->ApplyTransitionToDataProperty(receiver);
2834 :
2835 : // Write the property value.
2836 31570274 : it->WriteDataValue(value, true);
2837 :
2838 : #if VERIFY_HEAP
2839 : if (FLAG_verify_heap) {
2840 : receiver->HeapObjectVerify(isolate);
2841 : }
2842 : #endif
2843 : }
2844 :
2845 : return Just(true);
2846 : }
2847 :
2848 :
2849 : template <class T>
2850 52926 : static int AppendUniqueCallbacks(Isolate* isolate,
2851 : Handle<TemplateList> callbacks,
2852 : Handle<typename T::Array> array,
2853 : int valid_descriptors) {
2854 52926 : int nof_callbacks = callbacks->length();
2855 :
2856 : // Fill in new callback descriptors. Process the callbacks from
2857 : // back to front so that the last callback with a given name takes
2858 : // precedence over previously added callbacks with that name.
2859 106113 : for (int i = nof_callbacks - 1; i >= 0; i--) {
2860 106374 : Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)), isolate);
2861 106374 : Handle<Name> key(Name::cast(entry->name()), isolate);
2862 : DCHECK(key->IsUniqueName());
2863 : // Check if a descriptor with this name already exists before writing.
2864 53187 : if (!T::Contains(key, entry, valid_descriptors, array)) {
2865 53175 : T::Insert(key, entry, valid_descriptors, array);
2866 53175 : valid_descriptors++;
2867 : }
2868 : }
2869 :
2870 52926 : return valid_descriptors;
2871 : }
2872 :
2873 : struct FixedArrayAppender {
2874 : typedef FixedArray Array;
2875 53187 : static bool Contains(Handle<Name> key,
2876 : Handle<AccessorInfo> entry,
2877 : int valid_descriptors,
2878 : Handle<FixedArray> array) {
2879 53676 : for (int i = 0; i < valid_descriptors; i++) {
2880 1002 : if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
2881 : }
2882 : return false;
2883 : }
2884 53175 : static void Insert(Handle<Name> key,
2885 : Handle<AccessorInfo> entry,
2886 : int valid_descriptors,
2887 : Handle<FixedArray> array) {
2888 : DisallowHeapAllocation no_gc;
2889 106350 : array->set(valid_descriptors, *entry);
2890 53175 : }
2891 : };
2892 :
2893 52926 : int AccessorInfo::AppendUnique(Isolate* isolate, Handle<Object> descriptors,
2894 : Handle<FixedArray> array,
2895 : int valid_descriptors) {
2896 52926 : Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
2897 : DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
2898 : return AppendUniqueCallbacks<FixedArrayAppender>(isolate, callbacks, array,
2899 52926 : valid_descriptors);
2900 : }
2901 :
2902 :
2903 :
2904 :
2905 :
2906 5 : void JSProxy::Revoke(Handle<JSProxy> proxy) {
2907 : Isolate* isolate = proxy->GetIsolate();
2908 : // ES#sec-proxy-revocation-functions
2909 10 : if (!proxy->IsRevoked()) {
2910 : // 5. Set p.[[ProxyTarget]] to null.
2911 10 : proxy->set_target(ReadOnlyRoots(isolate).null_value());
2912 : // 6. Set p.[[ProxyHandler]] to null.
2913 10 : proxy->set_handler(ReadOnlyRoots(isolate).null_value());
2914 : }
2915 : DCHECK(proxy->IsRevoked());
2916 5 : }
2917 :
2918 : // static
2919 1238 : Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) {
2920 : Isolate* isolate = proxy->GetIsolate();
2921 1238 : Handle<JSReceiver> object = Handle<JSReceiver>::cast(proxy);
2922 922865 : for (int i = 0; i < JSProxy::kMaxIterationLimit; i++) {
2923 922856 : Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
2924 1845712 : if (proxy->IsRevoked()) {
2925 : isolate->Throw(*isolate->factory()->NewTypeError(
2926 : MessageTemplate::kProxyRevoked,
2927 324 : isolate->factory()->NewStringFromAsciiChecked("IsArray")));
2928 : return Nothing<bool>();
2929 : }
2930 : object = handle(JSReceiver::cast(proxy->target()), isolate);
2931 1845496 : if (object->IsJSArray()) return Just(true);
2932 1844758 : if (!object->IsJSProxy()) return Just(false);
2933 : }
2934 :
2935 : // Too deep recursion, throw a RangeError.
2936 9 : isolate->StackOverflow();
2937 : return Nothing<bool>();
2938 : }
2939 :
2940 47088 : Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
2941 : Handle<Name> name) {
2942 : DCHECK(!name->IsPrivate());
2943 47088 : STACK_CHECK(isolate, Nothing<bool>());
2944 : // 1. (Assert)
2945 : // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
2946 : Handle<Object> handler(proxy->handler(), isolate);
2947 : // 3. If handler is null, throw a TypeError exception.
2948 : // 4. Assert: Type(handler) is Object.
2949 94158 : if (proxy->IsRevoked()) {
2950 : isolate->Throw(*isolate->factory()->NewTypeError(
2951 0 : MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
2952 : return Nothing<bool>();
2953 : }
2954 : // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
2955 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
2956 : // 6. Let trap be ? GetMethod(handler, "has").
2957 : Handle<Object> trap;
2958 94158 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2959 : isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
2960 : isolate->factory()->has_string()),
2961 : Nothing<bool>());
2962 : // 7. If trap is undefined, then
2963 94158 : if (trap->IsUndefined(isolate)) {
2964 : // 7a. Return target.[[HasProperty]](P).
2965 38655 : return JSReceiver::HasProperty(target, name);
2966 : }
2967 : // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)).
2968 : Handle<Object> trap_result_obj;
2969 : Handle<Object> args[] = {target, name};
2970 16848 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2971 : isolate, trap_result_obj,
2972 : Execution::Call(isolate, trap, handler, arraysize(args), args),
2973 : Nothing<bool>());
2974 8379 : bool boolean_trap_result = trap_result_obj->BooleanValue(isolate);
2975 : // 9. If booleanTrapResult is false, then:
2976 8379 : if (!boolean_trap_result) {
2977 5481 : MAYBE_RETURN(JSProxy::CheckHasTrap(isolate, name, target), Nothing<bool>());
2978 : }
2979 : // 10. Return booleanTrapResult.
2980 : return Just(boolean_trap_result);
2981 : }
2982 :
2983 5490 : Maybe<bool> JSProxy::CheckHasTrap(Isolate* isolate, Handle<Name> name,
2984 : Handle<JSReceiver> target) {
2985 : // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
2986 : PropertyDescriptor target_desc;
2987 : Maybe<bool> target_found =
2988 5490 : JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
2989 5490 : MAYBE_RETURN(target_found, Nothing<bool>());
2990 : // 9b. If targetDesc is not undefined, then:
2991 5490 : if (target_found.FromJust()) {
2992 : // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
2993 : // exception.
2994 9 : if (!target_desc.configurable()) {
2995 : isolate->Throw(*isolate->factory()->NewTypeError(
2996 18 : MessageTemplate::kProxyHasNonConfigurable, name));
2997 9 : return Nothing<bool>();
2998 : }
2999 : // 9b ii. Let extensibleTarget be ? IsExtensible(target).
3000 0 : Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3001 0 : MAYBE_RETURN(extensible_target, Nothing<bool>());
3002 : // 9b iii. If extensibleTarget is false, throw a TypeError exception.
3003 0 : if (!extensible_target.FromJust()) {
3004 : isolate->Throw(*isolate->factory()->NewTypeError(
3005 0 : MessageTemplate::kProxyHasNonExtensible, name));
3006 : return Nothing<bool>();
3007 : }
3008 : }
3009 : return Just(true);
3010 : }
3011 :
3012 52778 : Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
3013 : Handle<Object> value, Handle<Object> receiver,
3014 : Maybe<ShouldThrow> should_throw) {
3015 : DCHECK(!name->IsPrivate());
3016 : Isolate* isolate = proxy->GetIsolate();
3017 52778 : STACK_CHECK(isolate, Nothing<bool>());
3018 : Factory* factory = isolate->factory();
3019 : Handle<String> trap_name = factory->set_string();
3020 :
3021 105500 : if (proxy->IsRevoked()) {
3022 : isolate->Throw(
3023 36 : *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3024 : return Nothing<bool>();
3025 : }
3026 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3027 : Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3028 :
3029 : Handle<Object> trap;
3030 105464 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3031 : isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3032 104930 : if (trap->IsUndefined(isolate)) {
3033 : LookupIterator it =
3034 44413 : LookupIterator::PropertyOrElement(isolate, receiver, name, target);
3035 :
3036 : return Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed,
3037 44413 : should_throw);
3038 : }
3039 :
3040 : Handle<Object> trap_result;
3041 8052 : Handle<Object> args[] = {target, name, value, receiver};
3042 16104 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3043 : isolate, trap_result,
3044 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3045 : Nothing<bool>());
3046 2781 : if (!trap_result->BooleanValue(isolate)) {
3047 585 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3048 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3049 : trap_name, name));
3050 : }
3051 :
3052 : MaybeHandle<Object> result =
3053 2286 : JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet);
3054 :
3055 2286 : if (result.is_null()) {
3056 : return Nothing<bool>();
3057 : }
3058 : return Just(true);
3059 : }
3060 :
3061 26592 : Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
3062 : Handle<Name> name,
3063 : LanguageMode language_mode) {
3064 : DCHECK(!name->IsPrivate());
3065 : ShouldThrow should_throw =
3066 26592 : is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
3067 : Isolate* isolate = proxy->GetIsolate();
3068 26592 : STACK_CHECK(isolate, Nothing<bool>());
3069 : Factory* factory = isolate->factory();
3070 : Handle<String> trap_name = factory->deleteProperty_string();
3071 :
3072 53148 : if (proxy->IsRevoked()) {
3073 : isolate->Throw(
3074 36 : *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3075 : return Nothing<bool>();
3076 : }
3077 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3078 : Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3079 :
3080 : Handle<Object> trap;
3081 53112 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3082 : isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3083 52842 : if (trap->IsUndefined(isolate)) {
3084 17973 : return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
3085 : }
3086 :
3087 : Handle<Object> trap_result;
3088 : Handle<Object> args[] = {target, name};
3089 16896 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3090 : isolate, trap_result,
3091 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3092 : Nothing<bool>());
3093 1809 : if (!trap_result->BooleanValue(isolate)) {
3094 1242 : RETURN_FAILURE(isolate, should_throw,
3095 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3096 : trap_name, name));
3097 : }
3098 :
3099 : // Enforce the invariant.
3100 : PropertyDescriptor target_desc;
3101 : Maybe<bool> owned =
3102 1053 : JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
3103 1053 : MAYBE_RETURN(owned, Nothing<bool>());
3104 1593 : if (owned.FromJust() && !target_desc.configurable()) {
3105 : isolate->Throw(*factory->NewTypeError(
3106 720 : MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
3107 : return Nothing<bool>();
3108 : }
3109 : return Just(true);
3110 : }
3111 :
3112 :
3113 : // static
3114 17 : MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
3115 : Handle<Object> handler) {
3116 34 : if (!target->IsJSReceiver()) {
3117 0 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
3118 : JSProxy);
3119 : }
3120 34 : if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
3121 0 : THROW_NEW_ERROR(isolate,
3122 : NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
3123 : JSProxy);
3124 : }
3125 34 : if (!handler->IsJSReceiver()) {
3126 0 : THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
3127 : JSProxy);
3128 : }
3129 34 : if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
3130 0 : THROW_NEW_ERROR(isolate,
3131 : NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
3132 : JSProxy);
3133 : }
3134 : return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
3135 17 : Handle<JSReceiver>::cast(handler));
3136 : }
3137 :
3138 :
3139 : // static
3140 36 : MaybeHandle<NativeContext> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
3141 : DCHECK(proxy->map()->is_constructor());
3142 72 : if (proxy->IsRevoked()) {
3143 0 : THROW_NEW_ERROR(proxy->GetIsolate(),
3144 : NewTypeError(MessageTemplate::kProxyRevoked),
3145 : NativeContext);
3146 : }
3147 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()),
3148 : proxy->GetIsolate());
3149 36 : return JSReceiver::GetFunctionRealm(target);
3150 : }
3151 :
3152 4212 : Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
3153 : PropertyDescriptor desc;
3154 : Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
3155 4212 : it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
3156 2106 : MAYBE_RETURN(found, Nothing<PropertyAttributes>());
3157 1809 : if (!found.FromJust()) return Just(ABSENT);
3158 1602 : return Just(desc.ToAttributes());
3159 : }
3160 :
3161 : // TODO(jkummerow): Consider unification with FastAsArrayLength() in
3162 : // accessors.cc.
3163 32708 : bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
3164 : DCHECK(value->IsNumber() || value->IsName());
3165 65416 : if (value->ToArrayLength(length)) return true;
3166 88212 : if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
3167 : return false;
3168 : }
3169 :
3170 0 : bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
3171 32708 : return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
3172 : }
3173 :
3174 : // ES6 9.4.2.1
3175 : // static
3176 33071 : Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
3177 : Handle<Object> name,
3178 : PropertyDescriptor* desc,
3179 : Maybe<ShouldThrow> should_throw) {
3180 : // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
3181 : // 2. If P is "length", then:
3182 : // TODO(jkummerow): Check if we need slow string comparison.
3183 33071 : if (*name == ReadOnlyRoots(isolate).length_string()) {
3184 : // 2a. Return ArraySetLength(A, Desc).
3185 363 : return ArraySetLength(isolate, o, desc, should_throw);
3186 : }
3187 : // 3. Else if P is an array index, then:
3188 32708 : uint32_t index = 0;
3189 32708 : if (PropertyKeyToArrayIndex(name, &index)) {
3190 : // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
3191 : PropertyDescriptor old_len_desc;
3192 : Maybe<bool> success = GetOwnPropertyDescriptor(
3193 27898 : isolate, o, isolate->factory()->length_string(), &old_len_desc);
3194 : // 3b. (Assert)
3195 : DCHECK(success.FromJust());
3196 : USE(success);
3197 : // 3c. Let oldLen be oldLenDesc.[[Value]].
3198 27898 : uint32_t old_len = 0;
3199 55796 : CHECK(old_len_desc.value()->ToArrayLength(&old_len));
3200 : // 3d. Let index be ToUint32(P).
3201 : // (Already done above.)
3202 : // 3e. (Assert)
3203 : // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
3204 : // return false.
3205 34146 : if (index >= old_len && old_len_desc.has_writable() &&
3206 : !old_len_desc.writable()) {
3207 0 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3208 : NewTypeError(MessageTemplate::kDefineDisallowed, name));
3209 : }
3210 : // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
3211 : Maybe<bool> succeeded =
3212 27898 : OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
3213 : // 3h. Assert: succeeded is not an abrupt completion.
3214 : // In our case, if should_throw == kThrowOnError, it can be!
3215 : // 3i. If succeeded is false, return false.
3216 55710 : if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
3217 : // 3j. If index >= oldLen, then:
3218 27803 : if (index >= old_len) {
3219 : // 3j i. Set oldLenDesc.[[Value]] to index + 1.
3220 3124 : old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
3221 : // 3j ii. Let succeeded be
3222 : // OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
3223 : succeeded = OrdinaryDefineOwnProperty(isolate, o,
3224 : isolate->factory()->length_string(),
3225 3124 : &old_len_desc, should_throw);
3226 : // 3j iii. Assert: succeeded is true.
3227 : DCHECK(succeeded.FromJust());
3228 : USE(succeeded);
3229 : }
3230 : // 3k. Return true.
3231 : return Just(true);
3232 : }
3233 :
3234 : // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
3235 4810 : return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
3236 : }
3237 :
3238 : // Part of ES6 9.4.2.4 ArraySetLength.
3239 : // static
3240 479567 : bool JSArray::AnythingToArrayLength(Isolate* isolate,
3241 : Handle<Object> length_object,
3242 : uint32_t* output) {
3243 : // Fast path: check numbers and strings that can be converted directly
3244 : // and unobservably.
3245 959134 : if (length_object->ToArrayLength(output)) return true;
3246 1297554 : if (length_object->IsString() &&
3247 432548 : Handle<String>::cast(length_object)->AsArrayIndex(output)) {
3248 : return true;
3249 : }
3250 : // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
3251 : // 3. Let newLen be ToUint32(Desc.[[Value]]).
3252 : Handle<Object> uint32_v;
3253 865006 : if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
3254 : // 4. ReturnIfAbrupt(newLen).
3255 : return false;
3256 : }
3257 : // 5. Let numberLen be ToNumber(Desc.[[Value]]).
3258 : Handle<Object> number_v;
3259 864988 : if (!Object::ToNumber(isolate, length_object).ToHandle(&number_v)) {
3260 : // 6. ReturnIfAbrupt(newLen).
3261 : return false;
3262 : }
3263 : // 7. If newLen != numberLen, throw a RangeError exception.
3264 864988 : if (uint32_v->Number() != number_v->Number()) {
3265 : Handle<Object> exception =
3266 153 : isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
3267 153 : isolate->Throw(*exception);
3268 : return false;
3269 : }
3270 864682 : CHECK(uint32_v->ToArrayLength(output));
3271 : return true;
3272 : }
3273 :
3274 : // ES6 9.4.2.4
3275 : // static
3276 363 : Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
3277 : PropertyDescriptor* desc,
3278 : Maybe<ShouldThrow> should_throw) {
3279 : // 1. If the [[Value]] field of Desc is absent, then
3280 363 : if (!desc->has_value()) {
3281 : // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
3282 : return OrdinaryDefineOwnProperty(
3283 282 : isolate, a, isolate->factory()->length_string(), desc, should_throw);
3284 : }
3285 : // 2. Let newLenDesc be a copy of Desc.
3286 : // (Actual copying is not necessary.)
3287 : PropertyDescriptor* new_len_desc = desc;
3288 : // 3. - 7. Convert Desc.[[Value]] to newLen.
3289 81 : uint32_t new_len = 0;
3290 81 : if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
3291 : DCHECK(isolate->has_pending_exception());
3292 : return Nothing<bool>();
3293 : }
3294 : // 8. Set newLenDesc.[[Value]] to newLen.
3295 : // (Done below, if needed.)
3296 : // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
3297 : PropertyDescriptor old_len_desc;
3298 : Maybe<bool> success = GetOwnPropertyDescriptor(
3299 72 : isolate, a, isolate->factory()->length_string(), &old_len_desc);
3300 : // 10. (Assert)
3301 : DCHECK(success.FromJust());
3302 : USE(success);
3303 : // 11. Let oldLen be oldLenDesc.[[Value]].
3304 72 : uint32_t old_len = 0;
3305 144 : CHECK(old_len_desc.value()->ToArrayLength(&old_len));
3306 : // 12. If newLen >= oldLen, then
3307 72 : if (new_len >= old_len) {
3308 : // 8. Set newLenDesc.[[Value]] to newLen.
3309 : // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
3310 63 : new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
3311 : return OrdinaryDefineOwnProperty(isolate, a,
3312 : isolate->factory()->length_string(),
3313 63 : new_len_desc, should_throw);
3314 : }
3315 : // 13. If oldLenDesc.[[Writable]] is false, return false.
3316 9 : if (!old_len_desc.writable()) {
3317 0 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3318 : NewTypeError(MessageTemplate::kRedefineDisallowed,
3319 : isolate->factory()->length_string()));
3320 : }
3321 : // 14. If newLenDesc.[[Writable]] is absent or has the value true,
3322 : // let newWritable be true.
3323 : bool new_writable = false;
3324 9 : if (!new_len_desc->has_writable() || new_len_desc->writable()) {
3325 : new_writable = true;
3326 : } else {
3327 : // 15. Else,
3328 : // 15a. Need to defer setting the [[Writable]] attribute to false in case
3329 : // any elements cannot be deleted.
3330 : // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
3331 : // 15c. Set newLenDesc.[[Writable]] to true.
3332 : // (Not needed.)
3333 : }
3334 : // Most of steps 16 through 19 is implemented by JSArray::SetLength.
3335 9 : JSArray::SetLength(a, new_len);
3336 : // Steps 19d-ii, 20.
3337 9 : if (!new_writable) {
3338 : PropertyDescriptor readonly;
3339 : readonly.set_writable(false);
3340 : Maybe<bool> success = OrdinaryDefineOwnProperty(
3341 : isolate, a, isolate->factory()->length_string(), &readonly,
3342 0 : should_throw);
3343 : DCHECK(success.FromJust());
3344 : USE(success);
3345 : }
3346 9 : uint32_t actual_new_len = 0;
3347 18 : CHECK(a->length()->ToArrayLength(&actual_new_len));
3348 : // Steps 19d-v, 21. Return false if there were non-deletable elements.
3349 9 : bool result = actual_new_len == new_len;
3350 9 : if (!result) {
3351 9 : RETURN_FAILURE(
3352 : isolate, GetShouldThrow(isolate, should_throw),
3353 : NewTypeError(MessageTemplate::kStrictDeleteProperty,
3354 : isolate->factory()->NewNumberFromUint(actual_new_len - 1),
3355 : a));
3356 : }
3357 : return Just(result);
3358 : }
3359 :
3360 : // ES6 9.5.6
3361 : // static
3362 41050 : Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
3363 : Handle<Object> key,
3364 : PropertyDescriptor* desc,
3365 : Maybe<ShouldThrow> should_throw) {
3366 41050 : STACK_CHECK(isolate, Nothing<bool>());
3367 82354 : if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
3368 : DCHECK(!Handle<Symbol>::cast(key)->IsPrivateName());
3369 : return JSProxy::SetPrivateSymbol(isolate, proxy, Handle<Symbol>::cast(key),
3370 18 : desc, should_throw);
3371 : }
3372 : Handle<String> trap_name = isolate->factory()->defineProperty_string();
3373 : // 1. Assert: IsPropertyKey(P) is true.
3374 : DCHECK(key->IsName() || key->IsNumber());
3375 : // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
3376 : Handle<Object> handler(proxy->handler(), isolate);
3377 : // 3. If handler is null, throw a TypeError exception.
3378 : // 4. Assert: Type(handler) is Object.
3379 82030 : if (proxy->IsRevoked()) {
3380 : isolate->Throw(*isolate->factory()->NewTypeError(
3381 18 : MessageTemplate::kProxyRevoked, trap_name));
3382 : return Nothing<bool>();
3383 : }
3384 : // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
3385 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3386 : // 6. Let trap be ? GetMethod(handler, "defineProperty").
3387 : Handle<Object> trap;
3388 82012 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3389 : isolate, trap,
3390 : Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
3391 : Nothing<bool>());
3392 : // 7. If trap is undefined, then:
3393 81832 : if (trap->IsUndefined(isolate)) {
3394 : // 7a. Return target.[[DefineOwnProperty]](P, Desc).
3395 : return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
3396 31974 : should_throw);
3397 : }
3398 : // 8. Let descObj be FromPropertyDescriptor(Desc).
3399 8942 : Handle<Object> desc_obj = desc->ToObject(isolate);
3400 : // 9. Let booleanTrapResult be
3401 : // ToBoolean(? Call(trap, handler, «target, P, descObj»)).
3402 : Handle<Name> property_name =
3403 17884 : key->IsName()
3404 : ? Handle<Name>::cast(key)
3405 8942 : : Handle<Name>::cast(isolate->factory()->NumberToString(key));
3406 : // Do not leak private property names.
3407 : DCHECK(!property_name->IsPrivate());
3408 : Handle<Object> trap_result_obj;
3409 8942 : Handle<Object> args[] = {target, property_name, desc_obj};
3410 17884 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3411 : isolate, trap_result_obj,
3412 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3413 : Nothing<bool>());
3414 : // 10. If booleanTrapResult is false, return false.
3415 1323 : if (!trap_result_obj->BooleanValue(isolate)) {
3416 99 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3417 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
3418 : trap_name, property_name));
3419 : }
3420 : // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
3421 : PropertyDescriptor target_desc;
3422 : Maybe<bool> target_found =
3423 1242 : JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
3424 1242 : MAYBE_RETURN(target_found, Nothing<bool>());
3425 : // 12. Let extensibleTarget be ? IsExtensible(target).
3426 1242 : Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
3427 1242 : MAYBE_RETURN(maybe_extensible, Nothing<bool>());
3428 : bool extensible_target = maybe_extensible.FromJust();
3429 : // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
3430 : // is false, then:
3431 : // 13a. Let settingConfigFalse be true.
3432 : // 14. Else let settingConfigFalse be false.
3433 1935 : bool setting_config_false = desc->has_configurable() && !desc->configurable();
3434 : // 15. If targetDesc is undefined, then
3435 1242 : if (!target_found.FromJust()) {
3436 : // 15a. If extensibleTarget is false, throw a TypeError exception.
3437 621 : if (!extensible_target) {
3438 : isolate->Throw(*isolate->factory()->NewTypeError(
3439 18 : MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
3440 : return Nothing<bool>();
3441 : }
3442 : // 15b. If settingConfigFalse is true, throw a TypeError exception.
3443 612 : if (setting_config_false) {
3444 : isolate->Throw(*isolate->factory()->NewTypeError(
3445 18 : MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
3446 : return Nothing<bool>();
3447 : }
3448 : } else {
3449 : // 16. Else targetDesc is not undefined,
3450 : // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
3451 : // targetDesc) is false, throw a TypeError exception.
3452 : Maybe<bool> valid = IsCompatiblePropertyDescriptor(
3453 : isolate, extensible_target, desc, &target_desc, property_name,
3454 621 : Just(kDontThrow));
3455 639 : MAYBE_RETURN(valid, Nothing<bool>());
3456 621 : if (!valid.FromJust()) {
3457 : isolate->Throw(*isolate->factory()->NewTypeError(
3458 18 : MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
3459 : return Nothing<bool>();
3460 : }
3461 : // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
3462 : // true, throw a TypeError exception.
3463 702 : if (setting_config_false && target_desc.configurable()) {
3464 : isolate->Throw(*isolate->factory()->NewTypeError(
3465 18 : MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
3466 : return Nothing<bool>();
3467 : }
3468 : }
3469 : // 17. Return true.
3470 : return Just(true);
3471 : }
3472 :
3473 : // static
3474 36 : Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
3475 : Handle<Symbol> private_name,
3476 : PropertyDescriptor* desc,
3477 : Maybe<ShouldThrow> should_throw) {
3478 : DCHECK(!private_name->IsPrivateName());
3479 : // Despite the generic name, this can only add private data properties.
3480 54 : if (!PropertyDescriptor::IsDataDescriptor(desc) ||
3481 18 : desc->ToAttributes() != DONT_ENUM) {
3482 36 : RETURN_FAILURE(isolate, GetShouldThrow(isolate, should_throw),
3483 : NewTypeError(MessageTemplate::kProxyPrivate));
3484 : }
3485 : DCHECK(proxy->map()->is_dictionary_map());
3486 : Handle<Object> value =
3487 : desc->has_value()
3488 : ? desc->value()
3489 18 : : Handle<Object>::cast(isolate->factory()->undefined_value());
3490 :
3491 18 : LookupIterator it(proxy, private_name, proxy);
3492 :
3493 18 : if (it.IsFound()) {
3494 : DCHECK_EQ(LookupIterator::DATA, it.state());
3495 : DCHECK_EQ(DONT_ENUM, it.property_attributes());
3496 6 : it.WriteDataValue(value, false);
3497 : return Just(true);
3498 : }
3499 :
3500 24 : Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
3501 : PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell);
3502 : Handle<NameDictionary> result =
3503 12 : NameDictionary::Add(isolate, dict, private_name, value, details);
3504 24 : if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
3505 : return Just(true);
3506 : }
3507 :
3508 : // ES6 9.5.5
3509 : // static
3510 30701 : Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
3511 : Handle<JSProxy> proxy,
3512 : Handle<Name> name,
3513 : PropertyDescriptor* desc) {
3514 : DCHECK(!name->IsPrivate());
3515 30701 : STACK_CHECK(isolate, Nothing<bool>());
3516 :
3517 : Handle<String> trap_name =
3518 : isolate->factory()->getOwnPropertyDescriptor_string();
3519 : // 1. (Assert)
3520 : // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
3521 : Handle<Object> handler(proxy->handler(), isolate);
3522 : // 3. If handler is null, throw a TypeError exception.
3523 : // 4. Assert: Type(handler) is Object.
3524 61368 : if (proxy->IsRevoked()) {
3525 : isolate->Throw(*isolate->factory()->NewTypeError(
3526 36 : MessageTemplate::kProxyRevoked, trap_name));
3527 : return Nothing<bool>();
3528 : }
3529 : // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
3530 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3531 : // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
3532 : Handle<Object> trap;
3533 61332 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3534 : isolate, trap,
3535 : Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
3536 : Nothing<bool>());
3537 : // 7. If trap is undefined, then
3538 61224 : if (trap->IsUndefined(isolate)) {
3539 : // 7a. Return target.[[GetOwnProperty]](P).
3540 19162 : return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
3541 : }
3542 : // 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
3543 : Handle<Object> trap_result_obj;
3544 : Handle<Object> args[] = {target, name};
3545 22900 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3546 : isolate, trap_result_obj,
3547 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3548 : Nothing<bool>());
3549 : // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
3550 : // TypeError exception.
3551 15381 : if (!trap_result_obj->IsJSReceiver() &&
3552 5661 : !trap_result_obj->IsUndefined(isolate)) {
3553 : isolate->Throw(*isolate->factory()->NewTypeError(
3554 36 : MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
3555 : return Nothing<bool>();
3556 : }
3557 : // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
3558 : PropertyDescriptor target_desc;
3559 : Maybe<bool> found =
3560 4842 : JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
3561 4842 : MAYBE_RETURN(found, Nothing<bool>());
3562 : // 11. If trapResultObj is undefined, then
3563 9684 : if (trap_result_obj->IsUndefined(isolate)) {
3564 : // 11a. If targetDesc is undefined, return undefined.
3565 783 : if (!found.FromJust()) return Just(false);
3566 : // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
3567 : // exception.
3568 45 : if (!target_desc.configurable()) {
3569 : isolate->Throw(*isolate->factory()->NewTypeError(
3570 54 : MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
3571 : return Nothing<bool>();
3572 : }
3573 : // 11c. Let extensibleTarget be ? IsExtensible(target).
3574 18 : Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3575 18 : MAYBE_RETURN(extensible_target, Nothing<bool>());
3576 : // 11d. (Assert)
3577 : // 11e. If extensibleTarget is false, throw a TypeError exception.
3578 18 : if (!extensible_target.FromJust()) {
3579 : isolate->Throw(*isolate->factory()->NewTypeError(
3580 0 : MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
3581 : return Nothing<bool>();
3582 : }
3583 : // 11f. Return undefined.
3584 : return Just(false);
3585 : }
3586 : // 12. Let extensibleTarget be ? IsExtensible(target).
3587 4059 : Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
3588 4059 : MAYBE_RETURN(extensible_target, Nothing<bool>());
3589 : // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
3590 4059 : if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
3591 4059 : desc)) {
3592 : DCHECK(isolate->has_pending_exception());
3593 : return Nothing<bool>();
3594 : }
3595 : // 14. Call CompletePropertyDescriptor(resultDesc).
3596 3987 : PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
3597 : // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
3598 : // resultDesc, targetDesc).
3599 : Maybe<bool> valid = IsCompatiblePropertyDescriptor(
3600 : isolate, extensible_target.FromJust(), desc, &target_desc, name,
3601 3987 : Just(kDontThrow));
3602 3987 : MAYBE_RETURN(valid, Nothing<bool>());
3603 : // 16. If valid is false, throw a TypeError exception.
3604 3987 : if (!valid.FromJust()) {
3605 : isolate->Throw(*isolate->factory()->NewTypeError(
3606 36 : MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
3607 : return Nothing<bool>();
3608 : }
3609 : // 17. If resultDesc.[[Configurable]] is false, then
3610 3969 : if (!desc->configurable()) {
3611 : // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
3612 513 : if (target_desc.is_empty() || target_desc.configurable()) {
3613 : // 17a i. Throw a TypeError exception.
3614 : isolate->Throw(*isolate->factory()->NewTypeError(
3615 : MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
3616 36 : name));
3617 : return Nothing<bool>();
3618 : }
3619 : }
3620 : // 18. Return resultDesc.
3621 : return Just(true);
3622 : }
3623 :
3624 73220 : Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
3625 : ShouldThrow should_throw) {
3626 : Isolate* isolate = proxy->GetIsolate();
3627 73220 : STACK_CHECK(isolate, Nothing<bool>());
3628 : Factory* factory = isolate->factory();
3629 : Handle<String> trap_name = factory->preventExtensions_string();
3630 :
3631 146422 : if (proxy->IsRevoked()) {
3632 : isolate->Throw(
3633 36 : *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3634 : return Nothing<bool>();
3635 : }
3636 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3637 : Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3638 :
3639 : Handle<Object> trap;
3640 146386 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3641 : isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3642 146350 : if (trap->IsUndefined(isolate)) {
3643 63461 : return JSReceiver::PreventExtensions(target, should_throw);
3644 : }
3645 :
3646 : Handle<Object> trap_result;
3647 : Handle<Object> args[] = {target};
3648 19428 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3649 : isolate, trap_result,
3650 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3651 : Nothing<bool>());
3652 54 : if (!trap_result->BooleanValue(isolate)) {
3653 18 : RETURN_FAILURE(
3654 : isolate, should_throw,
3655 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
3656 : }
3657 :
3658 : // Enforce the invariant.
3659 36 : Maybe<bool> target_result = JSReceiver::IsExtensible(target);
3660 36 : MAYBE_RETURN(target_result, Nothing<bool>());
3661 36 : if (target_result.FromJust()) {
3662 : isolate->Throw(*factory->NewTypeError(
3663 18 : MessageTemplate::kProxyPreventExtensionsExtensible));
3664 : return Nothing<bool>();
3665 : }
3666 : return Just(true);
3667 : }
3668 :
3669 81231 : Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
3670 : Isolate* isolate = proxy->GetIsolate();
3671 81231 : STACK_CHECK(isolate, Nothing<bool>());
3672 : Factory* factory = isolate->factory();
3673 : Handle<String> trap_name = factory->isExtensible_string();
3674 :
3675 162442 : if (proxy->IsRevoked()) {
3676 : isolate->Throw(
3677 36 : *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
3678 : return Nothing<bool>();
3679 : }
3680 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
3681 : Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
3682 :
3683 : Handle<Object> trap;
3684 162406 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3685 : isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
3686 162370 : if (trap->IsUndefined(isolate)) {
3687 70938 : return JSReceiver::IsExtensible(target);
3688 : }
3689 :
3690 : Handle<Object> trap_result;
3691 : Handle<Object> args[] = {target};
3692 20494 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3693 : isolate, trap_result,
3694 : Execution::Call(isolate, trap, handler, arraysize(args), args),
3695 : Nothing<bool>());
3696 :
3697 : // Enforce the invariant.
3698 423 : Maybe<bool> target_result = JSReceiver::IsExtensible(target);
3699 423 : MAYBE_RETURN(target_result, Nothing<bool>());
3700 423 : if (target_result.FromJust() != trap_result->BooleanValue(isolate)) {
3701 : isolate->Throw(
3702 : *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
3703 54 : factory->ToBoolean(target_result.FromJust())));
3704 : return Nothing<bool>();
3705 : }
3706 396 : return target_result;
3707 : }
3708 :
3709 17873595 : Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
3710 : Handle<DescriptorArray> desc,
3711 : int enumeration_index,
3712 : int slack) {
3713 : return DescriptorArray::CopyUpToAddAttributes(isolate, desc,
3714 17873595 : enumeration_index, NONE, slack);
3715 : }
3716 :
3717 18009029 : Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
3718 : Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index,
3719 : PropertyAttributes attributes, int slack) {
3720 18009029 : if (enumeration_index + slack == 0) {
3721 : return isolate->factory()->empty_descriptor_array();
3722 : }
3723 :
3724 : int size = enumeration_index;
3725 :
3726 : Handle<DescriptorArray> descriptors =
3727 : DescriptorArray::Allocate(isolate, size, slack);
3728 :
3729 16501312 : if (attributes != NONE) {
3730 222554 : for (int i = 0; i < size; ++i) {
3731 445105 : MaybeObject value_or_field_type = desc->GetValue(i);
3732 222553 : Name key = desc->GetKey(i);
3733 222554 : PropertyDetails details = desc->GetDetails(i);
3734 : // Bulk attribute changes never affect private properties.
3735 222554 : if (!key->IsPrivate()) {
3736 : int mask = DONT_DELETE | DONT_ENUM;
3737 : // READ_ONLY is an invalid attribute for JS setters/getters.
3738 222516 : HeapObject heap_object;
3739 445996 : if (details.kind() != kAccessor ||
3740 964 : !(value_or_field_type->GetHeapObjectIfStrong(&heap_object) &&
3741 964 : heap_object->IsAccessorPair())) {
3742 : mask |= READ_ONLY;
3743 : }
3744 : details = details.CopyAddAttributes(
3745 222516 : static_cast<PropertyAttributes>(attributes & mask));
3746 : }
3747 222553 : descriptors->Set(i, key, value_or_field_type, details);
3748 : }
3749 : } else {
3750 110295593 : for (int i = 0; i < size; ++i) {
3751 110295584 : descriptors->CopyFrom(i, *desc);
3752 : }
3753 : }
3754 :
3755 16553569 : if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
3756 :
3757 16501328 : return descriptors;
3758 : }
3759 :
3760 : // Create a new descriptor array with only enumerable, configurable, writeable
3761 : // data properties, but identical field locations.
3762 306 : Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
3763 : Isolate* isolate, Handle<DescriptorArray> src, int enumeration_index,
3764 : int slack) {
3765 306 : if (enumeration_index + slack == 0) {
3766 : return isolate->factory()->empty_descriptor_array();
3767 : }
3768 :
3769 : int size = enumeration_index;
3770 : Handle<DescriptorArray> descriptors =
3771 : DescriptorArray::Allocate(isolate, size, slack);
3772 :
3773 846 : for (int i = 0; i < size; ++i) {
3774 540 : Name key = src->GetKey(i);
3775 540 : PropertyDetails details = src->GetDetails(i);
3776 :
3777 : DCHECK(!key->IsPrivateName());
3778 : DCHECK(details.IsEnumerable());
3779 : DCHECK_EQ(details.kind(), kData);
3780 :
3781 : // Ensure the ObjectClone property details are NONE, and that all source
3782 : // details did not contain DONT_ENUM.
3783 : PropertyDetails new_details(kData, NONE, details.location(),
3784 : details.constness(), details.representation(),
3785 : details.field_index());
3786 : // Do not propagate the field type of normal object fields from the
3787 : // original descriptors since FieldType changes don't create new maps.
3788 1080 : MaybeObject type = src->GetValue(i);
3789 540 : if (details.location() == PropertyLocation::kField) {
3790 540 : type = MaybeObject::FromObject(FieldType::Any());
3791 : }
3792 540 : descriptors->Set(i, key, type, new_details);
3793 : }
3794 :
3795 306 : descriptors->Sort();
3796 :
3797 306 : return descriptors;
3798 : }
3799 :
3800 4858 : bool DescriptorArray::IsEqualUpTo(DescriptorArray desc, int nof_descriptors) {
3801 71868 : for (int i = 0; i < nof_descriptors; i++) {
3802 201030 : if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
3803 : return false;
3804 : }
3805 67010 : PropertyDetails details = GetDetails(i);
3806 67010 : PropertyDetails other_details = desc->GetDetails(i);
3807 134020 : if (details.kind() != other_details.kind() ||
3808 134020 : details.location() != other_details.location() ||
3809 : !details.representation().Equals(other_details.representation())) {
3810 : return false;
3811 : }
3812 : }
3813 : return true;
3814 : }
3815 :
3816 9774491 : Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
3817 : Handle<FixedArray> array, int index,
3818 : Handle<Object> value,
3819 : PretenureFlag pretenure) {
3820 9774491 : if (index < array->length()) {
3821 9240587 : array->set(index, *value);
3822 9240587 : return array;
3823 : }
3824 : int capacity = array->length();
3825 533904 : do {
3826 1067808 : capacity = JSObject::NewElementsCapacity(capacity);
3827 : } while (capacity <= index);
3828 : Handle<FixedArray> new_array =
3829 533904 : isolate->factory()->NewUninitializedFixedArray(capacity, pretenure);
3830 533904 : array->CopyTo(0, *new_array, 0, array->length());
3831 1067808 : new_array->FillWithHoles(array->length(), new_array->length());
3832 533904 : new_array->set(index, *value);
3833 533904 : return new_array;
3834 : }
3835 :
3836 0 : bool FixedArray::ContainsSortedNumbers() {
3837 0 : for (int i = 1; i < length(); ++i) {
3838 0 : Object a_obj = get(i - 1);
3839 0 : Object b_obj = get(i);
3840 0 : if (!a_obj->IsNumber() || !b_obj->IsNumber()) return false;
3841 :
3842 0 : uint32_t a = NumberToUint32(a_obj);
3843 0 : uint32_t b = NumberToUint32(b_obj);
3844 :
3845 0 : if (a > b) return false;
3846 : }
3847 : return true;
3848 : }
3849 :
3850 774416 : Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
3851 : Handle<FixedArray> array,
3852 : int new_length) {
3853 774416 : if (new_length == 0) {
3854 183802 : return array->GetReadOnlyRoots().empty_fixed_array_handle();
3855 : } else {
3856 682516 : array->Shrink(isolate, new_length);
3857 682516 : return array;
3858 : }
3859 : }
3860 :
3861 1997584 : void FixedArray::Shrink(Isolate* isolate, int new_length) {
3862 : DCHECK(0 < new_length && new_length <= length());
3863 1997584 : if (new_length < length()) {
3864 1351106 : isolate->heap()->RightTrimFixedArray(*this, length() - new_length);
3865 : }
3866 1997584 : }
3867 :
3868 551191 : void FixedArray::CopyTo(int pos, FixedArray dest, int dest_pos, int len) const {
3869 : DisallowHeapAllocation no_gc;
3870 : // Return early if len == 0 so that we don't try to read the write barrier off
3871 : // a canonical read-only empty fixed array.
3872 1102387 : if (len == 0) return;
3873 : WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
3874 8664497 : for (int index = 0; index < len; index++) {
3875 16240690 : dest->set(dest_pos + index, get(pos + index), mode);
3876 : }
3877 : }
3878 :
3879 :
3880 : // static
3881 1929 : Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
3882 : Handle<Object> obj) {
3883 1929 : int length = array->Length();
3884 1929 : array = EnsureSpace(isolate, array, length + 1);
3885 : // Check that GC didn't remove elements from the array.
3886 : DCHECK_EQ(array->Length(), length);
3887 1929 : array->Set(length, *obj);
3888 1929 : array->SetLength(length + 1);
3889 1929 : return array;
3890 : }
3891 :
3892 : // static
3893 5 : Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
3894 : Handle<Object> obj1, Handle<Object> obj2) {
3895 5 : int length = array->Length();
3896 5 : array = EnsureSpace(isolate, array, length + 2);
3897 : // Check that GC didn't remove elements from the array.
3898 : DCHECK_EQ(array->Length(), length);
3899 5 : array->Set(length, *obj1);
3900 10 : array->Set(length + 1, *obj2);
3901 5 : array->SetLength(length + 2);
3902 5 : return array;
3903 : }
3904 :
3905 : // static
3906 354 : Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) {
3907 : Handle<FixedArray> fixed_array =
3908 354 : isolate->factory()->NewFixedArray(size + kFirstIndex);
3909 : fixed_array->set_map_no_write_barrier(
3910 : ReadOnlyRoots(isolate).array_list_map());
3911 354 : Handle<ArrayList> result = Handle<ArrayList>::cast(fixed_array);
3912 354 : result->SetLength(0);
3913 354 : return result;
3914 : }
3915 :
3916 412 : Handle<FixedArray> ArrayList::Elements(Isolate* isolate,
3917 : Handle<ArrayList> array) {
3918 412 : int length = array->Length();
3919 412 : Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
3920 : // Do not copy the first entry, i.e., the length.
3921 412 : array->CopyTo(kFirstIndex, *result, 0, length);
3922 412 : return result;
3923 : }
3924 :
3925 : namespace {
3926 :
3927 9420623 : Handle<FixedArray> EnsureSpaceInFixedArray(Isolate* isolate,
3928 : Handle<FixedArray> array,
3929 : int length) {
3930 : int capacity = array->length();
3931 9420623 : if (capacity < length) {
3932 : int new_capacity = length;
3933 5302 : new_capacity = new_capacity + Max(new_capacity / 2, 2);
3934 2651 : int grow_by = new_capacity - capacity;
3935 2651 : array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
3936 : }
3937 9420623 : return array;
3938 : }
3939 :
3940 : } // namespace
3941 :
3942 : // static
3943 1934 : Handle<ArrayList> ArrayList::EnsureSpace(Isolate* isolate,
3944 : Handle<ArrayList> array, int length) {
3945 : const bool empty = (array->length() == 0);
3946 : Handle<FixedArray> ret =
3947 3868 : EnsureSpaceInFixedArray(isolate, array, kFirstIndex + length);
3948 1934 : if (empty) {
3949 50 : ret->set_map_no_write_barrier(array->GetReadOnlyRoots().array_list_map());
3950 :
3951 50 : Handle<ArrayList>::cast(ret)->SetLength(0);
3952 : }
3953 1934 : return Handle<ArrayList>::cast(ret);
3954 : }
3955 :
3956 : // static
3957 12327455 : Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
3958 : Handle<WeakArrayList> array,
3959 : const MaybeObjectHandle& value) {
3960 : int length = array->length();
3961 12327461 : array = EnsureSpace(isolate, array, length + 1);
3962 : // Reload length; GC might have removed elements from the array.
3963 : length = array->length();
3964 24654914 : array->Set(length, *value);
3965 12327459 : array->set_length(length + 1);
3966 12327460 : return array;
3967 : }
3968 :
3969 851777 : bool WeakArrayList::IsFull() { return length() == capacity(); }
3970 :
3971 : // static
3972 12459769 : Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
3973 : Handle<WeakArrayList> array,
3974 : int length,
3975 : PretenureFlag pretenure) {
3976 : int capacity = array->capacity();
3977 12459769 : if (capacity < length) {
3978 : int new_capacity = length;
3979 3067010 : new_capacity = new_capacity + Max(new_capacity / 2, 2);
3980 1533505 : int grow_by = new_capacity - capacity;
3981 : array =
3982 1533505 : isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by, pretenure);
3983 : }
3984 12459767 : return array;
3985 : }
3986 :
3987 412 : int WeakArrayList::CountLiveWeakReferences() const {
3988 : int live_weak_references = 0;
3989 237322 : for (int i = 0; i < length(); i++) {
3990 236498 : if (Get(i)->IsWeak()) {
3991 117889 : ++live_weak_references;
3992 : }
3993 : }
3994 412 : return live_weak_references;
3995 : }
3996 :
3997 3577028 : bool WeakArrayList::RemoveOne(const MaybeObjectHandle& value) {
3998 3577029 : if (length() == 0) return false;
3999 : // Optimize for the most recently added element to be removed again.
4000 : MaybeObject cleared_weak_ref =
4001 3577030 : HeapObjectReference::ClearedValue(GetIsolate());
4002 3577030 : int last_index = length() - 1;
4003 3577050 : for (int i = last_index; i >= 0; --i) {
4004 7154092 : if (Get(i) == *value) {
4005 : // Move the last element into the this slot (or no-op, if this is the
4006 : // last slot).
4007 3577026 : Set(i, Get(last_index));
4008 3577026 : Set(last_index, cleared_weak_ref);
4009 : set_length(last_index);
4010 3577026 : return true;
4011 : }
4012 : }
4013 : return false;
4014 : }
4015 :
4016 : // static
4017 497486 : Handle<WeakArrayList> PrototypeUsers::Add(Isolate* isolate,
4018 : Handle<WeakArrayList> array,
4019 : Handle<Map> value,
4020 : int* assigned_index) {
4021 : int length = array->length();
4022 497489 : if (length == 0) {
4023 : // Uninitialized WeakArrayList; need to initialize empty_slot_index.
4024 117651 : array = WeakArrayList::EnsureSpace(isolate, array, kFirstIndex + 1);
4025 : set_empty_slot_index(*array, kNoEmptySlotsMarker);
4026 235302 : array->Set(kFirstIndex, HeapObjectReference::Weak(*value));
4027 : array->set_length(kFirstIndex + 1);
4028 117651 : if (assigned_index != nullptr) *assigned_index = kFirstIndex;
4029 117651 : return array;
4030 : }
4031 :
4032 : // If the array has unfilled space at the end, use it.
4033 379838 : if (!array->IsFull()) {
4034 536288 : array->Set(length, HeapObjectReference::Weak(*value));
4035 268144 : array->set_length(length + 1);
4036 268144 : if (assigned_index != nullptr) *assigned_index = length;
4037 268144 : return array;
4038 : }
4039 :
4040 : // If there are empty slots, use one of them.
4041 111694 : int empty_slot = Smi::ToInt(empty_slot_index(*array));
4042 111694 : if (empty_slot != kNoEmptySlotsMarker) {
4043 : DCHECK_GE(empty_slot, kFirstIndex);
4044 97146 : CHECK_LT(empty_slot, array->length());
4045 194292 : int next_empty_slot = array->Get(empty_slot).ToSmi().value();
4046 :
4047 194292 : array->Set(empty_slot, HeapObjectReference::Weak(*value));
4048 97146 : if (assigned_index != nullptr) *assigned_index = empty_slot;
4049 :
4050 : set_empty_slot_index(*array, next_empty_slot);
4051 97146 : return array;
4052 : } else {
4053 : DCHECK_EQ(empty_slot, kNoEmptySlotsMarker);
4054 : }
4055 :
4056 : // Array full and no empty slots. Grow the array.
4057 14548 : array = WeakArrayList::EnsureSpace(isolate, array, length + 1);
4058 29094 : array->Set(length, HeapObjectReference::Weak(*value));
4059 : array->set_length(length + 1);
4060 14548 : if (assigned_index != nullptr) *assigned_index = length;
4061 14548 : return array;
4062 : }
4063 :
4064 30 : WeakArrayList PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
4065 : CompactionCallback callback,
4066 : PretenureFlag pretenure) {
4067 30 : if (array->length() == 0) {
4068 : return *array;
4069 : }
4070 30 : int new_length = kFirstIndex + array->CountLiveWeakReferences();
4071 30 : if (new_length == array->length()) {
4072 : return *array;
4073 : }
4074 :
4075 : Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
4076 : heap->isolate(),
4077 : handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
4078 5 : new_length, pretenure);
4079 : // Allocation might have caused GC and turned some of the elements into
4080 : // cleared weak heap objects. Count the number of live objects again.
4081 : int copy_to = kFirstIndex;
4082 40 : for (int i = kFirstIndex; i < array->length(); i++) {
4083 15 : MaybeObject element = array->Get(i);
4084 15 : HeapObject value;
4085 15 : if (element->GetHeapObjectIfWeak(&value)) {
4086 5 : callback(value, i, copy_to);
4087 10 : new_array->Set(copy_to++, element);
4088 : } else {
4089 : DCHECK(element->IsCleared() || element->IsSmi());
4090 : }
4091 : }
4092 : new_array->set_length(copy_to);
4093 : set_empty_slot_index(*new_array, kNoEmptySlotsMarker);
4094 : return *new_array;
4095 : }
4096 :
4097 4255636 : Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
4098 : Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture_count) {
4099 : DCHECK_GE(match_info->length(), kLastMatchOverhead);
4100 4255636 : const int required_length = kFirstCaptureIndex + capture_count;
4101 : return Handle<RegExpMatchInfo>::cast(
4102 4255636 : EnsureSpaceInFixedArray(isolate, match_info, required_length));
4103 : }
4104 :
4105 : // static
4106 5007098 : Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
4107 : Handle<Object> receiver,
4108 : Handle<JSFunction> function,
4109 : Handle<AbstractCode> code,
4110 : int offset, int flags,
4111 : Handle<FixedArray> parameters) {
4112 5007098 : const int frame_count = in->FrameCount();
4113 5007098 : const int new_length = LengthFor(frame_count + 1);
4114 : Handle<FrameArray> array =
4115 5007098 : EnsureSpace(function->GetIsolate(), in, new_length);
4116 10014196 : array->SetReceiver(frame_count, *receiver);
4117 10014196 : array->SetFunction(frame_count, *function);
4118 10014196 : array->SetCode(frame_count, *code);
4119 5007098 : array->SetOffset(frame_count, Smi::FromInt(offset));
4120 5007098 : array->SetFlags(frame_count, Smi::FromInt(flags));
4121 10014196 : array->SetParameters(frame_count, *parameters);
4122 : array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
4123 5007098 : return array;
4124 : }
4125 :
4126 : // static
4127 155955 : Handle<FrameArray> FrameArray::AppendWasmFrame(
4128 : Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
4129 : int wasm_function_index, wasm::WasmCode* code, int offset, int flags) {
4130 : Isolate* isolate = wasm_instance->GetIsolate();
4131 155955 : const int frame_count = in->FrameCount();
4132 155955 : const int new_length = LengthFor(frame_count + 1);
4133 155955 : Handle<FrameArray> array = EnsureSpace(isolate, in, new_length);
4134 : // The {code} will be {nullptr} for interpreted wasm frames.
4135 : Handle<Foreign> code_foreign =
4136 155955 : isolate->factory()->NewForeign(reinterpret_cast<Address>(code));
4137 311910 : array->SetWasmInstance(frame_count, *wasm_instance);
4138 155955 : array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
4139 311910 : array->SetWasmCodeObject(frame_count, *code_foreign);
4140 155955 : array->SetOffset(frame_count, Smi::FromInt(offset));
4141 155955 : array->SetFlags(frame_count, Smi::FromInt(flags));
4142 : array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
4143 155955 : return array;
4144 : }
4145 :
4146 1314082 : void FrameArray::ShrinkToFit(Isolate* isolate) {
4147 2628164 : Shrink(isolate, LengthFor(FrameCount()));
4148 1314082 : }
4149 :
4150 : // static
4151 5163053 : Handle<FrameArray> FrameArray::EnsureSpace(Isolate* isolate,
4152 : Handle<FrameArray> array,
4153 : int length) {
4154 : return Handle<FrameArray>::cast(
4155 5163053 : EnsureSpaceInFixedArray(isolate, array, length));
4156 : }
4157 :
4158 460292 : Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
4159 : int nof_descriptors,
4160 : int slack,
4161 : PretenureFlag pretenure) {
4162 460292 : return nof_descriptors + slack == 0
4163 : ? isolate->factory()->empty_descriptor_array()
4164 : : isolate->factory()->NewDescriptorArray(nof_descriptors, slack,
4165 33923828 : pretenure);
4166 : }
4167 :
4168 16961968 : void DescriptorArray::Initialize(EnumCache enum_cache,
4169 : HeapObject undefined_value,
4170 : int nof_descriptors, int slack) {
4171 : DCHECK_GE(nof_descriptors, 0);
4172 : DCHECK_GE(slack, 0);
4173 : DCHECK_LE(nof_descriptors + slack, kMaxNumberOfDescriptors);
4174 16961968 : set_number_of_all_descriptors(nof_descriptors + slack);
4175 16961968 : set_number_of_descriptors(nof_descriptors);
4176 : set_raw_number_of_marked_descriptors(0);
4177 : set_filler16bits(0);
4178 16961968 : set_enum_cache(enum_cache);
4179 : MemsetTagged(GetDescriptorSlot(0), undefined_value,
4180 16961974 : number_of_all_descriptors() * kEntrySize);
4181 16961972 : }
4182 :
4183 57 : void DescriptorArray::ClearEnumCache() {
4184 114 : set_enum_cache(GetReadOnlyRoots().empty_enum_cache());
4185 57 : }
4186 :
4187 268881 : void DescriptorArray::Replace(int index, Descriptor* descriptor) {
4188 : descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
4189 268882 : Set(index, descriptor);
4190 268885 : }
4191 :
4192 : // static
4193 47846 : void DescriptorArray::InitializeOrChangeEnumCache(
4194 : Handle<DescriptorArray> descriptors, Isolate* isolate,
4195 : Handle<FixedArray> keys, Handle<FixedArray> indices) {
4196 47846 : EnumCache enum_cache = descriptors->enum_cache();
4197 47846 : if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
4198 94150 : enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
4199 47075 : descriptors->set_enum_cache(enum_cache);
4200 : } else {
4201 771 : enum_cache->set_keys(*keys);
4202 771 : enum_cache->set_indices(*indices);
4203 : }
4204 47846 : }
4205 :
4206 110295584 : void DescriptorArray::CopyFrom(int index, DescriptorArray src) {
4207 110295584 : PropertyDetails details = src->GetDetails(index);
4208 110295591 : Set(index, src->GetKey(index), src->GetValue(index), details);
4209 110295592 : }
4210 :
4211 14242150 : void DescriptorArray::Sort() {
4212 : // In-place heap sort.
4213 14242150 : int len = number_of_descriptors();
4214 : // Reset sorting since the descriptor array might contain invalid pointers.
4215 14242150 : for (int i = 0; i < len; ++i) SetSortedKey(i, i);
4216 : // Bottom-up max-heap construction.
4217 : // Index of the last node with children
4218 14242153 : const int max_parent_index = (len / 2) - 1;
4219 57378776 : for (int i = max_parent_index; i >= 0; --i) {
4220 : int parent_index = i;
4221 43136639 : const uint32_t parent_hash = GetSortedKey(i)->Hash();
4222 132211334 : while (parent_index <= max_parent_index) {
4223 60865607 : int child_index = 2 * parent_index + 1;
4224 60865607 : uint32_t child_hash = GetSortedKey(child_index)->Hash();
4225 60865552 : if (child_index + 1 < len) {
4226 49795312 : uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
4227 49795293 : if (right_child_hash > child_hash) {
4228 : child_index++;
4229 : child_hash = right_child_hash;
4230 : }
4231 : }
4232 60865533 : if (child_hash <= parent_hash) break;
4233 45937988 : SwapSortedKeys(parent_index, child_index);
4234 : // Now element at child_index could be < its children.
4235 : parent_index = child_index; // parent_hash remains correct.
4236 : }
4237 : }
4238 :
4239 : // Extract elements and create sorted array.
4240 92254185 : for (int i = len - 1; i > 0; --i) {
4241 : // Put max element at the back of the array.
4242 78012021 : SwapSortedKeys(0, i);
4243 : // Shift down the new top element.
4244 : int parent_index = 0;
4245 78011905 : const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
4246 78011912 : const int max_parent_index = (i / 2) - 1;
4247 282430301 : while (parent_index <= max_parent_index) {
4248 138530120 : int child_index = parent_index * 2 + 1;
4249 138530120 : uint32_t child_hash = GetSortedKey(child_index)->Hash();
4250 138530063 : if (child_index + 1 < i) {
4251 118337697 : uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
4252 118337675 : if (right_child_hash > child_hash) {
4253 : child_index++;
4254 : child_hash = right_child_hash;
4255 : }
4256 : }
4257 138530041 : if (child_hash <= parent_hash) break;
4258 126406262 : SwapSortedKeys(parent_index, child_index);
4259 : parent_index = child_index;
4260 : }
4261 : }
4262 : DCHECK(IsSortedNoDuplicates());
4263 14242164 : }
4264 :
4265 37599431 : int16_t DescriptorArray::UpdateNumberOfMarkedDescriptors(
4266 : unsigned mark_compact_epoch, int16_t new_marked) {
4267 : STATIC_ASSERT(kMaxNumberOfDescriptors <=
4268 : NumberOfMarkedDescriptors::kMaxNumberOfMarkedDescriptors);
4269 : int16_t old_raw_marked = raw_number_of_marked_descriptors();
4270 : int16_t old_marked =
4271 : NumberOfMarkedDescriptors::decode(mark_compact_epoch, old_raw_marked);
4272 : int16_t new_raw_marked =
4273 : NumberOfMarkedDescriptors::encode(mark_compact_epoch, new_marked);
4274 75198868 : while (old_marked < new_marked) {
4275 : int16_t actual_raw_marked = CompareAndSwapRawNumberOfMarkedDescriptors(
4276 23559540 : old_raw_marked, new_raw_marked);
4277 23602478 : if (actual_raw_marked == old_raw_marked) {
4278 : break;
4279 : }
4280 : old_raw_marked = actual_raw_marked;
4281 : old_marked =
4282 : NumberOfMarkedDescriptors::decode(mark_compact_epoch, old_raw_marked);
4283 : }
4284 37642369 : return old_marked;
4285 : }
4286 :
4287 15545 : Handle<AccessorPair> AccessorPair::Copy(Isolate* isolate,
4288 : Handle<AccessorPair> pair) {
4289 15545 : Handle<AccessorPair> copy = isolate->factory()->NewAccessorPair();
4290 15545 : copy->set_getter(pair->getter());
4291 15545 : copy->set_setter(pair->setter());
4292 15545 : return copy;
4293 : }
4294 :
4295 90105 : Handle<Object> AccessorPair::GetComponent(Isolate* isolate,
4296 : Handle<AccessorPair> accessor_pair,
4297 : AccessorComponent component) {
4298 180210 : Object accessor = accessor_pair->get(component);
4299 90105 : if (accessor->IsFunctionTemplateInfo()) {
4300 : return ApiNatives::InstantiateFunction(
4301 178 : handle(FunctionTemplateInfo::cast(accessor), isolate))
4302 178 : .ToHandleChecked();
4303 : }
4304 90016 : if (accessor->IsNull(isolate)) {
4305 4375 : return isolate->factory()->undefined_value();
4306 : }
4307 : return handle(accessor, isolate);
4308 : }
4309 :
4310 : #ifdef DEBUG
4311 : bool DescriptorArray::IsEqualTo(DescriptorArray other) {
4312 : if (number_of_all_descriptors() != other->number_of_all_descriptors()) {
4313 : return false;
4314 : }
4315 : for (int i = 0; i < number_of_all_descriptors(); ++i) {
4316 : if (get(i) != other->get(i)) return false;
4317 : }
4318 : return true;
4319 : }
4320 : #endif
4321 :
4322 : // static
4323 471161 : MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
4324 942322 : if (name->IsString()) return Handle<String>::cast(name);
4325 : // ES6 section 9.2.11 SetFunctionName, step 4.
4326 11524 : Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
4327 11524 : if (description->IsUndefined(isolate)) {
4328 81 : return isolate->factory()->empty_string();
4329 : }
4330 5681 : IncrementalStringBuilder builder(isolate);
4331 : builder.AppendCharacter('[');
4332 5681 : builder.AppendString(Handle<String>::cast(description));
4333 : builder.AppendCharacter(']');
4334 5681 : return builder.Finish();
4335 : }
4336 :
4337 : // static
4338 409792 : MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name,
4339 : Handle<String> prefix) {
4340 : Handle<String> name_string;
4341 819584 : ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string,
4342 : ToFunctionName(isolate, name), String);
4343 409792 : IncrementalStringBuilder builder(isolate);
4344 409792 : builder.AppendString(prefix);
4345 : builder.AppendCharacter(' ');
4346 409792 : builder.AppendString(name_string);
4347 409792 : return builder.Finish();
4348 : }
4349 :
4350 :
4351 98000 : void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
4352 : Relocatable* current = isolate->relocatable_top();
4353 226340 : while (current != nullptr) {
4354 30340 : current->PostGarbageCollection();
4355 30340 : current = current->prev_;
4356 : }
4357 98000 : }
4358 :
4359 :
4360 : // Reserve space for statics needing saving and restoring.
4361 1144 : int Relocatable::ArchiveSpacePerThread() {
4362 1144 : return sizeof(Relocatable*); // NOLINT
4363 : }
4364 :
4365 :
4366 : // Archive statics that are thread-local.
4367 23397 : char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
4368 23397 : *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
4369 : isolate->set_relocatable_top(nullptr);
4370 23397 : return to + ArchiveSpacePerThread();
4371 : }
4372 :
4373 :
4374 : // Restore statics that are thread-local.
4375 23397 : char* Relocatable::RestoreState(Isolate* isolate, char* from) {
4376 23397 : isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
4377 23397 : return from + ArchiveSpacePerThread();
4378 : }
4379 :
4380 5180 : char* Relocatable::Iterate(RootVisitor* v, char* thread_storage) {
4381 5180 : Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
4382 : Iterate(v, top);
4383 5180 : return thread_storage + ArchiveSpacePerThread();
4384 : }
4385 :
4386 280837 : void Relocatable::Iterate(Isolate* isolate, RootVisitor* v) {
4387 : Iterate(v, isolate->relocatable_top());
4388 280837 : }
4389 :
4390 0 : void Relocatable::Iterate(RootVisitor* v, Relocatable* top) {
4391 : Relocatable* current = top;
4392 349414 : while (current != nullptr) {
4393 63397 : current->IterateInstance(v);
4394 63397 : current = current->prev_;
4395 : }
4396 0 : }
4397 :
4398 :
4399 :
4400 :
4401 :
4402 : namespace {
4403 :
4404 : template <typename sinkchar>
4405 103603 : void WriteFixedArrayToFlat(FixedArray fixed_array, int length, String separator,
4406 : sinkchar* sink, int sink_length) {
4407 : DisallowHeapAllocation no_allocation;
4408 103603 : CHECK_GT(length, 0);
4409 103603 : CHECK_LE(length, fixed_array->length());
4410 : #ifdef DEBUG
4411 : sinkchar* sink_end = sink + sink_length;
4412 : #endif
4413 :
4414 : const int separator_length = separator->length();
4415 : const bool use_one_byte_separator_fast_path =
4416 : separator_length == 1 && sizeof(sinkchar) == 1 &&
4417 164157 : StringShape(separator).IsSequentialOneByte();
4418 : uint8_t separator_one_char;
4419 102353 : if (use_one_byte_separator_fast_path) {
4420 61804 : CHECK(StringShape(separator).IsSequentialOneByte());
4421 61804 : CHECK_EQ(separator->length(), 1);
4422 61804 : separator_one_char =
4423 : SeqOneByteString::cast(separator)->GetChars(no_allocation)[0];
4424 : }
4425 :
4426 103603 : uint32_t num_separators = 0;
4427 31272465 : for (int i = 0; i < length; i++) {
4428 31272465 : Object element = fixed_array->get(i);
4429 : const bool element_is_separator_sequence = element->IsSmi();
4430 :
4431 : // If element is a Smi, it represents the number of separators to write.
4432 31272465 : if (V8_UNLIKELY(element_is_separator_sequence)) {
4433 6593 : CHECK(element->ToUint32(&num_separators));
4434 : // Verify that Smis (number of separators) only occur when necessary:
4435 : // 1) at the beginning
4436 : // 2) at the end
4437 : // 3) when the number of separators > 1
4438 : // - It is assumed that consecutive Strings will have one separator,
4439 : // so there is no need for a Smi.
4440 : DCHECK(i == 0 || i == length - 1 || num_separators > 1);
4441 : }
4442 :
4443 : // Write separator(s) if necessary.
4444 31272465 : if (num_separators > 0 && separator_length > 0) {
4445 : // TODO(pwong): Consider doubling strategy employed by runtime-strings.cc
4446 : // WriteRepeatToFlat().
4447 : // Fast path for single character, single byte separators.
4448 30997274 : if (use_one_byte_separator_fast_path) {
4449 : DCHECK_LE(sink + num_separators, sink_end);
4450 29384840 : memset(sink, separator_one_char, num_separators);
4451 : DCHECK_EQ(separator_length, 1);
4452 29384840 : sink += num_separators;
4453 : } else {
4454 1614165 : for (uint32_t j = 0; j < num_separators; j++) {
4455 : DCHECK_LE(sink + separator_length, sink_end);
4456 1614165 : String::WriteToFlat(separator, sink, 0, separator_length);
4457 1614165 : sink += separator_length;
4458 : }
4459 : }
4460 : }
4461 :
4462 31272465 : if (V8_UNLIKELY(element_is_separator_sequence)) {
4463 6593 : num_separators = 0;
4464 : } else {
4465 : DCHECK(element->IsString());
4466 : String string = String::cast(element);
4467 : const int string_length = string->length();
4468 :
4469 : DCHECK(string_length == 0 || sink < sink_end);
4470 31265872 : String::WriteToFlat(string, sink, 0, string_length);
4471 31265872 : sink += string_length;
4472 :
4473 : // Next string element, needs at least one separator preceding it.
4474 31265872 : num_separators = 1;
4475 : }
4476 : }
4477 :
4478 : // Verify we have written to the end of the sink.
4479 : DCHECK_EQ(sink, sink_end);
4480 103603 : }
4481 :
4482 : } // namespace
4483 :
4484 : // static
4485 103603 : Address JSArray::ArrayJoinConcatToSequentialString(Isolate* isolate,
4486 : Address raw_fixed_array,
4487 : intptr_t length,
4488 : Address raw_separator,
4489 : Address raw_dest) {
4490 : DisallowHeapAllocation no_allocation;
4491 103603 : DisallowJavascriptExecution no_js(isolate);
4492 103603 : FixedArray fixed_array = FixedArray::cast(Object(raw_fixed_array));
4493 103603 : String separator = String::cast(Object(raw_separator));
4494 : String dest = String::cast(Object(raw_dest));
4495 : DCHECK(fixed_array->IsFixedArray());
4496 : DCHECK(StringShape(dest).IsSequentialOneByte() ||
4497 : StringShape(dest).IsSequentialTwoByte());
4498 :
4499 103603 : if (StringShape(dest).IsSequentialOneByte()) {
4500 : WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
4501 : SeqOneByteString::cast(dest)->GetChars(no_allocation),
4502 102353 : dest->length());
4503 : } else {
4504 : DCHECK(StringShape(dest).IsSequentialTwoByte());
4505 : WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
4506 : SeqTwoByteString::cast(dest)->GetChars(no_allocation),
4507 1250 : dest->length());
4508 : }
4509 103603 : return dest->ptr();
4510 : }
4511 :
4512 :
4513 :
4514 :
4515 6130415 : uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
4516 : // For array indexes mix the length into the hash as an array index could
4517 : // be zero.
4518 : DCHECK_GT(length, 0);
4519 : DCHECK_LE(length, String::kMaxArrayIndexSize);
4520 : DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
4521 : (1 << String::kArrayIndexValueBits));
4522 :
4523 6922548 : value <<= String::ArrayIndexValueBits::kShift;
4524 6922548 : value |= length << String::ArrayIndexLengthBits::kShift;
4525 :
4526 : DCHECK_EQ(value & String::kIsNotArrayIndexMask, 0);
4527 : DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
4528 : Name::ContainsCachedArrayIndex(value));
4529 6130415 : return value;
4530 : }
4531 :
4532 :
4533 82732022 : uint32_t StringHasher::GetHashField() {
4534 82732022 : if (length_ <= String::kMaxHashCalcLength) {
4535 82665753 : if (is_array_index_) {
4536 1578958 : return MakeArrayIndexHash(array_index_, length_);
4537 : }
4538 163752548 : return (GetHashCore(raw_running_hash_) << String::kHashShift) |
4539 81876274 : String::kIsNotArrayIndexMask;
4540 : } else {
4541 66269 : return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
4542 : }
4543 : }
4544 :
4545 12949742 : uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
4546 : int* utf16_length_out) {
4547 12949742 : int vector_length = chars.length();
4548 : // Handle some edge cases
4549 12949742 : if (vector_length <= 1) {
4550 : DCHECK(vector_length == 0 ||
4551 : static_cast<uint8_t>(chars.start()[0]) <=
4552 : unibrow::Utf8::kMaxOneByteChar);
4553 2445 : *utf16_length_out = vector_length;
4554 2445 : return HashSequentialString(chars.start(), vector_length, seed);
4555 : }
4556 :
4557 : // Start with a fake length which won't affect computation.
4558 : // It will be updated later.
4559 : StringHasher hasher(String::kMaxArrayIndexSize, seed);
4560 : DCHECK(hasher.is_array_index_);
4561 :
4562 : unibrow::Utf8Iterator it = unibrow::Utf8Iterator(chars);
4563 : int utf16_length = 0;
4564 : bool is_index = true;
4565 :
4566 112508610 : while (utf16_length < String::kMaxHashCalcLength && !it.Done()) {
4567 86614016 : utf16_length++;
4568 86614016 : uint16_t c = *it;
4569 86614017 : ++it;
4570 : hasher.AddCharacter(c);
4571 86614016 : if (is_index) is_index = hasher.UpdateIndex(c);
4572 : }
4573 :
4574 : // Now that hashing is done, we just need to calculate utf16_length
4575 12947298 : while (!it.Done()) {
4576 0 : ++it;
4577 0 : utf16_length++;
4578 : }
4579 :
4580 12947298 : *utf16_length_out = utf16_length;
4581 : // Must set length here so that hash computation is correct.
4582 12947298 : hasher.length_ = utf16_length;
4583 12947298 : return hasher.GetHashField();
4584 : }
4585 :
4586 123681 : void IteratingStringHasher::VisitConsString(ConsString cons_string) {
4587 : // Run small ConsStrings through ConsStringIterator.
4588 123681 : if (cons_string->length() < 64) {
4589 78881 : ConsStringIterator iter(cons_string);
4590 : int offset;
4591 284651 : for (String string = iter.Next(&offset); !string.is_null();
4592 : string = iter.Next(&offset)) {
4593 : DCHECK_EQ(0, offset);
4594 126889 : String::VisitFlat(this, string, 0);
4595 : }
4596 123681 : return;
4597 : }
4598 : // Slow case.
4599 44800 : const int max_length = String::kMaxHashCalcLength;
4600 89600 : int length = std::min(cons_string->length(), max_length);
4601 44800 : if (cons_string->HasOnlyOneByteChars()) {
4602 44800 : uint8_t* buffer = new uint8_t[length];
4603 44800 : String::WriteToFlat(cons_string, buffer, 0, length);
4604 44800 : AddCharacters(buffer, length);
4605 44800 : delete[] buffer;
4606 : } else {
4607 0 : uint16_t* buffer = new uint16_t[length];
4608 0 : String::WriteToFlat(cons_string, buffer, 0, length);
4609 0 : AddCharacters(buffer, length);
4610 0 : delete[] buffer;
4611 : }
4612 : }
4613 :
4614 222 : Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
4615 : Handle<Map> initial_map) {
4616 : // Replace all of the cached initial array maps in the native context with
4617 : // the appropriate transitioned elements kind maps.
4618 222 : Handle<Map> current_map = initial_map;
4619 : ElementsKind kind = current_map->elements_kind();
4620 : DCHECK_EQ(GetInitialFastElementsKind(), kind);
4621 444 : native_context->set(Context::ArrayMapIndex(kind), *current_map);
4622 1332 : for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
4623 : i < kFastElementsKindCount; ++i) {
4624 : Handle<Map> new_map;
4625 1110 : ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
4626 1110 : Map maybe_elements_transition = current_map->ElementsTransitionMap();
4627 1110 : if (!maybe_elements_transition.is_null()) {
4628 : new_map = handle(maybe_elements_transition, native_context->GetIsolate());
4629 : } else {
4630 : new_map =
4631 : Map::CopyAsElementsKind(native_context->GetIsolate(), current_map,
4632 2220 : next_kind, INSERT_TRANSITION);
4633 : }
4634 : DCHECK_EQ(next_kind, new_map->elements_kind());
4635 2220 : native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
4636 : current_map = new_map;
4637 : }
4638 222 : return initial_map;
4639 : }
4640 :
4641 : STATIC_ASSERT(Oddball::kToNumberRawOffset == HeapNumber::kValueOffset);
4642 :
4643 672 : void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
4644 : const char* to_string, Handle<Object> to_number,
4645 : const char* type_of, byte kind) {
4646 : Handle<String> internalized_to_string =
4647 672 : isolate->factory()->InternalizeUtf8String(to_string);
4648 : Handle<String> internalized_type_of =
4649 672 : isolate->factory()->InternalizeUtf8String(type_of);
4650 1344 : if (to_number->IsHeapNumber()) {
4651 : oddball->set_to_number_raw_as_bits(
4652 224 : Handle<HeapNumber>::cast(to_number)->value_as_bits());
4653 : } else {
4654 1120 : oddball->set_to_number_raw(to_number->Number());
4655 : }
4656 672 : oddball->set_to_number(*to_number);
4657 672 : oddball->set_to_string(*internalized_to_string);
4658 672 : oddball->set_type_of(*internalized_type_of);
4659 : oddball->set_kind(kind);
4660 672 : }
4661 :
4662 2086 : int Script::GetEvalPosition() {
4663 : DisallowHeapAllocation no_gc;
4664 : DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
4665 : int position = eval_from_position();
4666 2086 : if (position < 0) {
4667 : // Due to laziness, the position may not have been translated from code
4668 : // offset yet, which would be encoded as negative integer. In that case,
4669 : // translate and set the position.
4670 775 : if (!has_eval_from_shared()) {
4671 : position = 0;
4672 : } else {
4673 775 : SharedFunctionInfo shared = eval_from_shared();
4674 775 : position = shared->abstract_code()->SourcePosition(-position);
4675 : }
4676 : DCHECK_GE(position, 0);
4677 : set_eval_from_position(position);
4678 : }
4679 2086 : return position;
4680 : }
4681 :
4682 2583472 : void Script::InitLineEnds(Handle<Script> script) {
4683 : Isolate* isolate = script->GetIsolate();
4684 7699412 : if (!script->line_ends()->IsUndefined(isolate)) return;
4685 : DCHECK(script->type() != Script::TYPE_WASM ||
4686 : script->source_mapping_url()->IsString());
4687 :
4688 51004 : Object src_obj = script->source();
4689 51004 : if (!src_obj->IsString()) {
4690 : DCHECK(src_obj->IsUndefined(isolate));
4691 10 : script->set_line_ends(ReadOnlyRoots(isolate).empty_fixed_array());
4692 : } else {
4693 : DCHECK(src_obj->IsString());
4694 : Handle<String> src(String::cast(src_obj), isolate);
4695 50999 : Handle<FixedArray> array = String::CalculateLineEnds(isolate, src, true);
4696 101998 : script->set_line_ends(*array);
4697 : }
4698 :
4699 : DCHECK(script->line_ends()->IsFixedArray());
4700 : }
4701 :
4702 2358129 : bool Script::GetPositionInfo(Handle<Script> script, int position,
4703 : PositionInfo* info, OffsetFlag offset_flag) {
4704 : // For wasm, we do not create an artificial line_ends array, but do the
4705 : // translation directly.
4706 2358129 : if (script->type() != Script::TYPE_WASM) InitLineEnds(script);
4707 2358129 : return script->GetPositionInfo(position, info, offset_flag);
4708 : }
4709 :
4710 20182677 : bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; }
4711 :
4712 382 : bool Script::ContainsAsmModule() {
4713 : DisallowHeapAllocation no_gc;
4714 382 : SharedFunctionInfo::ScriptIterator iter(this->GetIsolate(), *this);
4715 15330 : for (SharedFunctionInfo info = iter.Next(); !info.is_null();
4716 : info = iter.Next()) {
4717 7291 : if (info->HasAsmWasmData()) return true;
4718 : }
4719 374 : return false;
4720 : }
4721 :
4722 : namespace {
4723 269454 : bool GetPositionInfoSlow(const Script script, int position,
4724 : Script::PositionInfo* info) {
4725 538908 : if (!script->source()->IsString()) return false;
4726 269454 : if (position < 0) position = 0;
4727 :
4728 269454 : String source_string = String::cast(script->source());
4729 : int line = 0;
4730 : int line_start = 0;
4731 : int len = source_string->length();
4732 5647569901 : for (int pos = 0; pos <= len; ++pos) {
4733 11295138760 : if (pos == len || source_string->Get(pos) == '\n') {
4734 180482023 : if (position <= pos) {
4735 269444 : info->line = line;
4736 269444 : info->column = position - line_start;
4737 269444 : info->line_start = line_start;
4738 269444 : info->line_end = pos;
4739 269444 : return true;
4740 : }
4741 180212579 : line++;
4742 180212579 : line_start = pos + 1;
4743 : }
4744 : }
4745 : return false;
4746 : }
4747 : } // namespace
4748 :
4749 : #define SMI_VALUE(x) (Smi::ToInt(x))
4750 5339026 : bool Script::GetPositionInfo(int position, PositionInfo* info,
4751 : OffsetFlag offset_flag) const {
4752 : DisallowHeapAllocation no_allocation;
4753 :
4754 : // For wasm, we do not rely on the line_ends array, but do the translation
4755 : // directly.
4756 5339026 : if (type() == Script::TYPE_WASM) {
4757 : DCHECK_LE(0, position);
4758 : return WasmModuleObject::cast(wasm_module_object())
4759 1480 : ->GetPositionInfo(static_cast<uint32_t>(position), info);
4760 : }
4761 :
4762 10676572 : if (line_ends()->IsUndefined()) {
4763 : // Slow mode: we do not have line_ends. We have to iterate through source.
4764 269454 : if (!GetPositionInfoSlow(*this, position, info)) return false;
4765 : } else {
4766 : DCHECK(line_ends()->IsFixedArray());
4767 : FixedArray ends = FixedArray::cast(line_ends());
4768 :
4769 : const int ends_len = ends->length();
4770 5068832 : if (ends_len == 0) return false;
4771 :
4772 : // Return early on invalid positions. Negative positions behave as if 0 was
4773 : // passed, and positions beyond the end of the script return as failure.
4774 5068817 : if (position < 0) {
4775 : position = 0;
4776 10137604 : } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
4777 : return false;
4778 : }
4779 :
4780 : // Determine line number by doing a binary search on the line ends array.
4781 5063456 : if (SMI_VALUE(ends->get(0)) >= position) {
4782 260107 : info->line = 0;
4783 260107 : info->line_start = 0;
4784 260107 : info->column = position;
4785 : } else {
4786 : int left = 0;
4787 4803349 : int right = ends_len - 1;
4788 :
4789 49120555 : while (right > 0) {
4790 : DCHECK_LE(left, right);
4791 44317206 : const int mid = (left + right) / 2;
4792 44317206 : if (position > SMI_VALUE(ends->get(mid))) {
4793 20610255 : left = mid + 1;
4794 47413902 : } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
4795 : right = mid - 1;
4796 : } else {
4797 4803349 : info->line = mid;
4798 4803349 : break;
4799 : }
4800 : }
4801 : DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
4802 : SMI_VALUE(ends->get(info->line - 1)) < position);
4803 9606698 : info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
4804 4803349 : info->column = position - info->line_start;
4805 : }
4806 :
4807 : // Line end is position of the linebreak character.
4808 10126912 : info->line_end = SMI_VALUE(ends->get(info->line));
4809 5063456 : if (info->line_end > 0) {
4810 : DCHECK(source()->IsString());
4811 5062497 : String src = String::cast(source());
4812 10124994 : if (src->length() >= info->line_end &&
4813 5062497 : src->Get(info->line_end - 1) == '\r') {
4814 0 : info->line_end--;
4815 : }
4816 : }
4817 : }
4818 :
4819 : // Add offsets if requested.
4820 5332900 : if (offset_flag == WITH_OFFSET) {
4821 5199848 : if (info->line == 0) {
4822 440630 : info->column += column_offset();
4823 : }
4824 5199848 : info->line += line_offset();
4825 : }
4826 :
4827 : return true;
4828 : }
4829 : #undef SMI_VALUE
4830 :
4831 849856 : int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
4832 : PositionInfo info;
4833 849856 : GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
4834 849856 : return info.column;
4835 : }
4836 :
4837 134726 : int Script::GetColumnNumber(int code_pos) const {
4838 : PositionInfo info;
4839 134726 : GetPositionInfo(code_pos, &info, WITH_OFFSET);
4840 134726 : return info.column;
4841 : }
4842 :
4843 855005 : int Script::GetLineNumber(Handle<Script> script, int code_pos) {
4844 : PositionInfo info;
4845 855005 : GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
4846 855005 : return info.line;
4847 : }
4848 :
4849 2845824 : int Script::GetLineNumber(int code_pos) const {
4850 : PositionInfo info;
4851 2845824 : GetPositionInfo(code_pos, &info, WITH_OFFSET);
4852 2845824 : return info.line;
4853 : }
4854 :
4855 16843 : Object Script::GetNameOrSourceURL() {
4856 : // Keep in sync with ScriptNameOrSourceURL in messages.js.
4857 33686 : if (!source_url()->IsUndefined()) return source_url();
4858 : return name();
4859 : }
4860 :
4861 4086693 : MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
4862 8173386 : Isolate* isolate, const FunctionLiteral* fun) {
4863 4086693 : CHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
4864 : // If this check fails, the problem is most probably the function id
4865 : // renumbering done by AstFunctionLiteralIdReindexer; in particular, that
4866 : // AstTraversalVisitor doesn't recurse properly in the construct which
4867 : // triggers the mismatch.
4868 8173386 : CHECK_LT(fun->function_literal_id(), shared_function_infos()->length());
4869 4086693 : MaybeObject shared = shared_function_infos()->Get(fun->function_literal_id());
4870 4086694 : HeapObject heap_object;
4871 8171434 : if (!shared->GetHeapObject(&heap_object) ||
4872 : heap_object->IsUndefined(isolate)) {
4873 2577046 : return MaybeHandle<SharedFunctionInfo>();
4874 : }
4875 1509649 : return handle(SharedFunctionInfo::cast(heap_object), isolate);
4876 : }
4877 :
4878 135625 : Script::Iterator::Iterator(Isolate* isolate)
4879 271255 : : iterator_(isolate->heap()->script_list()) {}
4880 :
4881 5197448 : Script Script::Iterator::Next() {
4882 5197448 : Object o = iterator_.Next();
4883 5197448 : if (o != Object()) {
4884 : return Script::cast(o);
4885 : }
4886 4152 : return Script();
4887 : }
4888 :
4889 16177126 : Code SharedFunctionInfo::GetCode() const {
4890 : // ======
4891 : // NOTE: This chain of checks MUST be kept in sync with the equivalent CSA
4892 : // GetSharedFunctionInfoCode method in code-stub-assembler.cc.
4893 : // ======
4894 :
4895 : Isolate* isolate = GetIsolate();
4896 16177135 : Object data = function_data();
4897 16177128 : if (data->IsSmi()) {
4898 : // Holding a Smi means we are a builtin.
4899 : DCHECK(HasBuiltinId());
4900 2074463 : return isolate->builtins()->builtin(builtin_id());
4901 14102671 : } else if (data->IsBytecodeArray()) {
4902 : // Having a bytecode array means we are a compiled, interpreted function.
4903 : DCHECK(HasBytecodeArray());
4904 6942889 : return isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
4905 7159783 : } else if (data->IsAsmWasmData()) {
4906 : // Having AsmWasmData means we are an asm.js/wasm function.
4907 : DCHECK(HasAsmWasmData());
4908 4457 : return isolate->builtins()->builtin(Builtins::kInstantiateAsmJs);
4909 7155324 : } else if (data->IsUncompiledData()) {
4910 : // Having uncompiled data (with or without scope) means we need to compile.
4911 : DCHECK(HasUncompiledData());
4912 3254034 : return isolate->builtins()->builtin(Builtins::kCompileLazy);
4913 3901291 : } else if (data->IsFunctionTemplateInfo()) {
4914 : // Having a function template info means we are an API function.
4915 : DCHECK(IsApiFunction());
4916 3664112 : return isolate->builtins()->builtin(Builtins::kHandleApiCall);
4917 237179 : } else if (data->IsWasmExportedFunctionData()) {
4918 : // Having a WasmExportedFunctionData means the code is in there.
4919 : DCHECK(HasWasmExportedFunctionData());
4920 237139 : return wasm_exported_function_data()->wrapper_code();
4921 40 : } else if (data->IsInterpreterData()) {
4922 : Code code = InterpreterTrampoline();
4923 : DCHECK(code->IsCode());
4924 : DCHECK(code->is_interpreter_trampoline_builtin());
4925 40 : return code;
4926 : }
4927 0 : UNREACHABLE();
4928 : }
4929 :
4930 790187 : WasmExportedFunctionData SharedFunctionInfo::wasm_exported_function_data()
4931 : const {
4932 : DCHECK(HasWasmExportedFunctionData());
4933 790187 : return WasmExportedFunctionData::cast(function_data());
4934 : }
4935 :
4936 131295 : SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
4937 : Script script)
4938 : : ScriptIterator(isolate,
4939 262590 : handle(script->shared_function_infos(), isolate)) {}
4940 :
4941 0 : SharedFunctionInfo::ScriptIterator::ScriptIterator(
4942 : Isolate* isolate, Handle<WeakFixedArray> shared_function_infos)
4943 : : isolate_(isolate),
4944 : shared_function_infos_(shared_function_infos),
4945 243596 : index_(0) {}
4946 :
4947 2182505 : SharedFunctionInfo SharedFunctionInfo::ScriptIterator::Next() {
4948 8478425 : while (index_ < shared_function_infos_->length()) {
4949 6033454 : MaybeObject raw = shared_function_infos_->Get(index_++);
4950 3016727 : HeapObject heap_object;
4951 5667354 : if (!raw->GetHeapObject(&heap_object) ||
4952 2650627 : heap_object->IsUndefined(isolate_)) {
4953 965455 : continue;
4954 : }
4955 2051272 : return SharedFunctionInfo::cast(heap_object);
4956 : }
4957 131233 : return SharedFunctionInfo();
4958 : }
4959 :
4960 10 : void SharedFunctionInfo::ScriptIterator::Reset(Script script) {
4961 20 : shared_function_infos_ = handle(script->shared_function_infos(), isolate_);
4962 10 : index_ = 0;
4963 10 : }
4964 :
4965 5 : SharedFunctionInfo::GlobalIterator::GlobalIterator(Isolate* isolate)
4966 : : script_iterator_(isolate),
4967 : noscript_sfi_iterator_(isolate->heap()->noscript_shared_function_infos()),
4968 10 : sfi_iterator_(isolate, script_iterator_.Next()) {}
4969 :
4970 3356 : SharedFunctionInfo SharedFunctionInfo::GlobalIterator::Next() {
4971 3356 : HeapObject next = noscript_sfi_iterator_.Next();
4972 3356 : if (!next.is_null()) return SharedFunctionInfo::cast(next);
4973 : for (;;) {
4974 65 : next = sfi_iterator_.Next();
4975 120 : if (!next.is_null()) return SharedFunctionInfo::cast(next);
4976 15 : Script next_script = script_iterator_.Next();
4977 15 : if (next_script.is_null()) return SharedFunctionInfo();
4978 10 : sfi_iterator_.Reset(next_script);
4979 10 : }
4980 : }
4981 :
4982 3577009 : void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
4983 : Handle<Object> script_object,
4984 : int function_literal_id,
4985 : bool reset_preparsed_scope_data) {
4986 10731031 : if (shared->script() == *script_object) return;
4987 : Isolate* isolate = shared->GetIsolate();
4988 :
4989 10731024 : if (reset_preparsed_scope_data &&
4990 3577268 : shared->HasUncompiledDataWithPreparseData()) {
4991 0 : shared->ClearPreparseData();
4992 : }
4993 :
4994 : // Add shared function info to new script's list. If a collection occurs,
4995 : // the shared function info may be temporarily in two lists.
4996 : // This is okay because the gc-time processing of these lists can tolerate
4997 : // duplicates.
4998 7154017 : if (script_object->IsScript()) {
4999 : DCHECK(!shared->script()->IsScript());
5000 3577008 : Handle<Script> script = Handle<Script>::cast(script_object);
5001 : Handle<WeakFixedArray> list =
5002 7154016 : handle(script->shared_function_infos(), isolate);
5003 : #ifdef DEBUG
5004 : DCHECK_LT(function_literal_id, list->length());
5005 : MaybeObject maybe_object = list->Get(function_literal_id);
5006 : HeapObject heap_object;
5007 : if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
5008 : DCHECK_EQ(heap_object, *shared);
5009 : }
5010 : #endif
5011 7154016 : list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
5012 :
5013 : // Remove shared function info from root array.
5014 : WeakArrayList noscript_list =
5015 3577007 : isolate->heap()->noscript_shared_function_infos();
5016 3577008 : CHECK(noscript_list->RemoveOne(MaybeObjectHandle::Weak(shared)));
5017 : } else {
5018 : DCHECK(shared->script()->IsScript());
5019 : Handle<WeakArrayList> list =
5020 : isolate->factory()->noscript_shared_function_infos();
5021 :
5022 : #ifdef DEBUG
5023 : if (FLAG_enable_slow_asserts) {
5024 : WeakArrayList::Iterator iterator(*list);
5025 : for (HeapObject next = iterator.Next(); !next.is_null();
5026 : next = iterator.Next()) {
5027 : DCHECK_NE(next, *shared);
5028 : }
5029 : }
5030 : #endif // DEBUG
5031 :
5032 : list =
5033 0 : WeakArrayList::AddToEnd(isolate, list, MaybeObjectHandle::Weak(shared));
5034 :
5035 0 : isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
5036 :
5037 : // Remove shared function info from old script's list.
5038 0 : Script old_script = Script::cast(shared->script());
5039 :
5040 : // Due to liveedit, it might happen that the old_script doesn't know
5041 : // about the SharedFunctionInfo, so we have to guard against that.
5042 0 : Handle<WeakFixedArray> infos(old_script->shared_function_infos(), isolate);
5043 0 : if (function_literal_id < infos->length()) {
5044 : MaybeObject raw =
5045 0 : old_script->shared_function_infos()->Get(function_literal_id);
5046 0 : HeapObject heap_object;
5047 0 : if (raw->GetHeapObjectIfWeak(&heap_object) && heap_object == *shared) {
5048 : old_script->shared_function_infos()->Set(
5049 : function_literal_id, HeapObjectReference::Strong(
5050 0 : ReadOnlyRoots(isolate).undefined_value()));
5051 : }
5052 : }
5053 : }
5054 :
5055 : // Finally set new script.
5056 3577010 : shared->set_script(*script_object);
5057 : }
5058 :
5059 8384513 : bool SharedFunctionInfo::HasBreakInfo() const {
5060 8384513 : if (!HasDebugInfo()) return false;
5061 476663 : DebugInfo info = GetDebugInfo();
5062 476663 : bool has_break_info = info->HasBreakInfo();
5063 476663 : return has_break_info;
5064 : }
5065 :
5066 14477 : bool SharedFunctionInfo::BreakAtEntry() const {
5067 14477 : if (!HasDebugInfo()) return false;
5068 470 : DebugInfo info = GetDebugInfo();
5069 470 : bool break_at_entry = info->BreakAtEntry();
5070 470 : return break_at_entry;
5071 : }
5072 :
5073 205659 : bool SharedFunctionInfo::HasCoverageInfo() const {
5074 205659 : if (!HasDebugInfo()) return false;
5075 191920 : DebugInfo info = GetDebugInfo();
5076 191920 : bool has_coverage_info = info->HasCoverageInfo();
5077 191920 : return has_coverage_info;
5078 : }
5079 :
5080 179448 : CoverageInfo SharedFunctionInfo::GetCoverageInfo() const {
5081 : DCHECK(HasCoverageInfo());
5082 358896 : return CoverageInfo::cast(GetDebugInfo()->coverage_info());
5083 : }
5084 :
5085 7203350 : String SharedFunctionInfo::DebugName() {
5086 : DisallowHeapAllocation no_gc;
5087 7203350 : String function_name = Name();
5088 7203354 : if (function_name->length() > 0) return function_name;
5089 1949521 : return inferred_name();
5090 : }
5091 :
5092 928814 : bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
5093 928814 : Vector<const char> filter = CStrVector(raw_filter);
5094 928814 : std::unique_ptr<char[]> cstrname(DebugName()->ToCString());
5095 1857628 : return v8::internal::PassesFilter(CStrVector(cstrname.get()), filter);
5096 : }
5097 :
5098 6836571 : bool SharedFunctionInfo::HasSourceCode() const {
5099 : Isolate* isolate = GetIsolate();
5100 27346284 : return !script()->IsUndefined(isolate) &&
5101 27346284 : !Script::cast(script())->source()->IsUndefined(isolate);
5102 : }
5103 :
5104 109516 : void SharedFunctionInfo::DiscardCompiledMetadata(
5105 : Isolate* isolate,
5106 : std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)>
5107 : gc_notify_updated_slot) {
5108 : DisallowHeapAllocation no_gc;
5109 109516 : if (is_compiled()) {
5110 : HeapObject outer_scope_info;
5111 109509 : if (scope_info()->HasOuterScopeInfo()) {
5112 104064 : outer_scope_info = scope_info()->OuterScopeInfo();
5113 : } else {
5114 5445 : outer_scope_info = ReadOnlyRoots(isolate).the_hole_value();
5115 : }
5116 :
5117 : // Raw setter to avoid validity checks, since we're performing the unusual
5118 : // task of decompiling.
5119 109509 : set_raw_outer_scope_info_or_feedback_metadata(outer_scope_info);
5120 : gc_notify_updated_slot(
5121 : *this,
5122 : RawField(SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset),
5123 109509 : outer_scope_info);
5124 : } else {
5125 : DCHECK(outer_scope_info()->IsScopeInfo() ||
5126 : outer_scope_info()->IsTheHole());
5127 : }
5128 :
5129 : // TODO(rmcilroy): Possibly discard ScopeInfo here as well.
5130 109516 : }
5131 :
5132 : // static
5133 218 : void SharedFunctionInfo::DiscardCompiled(
5134 : Isolate* isolate, Handle<SharedFunctionInfo> shared_info) {
5135 : DCHECK(shared_info->CanDiscardCompiled());
5136 :
5137 : Handle<String> inferred_name_val =
5138 436 : handle(shared_info->inferred_name(), isolate);
5139 218 : int start_position = shared_info->StartPosition();
5140 218 : int end_position = shared_info->EndPosition();
5141 218 : int function_literal_id = shared_info->FunctionLiteralId(isolate);
5142 :
5143 436 : shared_info->DiscardCompiledMetadata(isolate);
5144 :
5145 : // Replace compiled data with a new UncompiledData object.
5146 218 : if (shared_info->HasUncompiledDataWithPreparseData()) {
5147 : // If this is uncompiled data with a pre-parsed scope data, we can just
5148 : // clear out the scope data and keep the uncompiled data.
5149 7 : shared_info->ClearPreparseData();
5150 : } else {
5151 : // Create a new UncompiledData, without pre-parsed scope, and update the
5152 : // function data to point to it. Use the raw function data setter to avoid
5153 : // validity checks, since we're performing the unusual task of decompiling.
5154 : Handle<UncompiledData> data =
5155 : isolate->factory()->NewUncompiledDataWithoutPreparseData(
5156 : inferred_name_val, start_position, end_position,
5157 211 : function_literal_id);
5158 422 : shared_info->set_function_data(*data);
5159 : }
5160 218 : }
5161 :
5162 : // static
5163 567 : Handle<Object> SharedFunctionInfo::GetSourceCode(
5164 : Handle<SharedFunctionInfo> shared) {
5165 : Isolate* isolate = shared->GetIsolate();
5166 567 : if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
5167 1134 : Handle<String> source(String::cast(Script::cast(shared->script())->source()),
5168 : isolate);
5169 : return isolate->factory()->NewSubString(source, shared->StartPosition(),
5170 1134 : shared->EndPosition());
5171 : }
5172 :
5173 : // static
5174 785231 : Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony(
5175 : Handle<SharedFunctionInfo> shared) {
5176 : Isolate* isolate = shared->GetIsolate();
5177 785231 : if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
5178 : Handle<String> script_source(
5179 1570462 : String::cast(Script::cast(shared->script())->source()), isolate);
5180 785231 : int start_pos = shared->function_token_position();
5181 : DCHECK_NE(start_pos, kNoSourcePosition);
5182 : Handle<String> source = isolate->factory()->NewSubString(
5183 785231 : script_source, start_pos, shared->EndPosition());
5184 785231 : if (!shared->is_wrapped()) return source;
5185 :
5186 : DCHECK(!shared->name_should_print_as_anonymous());
5187 15 : IncrementalStringBuilder builder(isolate);
5188 : builder.AppendCString("function ");
5189 30 : builder.AppendString(Handle<String>(shared->Name(), isolate));
5190 : builder.AppendCString("(");
5191 30 : Handle<FixedArray> args(Script::cast(shared->script())->wrapped_arguments(),
5192 30 : isolate);
5193 : int argc = args->length();
5194 20 : for (int i = 0; i < argc; i++) {
5195 5 : if (i > 0) builder.AppendCString(", ");
5196 5 : builder.AppendString(Handle<String>(String::cast(args->get(i)), isolate));
5197 : }
5198 : builder.AppendCString(") {\n");
5199 15 : builder.AppendString(source);
5200 : builder.AppendCString("\n}");
5201 30 : return builder.Finish().ToHandleChecked();
5202 : }
5203 :
5204 : namespace {
5205 121904 : void TraceInlining(SharedFunctionInfo shared, const char* msg) {
5206 121904 : if (FLAG_trace_turbo_inlining) {
5207 0 : StdoutStream os;
5208 0 : os << Brief(shared) << ": IsInlineable? " << msg << "\n";
5209 : }
5210 121904 : }
5211 : } // namespace
5212 :
5213 121903 : bool SharedFunctionInfo::IsInlineable() {
5214 243807 : if (!script()->IsScript()) {
5215 12732 : TraceInlining(*this, "false (no Script associated with it)");
5216 12732 : return false;
5217 : }
5218 :
5219 109179 : if (GetIsolate()->is_precise_binary_code_coverage() &&
5220 8 : !has_reported_binary_coverage()) {
5221 : // We may miss invocations if this function is inlined.
5222 0 : TraceInlining(*this, "false (requires precise binary coverage)");
5223 0 : return false;
5224 : }
5225 :
5226 109171 : if (optimization_disabled()) {
5227 930 : TraceInlining(*this, "false (optimization disabled)");
5228 930 : return false;
5229 : }
5230 :
5231 : // Built-in functions are handled by the JSCallReducer.
5232 108241 : if (HasBuiltinFunctionId()) {
5233 0 : TraceInlining(*this, "false (is a builtin)");
5234 0 : return false;
5235 : }
5236 :
5237 108241 : if (!IsUserJavaScript()) {
5238 325 : TraceInlining(*this, "false (is not user code)");
5239 325 : return false;
5240 : }
5241 :
5242 : // If there is no bytecode array, it is either not compiled or it is compiled
5243 : // with WebAssembly for the asm.js pipeline. In either case we don't want to
5244 : // inline.
5245 107917 : if (!HasBytecodeArray()) {
5246 1798 : TraceInlining(*this, "false (has no BytecodeArray)");
5247 1798 : return false;
5248 : }
5249 :
5250 212238 : if (GetBytecodeArray()->length() > FLAG_max_inlined_bytecode_size) {
5251 392 : TraceInlining(*this, "false (length > FLAG_max_inlined_bytecode_size)");
5252 392 : return false;
5253 : }
5254 :
5255 105727 : if (HasBreakInfo()) {
5256 2 : TraceInlining(*this, "false (may contain break points)");
5257 2 : return false;
5258 : }
5259 :
5260 105725 : TraceInlining(*this, "true");
5261 105725 : return true;
5262 : }
5263 :
5264 0 : int SharedFunctionInfo::SourceSize() { return EndPosition() - StartPosition(); }
5265 :
5266 112301 : int SharedFunctionInfo::FindIndexInScript(Isolate* isolate) const {
5267 : DisallowHeapAllocation no_gc;
5268 :
5269 112301 : Object script_obj = script();
5270 112301 : if (!script_obj->IsScript()) return FunctionLiteral::kIdTypeInvalid;
5271 :
5272 : WeakFixedArray shared_info_list =
5273 112301 : Script::cast(script_obj)->shared_function_infos();
5274 : SharedFunctionInfo::ScriptIterator iterator(
5275 : isolate,
5276 : Handle<WeakFixedArray>(reinterpret_cast<Address*>(&shared_info_list)));
5277 :
5278 837905 : for (SharedFunctionInfo shared = iterator.Next(); !shared.is_null();
5279 : shared = iterator.Next()) {
5280 837905 : if (shared == *this) {
5281 112301 : return iterator.CurrentIndex();
5282 : }
5283 : }
5284 :
5285 : return FunctionLiteral::kIdTypeInvalid;
5286 : }
5287 :
5288 :
5289 : // Output the source code without any allocation in the heap.
5290 24 : std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
5291 24 : const SharedFunctionInfo s = v.value;
5292 : // For some native functions there is no source.
5293 24 : if (!s->HasSourceCode()) return os << "<No Source>";
5294 :
5295 : // Get the source for the script which this function came from.
5296 : // Don't use String::cast because we don't want more assertion errors while
5297 : // we are already creating a stack dump.
5298 : String script_source =
5299 48 : String::unchecked_cast(Script::cast(s->script())->source());
5300 :
5301 24 : if (!script_source->LooksValid()) return os << "<Invalid Source>";
5302 :
5303 24 : if (!s->is_toplevel()) {
5304 16 : os << "function ";
5305 16 : String name = s->Name();
5306 16 : if (name->length() > 0) {
5307 16 : name->PrintUC16(os);
5308 : }
5309 : }
5310 :
5311 24 : int len = s->EndPosition() - s->StartPosition();
5312 24 : if (len <= v.max_length || v.max_length < 0) {
5313 8 : script_source->PrintUC16(os, s->StartPosition(), s->EndPosition());
5314 8 : return os;
5315 : } else {
5316 : script_source->PrintUC16(os, s->StartPosition(),
5317 16 : s->StartPosition() + v.max_length);
5318 16 : return os << "...\n";
5319 : }
5320 : }
5321 :
5322 :
5323 20330 : void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
5324 : DCHECK_NE(reason, BailoutReason::kNoReason);
5325 :
5326 : set_flags(DisabledOptimizationReasonBits::update(flags(), reason));
5327 : // Code should be the lazy compilation stub or else interpreted.
5328 : DCHECK(abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
5329 : abstract_code()->kind() == AbstractCode::BUILTIN);
5330 40660 : PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), *this));
5331 20330 : if (FLAG_trace_opt) {
5332 0 : PrintF("[disabled optimization for ");
5333 0 : ShortPrint();
5334 0 : PrintF(", reason: %s]\n", GetBailoutReason(reason));
5335 : }
5336 20330 : }
5337 :
5338 3576878 : void SharedFunctionInfo::InitFromFunctionLiteral(
5339 24038316 : Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit,
5340 : bool is_toplevel) {
5341 : Isolate* isolate = shared_info->GetIsolate();
5342 : bool needs_position_info = true;
5343 :
5344 : // When adding fields here, make sure DeclarationScope::AnalyzePartially is
5345 : // updated accordingly.
5346 : shared_info->set_internal_formal_parameter_count(lit->parameter_count());
5347 : shared_info->SetFunctionTokenPosition(lit->function_token_position(),
5348 10730640 : lit->start_position());
5349 3576880 : if (shared_info->scope_info()->HasPositionInfo()) {
5350 0 : shared_info->scope_info()->SetPositionInfo(lit->start_position(),
5351 0 : lit->end_position());
5352 : needs_position_info = false;
5353 : }
5354 7153757 : shared_info->set_is_declaration(lit->is_declaration());
5355 7153757 : shared_info->set_is_named_expression(lit->is_named_expression());
5356 7153756 : shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
5357 7153759 : shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
5358 7153759 : shared_info->set_language_mode(lit->language_mode());
5359 7153758 : shared_info->set_is_wrapped(lit->is_wrapped());
5360 : // shared_info->set_kind(lit->kind());
5361 : // FunctionKind must have already been set.
5362 : DCHECK(lit->kind() == shared_info->kind());
5363 7153759 : shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
5364 : DCHECK_IMPLIES(lit->requires_instance_members_initializer(),
5365 : IsClassConstructor(lit->kind()));
5366 : shared_info->set_requires_instance_members_initializer(
5367 7153759 : lit->requires_instance_members_initializer());
5368 :
5369 7153761 : shared_info->set_is_toplevel(is_toplevel);
5370 : DCHECK(shared_info->outer_scope_info()->IsTheHole());
5371 3576881 : if (!is_toplevel) {
5372 2577043 : Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
5373 2577041 : if (outer_scope) {
5374 4374778 : shared_info->set_outer_scope_info(*outer_scope->scope_info());
5375 : }
5376 : }
5377 :
5378 : // For lazy parsed functions, the following flags will be inaccurate since we
5379 : // don't have the information yet. They're set later in
5380 : // SetSharedFunctionFlagsFromLiteral (compiler.cc), when the function is
5381 : // really parsed and compiled.
5382 3576879 : if (lit->ShouldEagerCompile()) {
5383 : shared_info->set_length(lit->function_length());
5384 3016856 : shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
5385 3016858 : shared_info->SetExpectedNofPropertiesFromEstimate(lit);
5386 : DCHECK_NULL(lit->produced_preparse_data());
5387 : // If we're about to eager compile, we'll have the function literal
5388 : // available, so there's no need to wastefully allocate an uncompiled data.
5389 : // TODO(leszeks): This should be explicitly passed as a parameter, rather
5390 : // than relying on a property of the literal.
5391 : needs_position_info = false;
5392 : } else {
5393 : // Set an invalid length for lazy functions. This way we can set the correct
5394 : // value after compiling, but avoid overwriting values set manually by the
5395 : // bootstrapper.
5396 : shared_info->set_length(SharedFunctionInfo::kInvalidLength);
5397 : ProducedPreparseData* scope_data = lit->produced_preparse_data();
5398 2068450 : if (scope_data != nullptr) {
5399 : Handle<PreparseData> preparse_data =
5400 118374 : scope_data->Serialize(shared_info->GetIsolate());
5401 : Handle<UncompiledData> data =
5402 : isolate->factory()->NewUncompiledDataWithPreparseData(
5403 : lit->inferred_name(), lit->start_position(), lit->end_position(),
5404 59187 : lit->function_literal_id(), preparse_data);
5405 118374 : shared_info->set_uncompiled_data(*data);
5406 : needs_position_info = false;
5407 : }
5408 : }
5409 3576879 : if (needs_position_info) {
5410 : Handle<UncompiledData> data =
5411 : isolate->factory()->NewUncompiledDataWithoutPreparseData(
5412 : lit->inferred_name(), lit->start_position(), lit->end_position(),
5413 2009263 : lit->function_literal_id());
5414 4018528 : shared_info->set_uncompiled_data(*data);
5415 : }
5416 3576880 : }
5417 :
5418 2065958 : void SharedFunctionInfo::SetExpectedNofPropertiesFromEstimate(
5419 3574387 : FunctionLiteral* literal) {
5420 3574387 : int estimate = literal->expected_property_count();
5421 :
5422 : // If no properties are added in the constructor, they are more likely
5423 : // to be added later.
5424 3574387 : if (estimate == 0) estimate = 2;
5425 :
5426 : // Limit actual estimate to fit in a 8 bit field, we will never allocate
5427 : // more than this in any case.
5428 : STATIC_ASSERT(JSObject::kMaxInObjectProperties <= kMaxUInt8);
5429 3574387 : estimate = std::min(estimate, kMaxUInt8);
5430 :
5431 : set_expected_nof_properties(estimate);
5432 2065958 : }
5433 :
5434 1137 : void SharedFunctionInfo::SetFunctionTokenPosition(int function_token_position,
5435 : int start_position) {
5436 : int offset;
5437 3578017 : if (function_token_position == kNoSourcePosition) {
5438 : offset = 0;
5439 : } else {
5440 2552605 : offset = start_position - function_token_position;
5441 : }
5442 :
5443 3578017 : if (offset > kMaximumFunctionTokenOffset) {
5444 : offset = kFunctionTokenOutOfRange;
5445 : }
5446 : set_raw_function_token_offset(offset);
5447 1137 : }
5448 :
5449 10223387 : int SharedFunctionInfo::StartPosition() const {
5450 10223387 : Object maybe_scope_info = name_or_scope_info();
5451 10223391 : if (maybe_scope_info->IsScopeInfo()) {
5452 6357840 : ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
5453 6357840 : if (info->HasPositionInfo()) {
5454 6357840 : return info->StartPosition();
5455 : }
5456 3865551 : } else if (HasUncompiledData()) {
5457 : // Works with or without scope.
5458 5684844 : return uncompiled_data()->start_position();
5459 1023127 : } else if (IsApiFunction() || HasBuiltinId()) {
5460 : DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
5461 : return 0;
5462 : }
5463 : return kNoSourcePosition;
5464 : }
5465 :
5466 2379206 : int SharedFunctionInfo::EndPosition() const {
5467 2379206 : Object maybe_scope_info = name_or_scope_info();
5468 2379207 : if (maybe_scope_info->IsScopeInfo()) {
5469 578279 : ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
5470 578279 : if (info->HasPositionInfo()) {
5471 578279 : return info->EndPosition();
5472 : }
5473 1800928 : } else if (HasUncompiledData()) {
5474 : // Works with or without scope.
5475 3601856 : return uncompiled_data()->end_position();
5476 0 : } else if (IsApiFunction() || HasBuiltinId()) {
5477 : DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
5478 : return 0;
5479 : }
5480 : return kNoSourcePosition;
5481 : }
5482 :
5483 708633 : int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate) const {
5484 : // Fast path for the common case when the SFI is uncompiled and so the
5485 : // function literal id is already in the uncompiled data.
5486 1309088 : if (HasUncompiledData() && uncompiled_data()->has_function_literal_id()) {
5487 1192665 : int id = uncompiled_data()->function_literal_id();
5488 : // Make sure the id is what we should have found with the slow path.
5489 : DCHECK_EQ(id, FindIndexInScript(isolate));
5490 596333 : return id;
5491 : }
5492 :
5493 : // Otherwise, search for the function in the SFI's script's function list,
5494 : // and return its index in that list.
5495 112301 : return FindIndexInScript(isolate);
5496 : }
5497 :
5498 1137 : void SharedFunctionInfo::SetPosition(int start_position, int end_position) {
5499 1137 : Object maybe_scope_info = name_or_scope_info();
5500 1137 : if (maybe_scope_info->IsScopeInfo()) {
5501 1067 : ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
5502 1067 : if (info->HasPositionInfo()) {
5503 1067 : info->SetPositionInfo(start_position, end_position);
5504 : }
5505 70 : } else if (HasUncompiledData()) {
5506 70 : if (HasUncompiledDataWithPreparseData()) {
5507 : // Clear out preparsed scope data, since the position setter invalidates
5508 : // any scope data.
5509 14 : ClearPreparseData();
5510 : }
5511 140 : uncompiled_data()->set_start_position(start_position);
5512 140 : uncompiled_data()->set_end_position(end_position);
5513 : } else {
5514 0 : UNREACHABLE();
5515 : }
5516 1137 : }
5517 :
5518 : // static
5519 23545 : void SharedFunctionInfo::EnsureSourcePositionsAvailable(
5520 : Isolate* isolate, Handle<SharedFunctionInfo> shared_info) {
5521 47110 : if (FLAG_enable_lazy_source_positions && shared_info->HasBytecodeArray() &&
5522 23555 : !shared_info->GetBytecodeArray()->HasSourcePositionTable()) {
5523 5 : Compiler::CollectSourcePositions(isolate, shared_info);
5524 : }
5525 23545 : }
5526 :
5527 0 : bool BytecodeArray::IsBytecodeEqual(const BytecodeArray other) const {
5528 0 : if (length() != other->length()) return false;
5529 :
5530 0 : for (int i = 0; i < length(); ++i) {
5531 0 : if (get(i) != other->get(i)) return false;
5532 : }
5533 :
5534 : return true;
5535 : }
5536 :
5537 : // static
5538 142028 : void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
5539 : DCHECK_GE(capacity, 0);
5540 : array->GetIsolate()->factory()->NewJSArrayStorage(
5541 142031 : array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
5542 142037 : }
5543 :
5544 484666 : void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
5545 : // We should never end in here with a pixel or external array.
5546 : DCHECK(array->AllowsSetLength());
5547 484666 : if (array->SetLengthWouldNormalize(new_length)) {
5548 437 : JSObject::NormalizeElements(array);
5549 : }
5550 484666 : array->GetElementsAccessor()->SetLength(array, new_length);
5551 484666 : }
5552 :
5553 : // ES6: 9.5.2 [[SetPrototypeOf]] (V)
5554 : // static
5555 71920 : Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
5556 : bool from_javascript,
5557 : ShouldThrow should_throw) {
5558 : Isolate* isolate = proxy->GetIsolate();
5559 71920 : STACK_CHECK(isolate, Nothing<bool>());
5560 : Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
5561 : // 1. Assert: Either Type(V) is Object or Type(V) is Null.
5562 : DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
5563 : // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
5564 : Handle<Object> handler(proxy->handler(), isolate);
5565 : // 3. If handler is null, throw a TypeError exception.
5566 : // 4. Assert: Type(handler) is Object.
5567 143806 : if (proxy->IsRevoked()) {
5568 : isolate->Throw(*isolate->factory()->NewTypeError(
5569 18 : MessageTemplate::kProxyRevoked, trap_name));
5570 : return Nothing<bool>();
5571 : }
5572 : // 5. Let target be the value of the [[ProxyTarget]] internal slot.
5573 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
5574 : // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
5575 : Handle<Object> trap;
5576 143788 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5577 : isolate, trap,
5578 : Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
5579 : Nothing<bool>());
5580 : // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
5581 143788 : if (trap->IsUndefined(isolate)) {
5582 : return JSReceiver::SetPrototype(target, value, from_javascript,
5583 63172 : should_throw);
5584 : }
5585 : // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)).
5586 8722 : Handle<Object> argv[] = {target, value};
5587 : Handle<Object> trap_result;
5588 17444 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5589 : isolate, trap_result,
5590 : Execution::Call(isolate, trap, handler, arraysize(argv), argv),
5591 : Nothing<bool>());
5592 90 : bool bool_trap_result = trap_result->BooleanValue(isolate);
5593 : // 9. If booleanTrapResult is false, return false.
5594 90 : if (!bool_trap_result) {
5595 90 : RETURN_FAILURE(
5596 : isolate, should_throw,
5597 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
5598 : }
5599 : // 10. Let extensibleTarget be ? IsExtensible(target).
5600 54 : Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
5601 54 : if (is_extensible.IsNothing()) return Nothing<bool>();
5602 : // 11. If extensibleTarget is true, return true.
5603 54 : if (is_extensible.FromJust()) {
5604 27 : if (bool_trap_result) return Just(true);
5605 0 : RETURN_FAILURE(
5606 : isolate, should_throw,
5607 : NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
5608 : }
5609 : // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
5610 : Handle<Object> target_proto;
5611 54 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
5612 : JSReceiver::GetPrototype(isolate, target),
5613 : Nothing<bool>());
5614 : // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
5615 36 : if (bool_trap_result && !value->SameValue(*target_proto)) {
5616 : isolate->Throw(*isolate->factory()->NewTypeError(
5617 18 : MessageTemplate::kProxySetPrototypeOfNonExtensible));
5618 : return Nothing<bool>();
5619 : }
5620 : // 14. Return true.
5621 : return Just(true);
5622 : }
5623 :
5624 :
5625 :
5626 :
5627 :
5628 484666 : bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
5629 969332 : if (!HasFastElements()) return false;
5630 954008 : uint32_t capacity = static_cast<uint32_t>(elements()->length());
5631 : uint32_t new_capacity;
5632 477441 : return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
5633 : ShouldConvertToSlowElements(*this, capacity, new_length - 1,
5634 477441 : &new_capacity);
5635 : }
5636 :
5637 :
5638 : const double AllocationSite::kPretenureRatio = 0.85;
5639 :
5640 :
5641 0 : void AllocationSite::ResetPretenureDecision() {
5642 : set_pretenure_decision(kUndecided);
5643 : set_memento_found_count(0);
5644 : set_memento_create_count(0);
5645 0 : }
5646 :
5647 24239 : PretenureFlag AllocationSite::GetPretenureMode() const {
5648 : PretenureDecision mode = pretenure_decision();
5649 : // Zombie objects "decide" to be untenured.
5650 24239 : return mode == kTenure ? TENURED : NOT_TENURED;
5651 : }
5652 :
5653 0 : bool AllocationSite::IsNested() {
5654 : DCHECK(FLAG_trace_track_allocation_sites);
5655 0 : Object current = boilerplate()->GetHeap()->allocation_sites_list();
5656 0 : while (current->IsAllocationSite()) {
5657 : AllocationSite current_site = AllocationSite::cast(current);
5658 0 : if (current_site->nested_site() == *this) {
5659 : return true;
5660 : }
5661 0 : current = current_site->weak_next();
5662 : }
5663 : return false;
5664 : }
5665 :
5666 :
5667 4872 : bool AllocationSite::ShouldTrack(ElementsKind from, ElementsKind to) {
5668 7616 : return IsSmiElementsKind(from) &&
5669 7616 : IsMoreGeneralElementsKindTransition(from, to);
5670 : }
5671 :
5672 0 : const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
5673 0 : switch (decision) {
5674 : case kUndecided: return "undecided";
5675 0 : case kDontTenure: return "don't tenure";
5676 0 : case kMaybeTenure: return "maybe tenure";
5677 0 : case kTenure: return "tenure";
5678 0 : case kZombie: return "zombie";
5679 0 : default: UNREACHABLE();
5680 : }
5681 : return nullptr;
5682 : }
5683 :
5684 :
5685 :
5686 12094193 : bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
5687 12094198 : Map map = array->map();
5688 : // Fast path: "length" is the first fast property of arrays. Since it's not
5689 : // configurable, it's guaranteed to be the first in the descriptor array.
5690 12094198 : if (!map->is_dictionary_map()) {
5691 : DCHECK(map->instance_descriptors()->GetKey(0) ==
5692 : array->GetReadOnlyRoots().length_string());
5693 24187127 : return map->instance_descriptors()->GetDetails(0).IsReadOnly();
5694 : }
5695 :
5696 : Isolate* isolate = array->GetIsolate();
5697 : LookupIterator it(array, isolate->factory()->length_string(), array,
5698 611 : LookupIterator::OWN_SKIP_INTERCEPTOR);
5699 611 : CHECK_EQ(LookupIterator::ACCESSOR, it.state());
5700 611 : return it.IsReadOnly();
5701 : }
5702 :
5703 :
5704 2838013 : bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
5705 : uint32_t index) {
5706 2838013 : uint32_t length = 0;
5707 5676026 : CHECK(array->length()->ToArrayLength(&length));
5708 2838013 : if (length <= index) return HasReadOnlyLength(array);
5709 : return false;
5710 : }
5711 :
5712 :
5713 :
5714 : // Certain compilers request function template instantiation when they
5715 : // see the definition of the other template functions in the
5716 : // class. This requires us to have the template functions put
5717 : // together, so even though this function belongs in objects-debug.cc,
5718 : // we keep it here instead to satisfy certain compilers.
5719 : #ifdef OBJECT_PRINT
5720 : template <typename Derived, typename Shape>
5721 : void Dictionary<Derived, Shape>::Print(std::ostream& os) {
5722 : DisallowHeapAllocation no_gc;
5723 : ReadOnlyRoots roots = this->GetReadOnlyRoots();
5724 : Derived dictionary = Derived::cast(*this);
5725 : int capacity = dictionary->Capacity();
5726 : for (int i = 0; i < capacity; i++) {
5727 : Object k = dictionary->KeyAt(i);
5728 : if (!dictionary->ToKey(roots, i, &k)) continue;
5729 : os << "\n ";
5730 : if (k->IsString()) {
5731 : String::cast(k)->StringPrint(os);
5732 : } else {
5733 : os << Brief(k);
5734 : }
5735 : os << ": " << Brief(dictionary->ValueAt(i)) << " ";
5736 : dictionary->DetailsAt(i).PrintAsSlowTo(os);
5737 : }
5738 : }
5739 : template <typename Derived, typename Shape>
5740 : void Dictionary<Derived, Shape>::Print() {
5741 : StdoutStream os;
5742 : Print(os);
5743 : os << std::endl;
5744 : }
5745 : #endif
5746 :
5747 :
5748 :
5749 5256 : int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
5750 : return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
5751 5256 : ElementsKindToShiftSize(kind));
5752 : }
5753 :
5754 457695 : bool FixedArrayBase::IsCowArray() const {
5755 915394 : return map() == GetReadOnlyRoots().fixed_cow_array_map();
5756 : }
5757 :
5758 :
5759 1834 : const char* Symbol::PrivateSymbolToName() const {
5760 1834 : ReadOnlyRoots roots = GetReadOnlyRoots();
5761 : #define SYMBOL_CHECK_AND_PRINT(_, name) \
5762 : if (*this == roots.name()) return #name;
5763 27879 : PRIVATE_SYMBOL_LIST_GENERATOR(SYMBOL_CHECK_AND_PRINT, /* not used */)
5764 : #undef SYMBOL_CHECK_AND_PRINT
5765 150 : return "UNKNOWN";
5766 : }
5767 :
5768 :
5769 3901 : void Symbol::SymbolShortPrint(std::ostream& os) {
5770 3901 : os << "<Symbol:";
5771 7802 : if (!name()->IsUndefined()) {
5772 2067 : os << " ";
5773 : HeapStringAllocator allocator;
5774 : StringStream accumulator(&allocator);
5775 2067 : String::cast(name())->StringShortPrint(&accumulator, false);
5776 6201 : os << accumulator.ToCString().get();
5777 : } else {
5778 1834 : os << " (" << PrivateSymbolToName() << ")";
5779 : }
5780 3901 : os << ">";
5781 3901 : }
5782 :
5783 :
5784 : // StringSharedKeys are used as keys in the eval cache.
5785 3523725 : class StringSharedKey : public HashTableKey {
5786 : public:
5787 : // This tuple unambiguously identifies calls to eval() or
5788 : // CreateDynamicFunction() (such as through the Function() constructor).
5789 : // * source is the string passed into eval(). For dynamic functions, this is
5790 : // the effective source for the function, some of which is implicitly
5791 : // generated.
5792 : // * shared is the shared function info for the function containing the call
5793 : // to eval(). for dynamic functions, shared is the native context closure.
5794 : // * When positive, position is the position in the source where eval is
5795 : // called. When negative, position is the negation of the position in the
5796 : // dynamic function's effective source where the ')' ends the parameters.
5797 5114436 : StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
5798 : LanguageMode language_mode, int position)
5799 : : HashTableKey(CompilationCacheShape::StringSharedHash(
5800 : *source, *shared, language_mode, position)),
5801 : source_(source),
5802 : shared_(shared),
5803 : language_mode_(language_mode),
5804 10228872 : position_(position) {}
5805 :
5806 6239808 : bool IsMatch(Object other) override {
5807 : DisallowHeapAllocation no_allocation;
5808 6239808 : if (!other->IsFixedArray()) {
5809 : DCHECK(other->IsNumber());
5810 1944669 : uint32_t other_hash = static_cast<uint32_t>(other->Number());
5811 1944669 : return Hash() == other_hash;
5812 : }
5813 : FixedArray other_array = FixedArray::cast(other);
5814 : SharedFunctionInfo shared = SharedFunctionInfo::cast(other_array->get(0));
5815 4295139 : if (shared != *shared_) return false;
5816 4129467 : int language_unchecked = Smi::ToInt(other_array->get(2));
5817 : DCHECK(is_valid_language_mode(language_unchecked));
5818 4129467 : LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
5819 4129467 : if (language_mode != language_mode_) return false;
5820 4116341 : int position = Smi::ToInt(other_array->get(3));
5821 4116341 : if (position != position_) return false;
5822 4116175 : String source = String::cast(other_array->get(1));
5823 4116175 : return source->Equals(*source_);
5824 : }
5825 :
5826 1322384 : Handle<Object> AsHandle(Isolate* isolate) {
5827 1322384 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
5828 2644770 : array->set(0, *shared_);
5829 2644770 : array->set(1, *source_);
5830 1322385 : array->set(2, Smi::FromEnum(language_mode_));
5831 1322385 : array->set(3, Smi::FromInt(position_));
5832 1322385 : array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
5833 1322385 : return array;
5834 : }
5835 :
5836 : private:
5837 : Handle<String> source_;
5838 : Handle<SharedFunctionInfo> shared_;
5839 : LanguageMode language_mode_;
5840 : int position_;
5841 : };
5842 :
5843 174336 : v8::Promise::PromiseState JSPromise::status() const {
5844 214456 : int value = flags() & kStatusMask;
5845 : DCHECK(value == 0 || value == 1 || value == 2);
5846 214456 : return static_cast<v8::Promise::PromiseState>(value);
5847 : }
5848 :
5849 40120 : void JSPromise::set_status(Promise::PromiseState status) {
5850 40120 : int value = flags() & ~kStatusMask;
5851 40120 : set_flags(value | status);
5852 40120 : }
5853 :
5854 : // static
5855 40 : const char* JSPromise::Status(v8::Promise::PromiseState status) {
5856 40 : switch (status) {
5857 : case v8::Promise::kFulfilled:
5858 : return "resolved";
5859 : case v8::Promise::kPending:
5860 15 : return "pending";
5861 : case v8::Promise::kRejected:
5862 5 : return "rejected";
5863 : }
5864 0 : UNREACHABLE();
5865 : }
5866 :
5867 21898 : int JSPromise::async_task_id() const {
5868 43796 : return AsyncTaskIdField::decode(flags());
5869 : }
5870 :
5871 6608 : void JSPromise::set_async_task_id(int id) {
5872 13216 : set_flags(AsyncTaskIdField::update(flags(), id));
5873 6608 : }
5874 :
5875 : // static
5876 29166 : Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
5877 : Handle<Object> value) {
5878 : Isolate* const isolate = promise->GetIsolate();
5879 :
5880 : // 1. Assert: The value of promise.[[PromiseState]] is "pending".
5881 29166 : CHECK_EQ(Promise::kPending, promise->status());
5882 :
5883 : // 2. Let reactions be promise.[[PromiseFulfillReactions]].
5884 : Handle<Object> reactions(promise->reactions(), isolate);
5885 :
5886 : // 3. Set promise.[[PromiseResult]] to value.
5887 : // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
5888 : // 5. Set promise.[[PromiseRejectReactions]] to undefined.
5889 29166 : promise->set_reactions_or_result(*value);
5890 :
5891 : // 6. Set promise.[[PromiseState]] to "fulfilled".
5892 29166 : promise->set_status(Promise::kFulfilled);
5893 :
5894 : // 7. Return TriggerPromiseReactions(reactions, value).
5895 : return TriggerPromiseReactions(isolate, reactions, value,
5896 29166 : PromiseReaction::kFulfill);
5897 : }
5898 :
5899 : // static
5900 10954 : Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
5901 : Handle<Object> reason, bool debug_event) {
5902 7547 : Isolate* const isolate = promise->GetIsolate();
5903 :
5904 18501 : if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
5905 : isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
5906 10954 : isolate->factory()->undefined_value());
5907 :
5908 : // 1. Assert: The value of promise.[[PromiseState]] is "pending".
5909 10954 : CHECK_EQ(Promise::kPending, promise->status());
5910 :
5911 : // 2. Let reactions be promise.[[PromiseRejectReactions]].
5912 : Handle<Object> reactions(promise->reactions(), isolate);
5913 :
5914 : // 3. Set promise.[[PromiseResult]] to reason.
5915 : // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
5916 : // 5. Set promise.[[PromiseRejectReactions]] to undefined.
5917 10954 : promise->set_reactions_or_result(*reason);
5918 :
5919 : // 6. Set promise.[[PromiseState]] to "rejected".
5920 10954 : promise->set_status(Promise::kRejected);
5921 :
5922 : // 7. If promise.[[PromiseIsHandled]] is false, perform
5923 : // HostPromiseRejectionTracker(promise, "reject").
5924 10954 : if (!promise->has_handler()) {
5925 8438 : isolate->ReportPromiseReject(promise, reason, kPromiseRejectWithNoHandler);
5926 : }
5927 :
5928 : // 8. Return TriggerPromiseReactions(reactions, reason).
5929 : return TriggerPromiseReactions(isolate, reactions, reason,
5930 10954 : PromiseReaction::kReject);
5931 : }
5932 :
5933 : // static
5934 30825 : MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
5935 : Handle<Object> resolution) {
5936 1545 : Isolate* const isolate = promise->GetIsolate();
5937 :
5938 : isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
5939 30825 : isolate->factory()->undefined_value());
5940 :
5941 : // 6. If SameValue(resolution, promise) is true, then
5942 30825 : if (promise.is_identical_to(resolution)) {
5943 : // a. Let selfResolutionError be a newly created TypeError object.
5944 : Handle<Object> self_resolution_error = isolate->factory()->NewTypeError(
5945 50 : MessageTemplate::kPromiseCyclic, resolution);
5946 : // b. Return RejectPromise(promise, selfResolutionError).
5947 50 : return Reject(promise, self_resolution_error);
5948 : }
5949 :
5950 : // 7. If Type(resolution) is not Object, then
5951 61550 : if (!resolution->IsJSReceiver()) {
5952 : // a. Return FulfillPromise(promise, resolution).
5953 27206 : return Fulfill(promise, resolution);
5954 : }
5955 :
5956 : // 8. Let then be Get(resolution, "then").
5957 : MaybeHandle<Object> then;
5958 3569 : if (isolate->IsPromiseThenLookupChainIntact(
5959 3569 : Handle<JSReceiver>::cast(resolution))) {
5960 : // We can skip the "then" lookup on {resolution} if its [[Prototype]]
5961 : // is the (initial) Promise.prototype and the Promise#then protector
5962 : // is intact, as that guards the lookup path for the "then" property
5963 : // on JSPromise instances which have the (initial) %PromisePrototype%.
5964 1540 : then = isolate->promise_then();
5965 : } else {
5966 : then =
5967 : JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(resolution),
5968 2029 : isolate->factory()->then_string());
5969 : }
5970 :
5971 : // 9. If then is an abrupt completion, then
5972 : Handle<Object> then_action;
5973 3569 : if (!then.ToHandle(&then_action)) {
5974 : // a. Return RejectPromise(promise, then.[[Value]]).
5975 : Handle<Object> reason(isolate->pending_exception(), isolate);
5976 64 : isolate->clear_pending_exception();
5977 64 : return Reject(promise, reason, false);
5978 : }
5979 :
5980 : // 10. Let thenAction be then.[[Value]].
5981 : // 11. If IsCallable(thenAction) is false, then
5982 7010 : if (!then_action->IsCallable()) {
5983 : // a. Return FulfillPromise(promise, resolution).
5984 1960 : return Fulfill(promise, resolution);
5985 : }
5986 :
5987 : // 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
5988 : // «promise, resolution, thenAction»).
5989 : Handle<PromiseResolveThenableJobTask> task =
5990 : isolate->factory()->NewPromiseResolveThenableJobTask(
5991 : promise, Handle<JSReceiver>::cast(then_action),
5992 3090 : Handle<JSReceiver>::cast(resolution), isolate->native_context());
5993 4275 : if (isolate->debug()->is_active() && resolution->IsJSPromise()) {
5994 : // Mark the dependency of the new {promise} on the {resolution}.
5995 : Object::SetProperty(isolate, resolution,
5996 : isolate->factory()->promise_handled_by_symbol(),
5997 1365 : promise)
5998 2730 : .Check();
5999 : }
6000 3090 : isolate->native_context()->microtask_queue()->EnqueueMicrotask(*task);
6001 :
6002 : // 13. Return undefined.
6003 1545 : return isolate->factory()->undefined_value();
6004 : }
6005 :
6006 : // static
6007 40120 : Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
6008 : Handle<Object> reactions,
6009 : Handle<Object> argument,
6010 : PromiseReaction::Type type) {
6011 96838 : CHECK(reactions->IsSmi() || reactions->IsPromiseReaction());
6012 :
6013 : // We need to reverse the {reactions} here, since we record them
6014 : // on the JSPromise in the reverse order.
6015 : {
6016 : DisallowHeapAllocation no_gc;
6017 40120 : Object current = *reactions;
6018 : Object reversed = Smi::kZero;
6019 89063 : while (!current->IsSmi()) {
6020 : Object next = PromiseReaction::cast(current)->next();
6021 8823 : PromiseReaction::cast(current)->set_next(reversed);
6022 8823 : reversed = current;
6023 8823 : current = next;
6024 : }
6025 : reactions = handle(reversed, isolate);
6026 : }
6027 :
6028 : // Morph the {reactions} into PromiseReactionJobTasks
6029 : // and push them onto the microtask queue.
6030 138006 : while (!reactions->IsSmi()) {
6031 8823 : Handle<HeapObject> task = Handle<HeapObject>::cast(reactions);
6032 8823 : Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(task);
6033 : reactions = handle(reaction->next(), isolate);
6034 :
6035 : STATIC_ASSERT(static_cast<int>(PromiseReaction::kSize) ==
6036 : static_cast<int>(PromiseReactionJobTask::kSize));
6037 8823 : if (type == PromiseReaction::kFulfill) {
6038 : task->synchronized_set_map(
6039 6287 : ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map());
6040 18861 : Handle<PromiseFulfillReactionJobTask>::cast(task)->set_argument(
6041 6287 : *argument);
6042 18861 : Handle<PromiseFulfillReactionJobTask>::cast(task)->set_context(
6043 25148 : *isolate->native_context());
6044 : STATIC_ASSERT(
6045 : static_cast<int>(PromiseReaction::kFulfillHandlerOffset) ==
6046 : static_cast<int>(PromiseFulfillReactionJobTask::kHandlerOffset));
6047 : STATIC_ASSERT(
6048 : static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
6049 : static_cast<int>(
6050 : PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset));
6051 : } else {
6052 : DisallowHeapAllocation no_gc;
6053 2536 : HeapObject handler = reaction->reject_handler();
6054 : task->synchronized_set_map(
6055 2536 : ReadOnlyRoots(isolate).promise_reject_reaction_job_task_map());
6056 5072 : Handle<PromiseRejectReactionJobTask>::cast(task)->set_argument(*argument);
6057 7608 : Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
6058 10144 : *isolate->native_context());
6059 5072 : Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(handler);
6060 : STATIC_ASSERT(
6061 : static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
6062 : static_cast<int>(
6063 : PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset));
6064 : }
6065 :
6066 17646 : isolate->native_context()->microtask_queue()->EnqueueMicrotask(
6067 35292 : *Handle<PromiseReactionJobTask>::cast(task));
6068 : }
6069 :
6070 40120 : return isolate->factory()->undefined_value();
6071 : }
6072 :
6073 : namespace {
6074 :
6075 : constexpr JSRegExp::Flag kCharFlagValues[] = {
6076 : JSRegExp::kGlobal, // g
6077 : JSRegExp::kInvalid, // h
6078 : JSRegExp::kIgnoreCase, // i
6079 : JSRegExp::kInvalid, // j
6080 : JSRegExp::kInvalid, // k
6081 : JSRegExp::kInvalid, // l
6082 : JSRegExp::kMultiline, // m
6083 : JSRegExp::kInvalid, // n
6084 : JSRegExp::kInvalid, // o
6085 : JSRegExp::kInvalid, // p
6086 : JSRegExp::kInvalid, // q
6087 : JSRegExp::kInvalid, // r
6088 : JSRegExp::kDotAll, // s
6089 : JSRegExp::kInvalid, // t
6090 : JSRegExp::kUnicode, // u
6091 : JSRegExp::kInvalid, // v
6092 : JSRegExp::kInvalid, // w
6093 : JSRegExp::kInvalid, // x
6094 : JSRegExp::kSticky, // y
6095 : };
6096 :
6097 : constexpr JSRegExp::Flag CharToFlag(uc16 flag_char) {
6098 75710 : return (flag_char < 'g' || flag_char > 'y')
6099 : ? JSRegExp::kInvalid
6100 75710 : : kCharFlagValues[flag_char - 'g'];
6101 : }
6102 :
6103 378291 : JSRegExp::Flags RegExpFlagsFromString(Isolate* isolate, Handle<String> flags,
6104 : bool* success) {
6105 : STATIC_ASSERT(CharToFlag('g') == JSRegExp::kGlobal);
6106 : STATIC_ASSERT(CharToFlag('i') == JSRegExp::kIgnoreCase);
6107 : STATIC_ASSERT(CharToFlag('m') == JSRegExp::kMultiline);
6108 : STATIC_ASSERT(CharToFlag('s') == JSRegExp::kDotAll);
6109 : STATIC_ASSERT(CharToFlag('u') == JSRegExp::kUnicode);
6110 : STATIC_ASSERT(CharToFlag('y') == JSRegExp::kSticky);
6111 :
6112 : int length = flags->length();
6113 378291 : if (length == 0) {
6114 303788 : *success = true;
6115 303788 : return JSRegExp::kNone;
6116 : }
6117 : // A longer flags string cannot be valid.
6118 74503 : if (length > JSRegExp::FlagCount()) return JSRegExp::Flags(0);
6119 : // Initialize {value} to {kInvalid} to allow 2-in-1 duplicate/invalid check.
6120 : JSRegExp::Flags value = JSRegExp::kInvalid;
6121 149006 : if (flags->IsSeqOneByteString()) {
6122 : DisallowHeapAllocation no_gc;
6123 : SeqOneByteString seq_flags = SeqOneByteString::cast(*flags);
6124 150069 : for (int i = 0; i < length; i++) {
6125 : JSRegExp::Flag flag = CharToFlag(seq_flags.SeqOneByteStringGet(i));
6126 : // Duplicate or invalid flag.
6127 75710 : if (value & flag) return JSRegExp::Flags(0);
6128 : value |= flag;
6129 : }
6130 : } else {
6131 0 : flags = String::Flatten(isolate, flags);
6132 : DisallowHeapAllocation no_gc;
6133 0 : String::FlatContent flags_content = flags->GetFlatContent(no_gc);
6134 0 : for (int i = 0; i < length; i++) {
6135 0 : JSRegExp::Flag flag = CharToFlag(flags_content.Get(i));
6136 : // Duplicate or invalid flag.
6137 0 : if (value & flag) return JSRegExp::Flags(0);
6138 : value |= flag;
6139 : }
6140 : }
6141 74359 : *success = true;
6142 : // Drop the initially set {kInvalid} bit.
6143 : value ^= JSRegExp::kInvalid;
6144 74359 : return value;
6145 : }
6146 :
6147 : } // namespace
6148 :
6149 :
6150 : // static
6151 81666 : MaybeHandle<JSRegExp> JSRegExp::New(Isolate* isolate, Handle<String> pattern,
6152 : Flags flags) {
6153 81666 : Handle<JSFunction> constructor = isolate->regexp_function();
6154 : Handle<JSRegExp> regexp =
6155 81666 : Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
6156 :
6157 81666 : return JSRegExp::Initialize(regexp, pattern, flags);
6158 : }
6159 :
6160 :
6161 : // static
6162 18540 : Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
6163 : Isolate* const isolate = regexp->GetIsolate();
6164 18540 : return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
6165 : }
6166 :
6167 : namespace {
6168 :
6169 : template <typename Char>
6170 459813 : int CountRequiredEscapes(Handle<String> source) {
6171 : DisallowHeapAllocation no_gc;
6172 : int escapes = 0;
6173 919626 : Vector<const Char> src = source->GetCharVector<Char>(no_gc);
6174 19348013046 : for (int i = 0; i < src.length(); i++) {
6175 19347093420 : const Char c = src[i];
6176 9673546710 : if (c == '\\') {
6177 : // Escape. Skip next character;
6178 131011 : i++;
6179 9673415699 : } else if (c == '/') {
6180 : // Not escaped forward-slash needs escape.
6181 1397 : escapes++;
6182 9673414302 : } else if (c == '\n') {
6183 925 : escapes++;
6184 9673413377 : } else if (c == '\r') {
6185 36 : escapes++;
6186 445841 : } else if (static_cast<int>(c) == 0x2028) {
6187 20 : escapes += std::strlen("\\u2028") - 1;
6188 445821 : } else if (static_cast<int>(c) == 0x2029) {
6189 20 : escapes += std::strlen("\\u2029") - 1;
6190 : } else {
6191 : DCHECK(!unibrow::IsLineTerminator(static_cast<unibrow::uchar>(c)));
6192 : }
6193 : }
6194 459813 : return escapes;
6195 : }
6196 :
6197 : template <typename Char>
6198 : void WriteStringToCharVector(Vector<Char> v, int* d, const char* string) {
6199 : int s = 0;
6200 4324 : while (string[s] != '\0') v[(*d)++] = string[s++];
6201 : }
6202 :
6203 : template <typename Char, typename StringType>
6204 1527 : Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
6205 : Handle<StringType> result) {
6206 : DisallowHeapAllocation no_gc;
6207 3054 : Vector<const Char> src = source->GetCharVector<Char>(no_gc);
6208 : Vector<Char> dst(result->GetChars(no_gc), result->length());
6209 : int s = 0;
6210 : int d = 0;
6211 : // TODO(v8:1982): Fully implement
6212 : // https://tc39.github.io/ecma262/#sec-escaperegexppattern
6213 33759 : while (s < src.length()) {
6214 61410 : if (src[s] == '\\') {
6215 : // Escape. Copy this and next character.
6216 3606 : dst[d++] = src[s++];
6217 1803 : if (s == src.length()) break;
6218 28902 : } else if (src[s] == '/') {
6219 : // Not escaped forward-slash needs escape.
6220 2794 : dst[d++] = '\\';
6221 27505 : } else if (src[s] == '\n') {
6222 : WriteStringToCharVector(dst, &d, "\\n");
6223 925 : s++;
6224 925 : continue;
6225 26580 : } else if (src[s] == '\r') {
6226 : WriteStringToCharVector(dst, &d, "\\r");
6227 36 : s++;
6228 36 : continue;
6229 51 : } else if (static_cast<int>(src[s]) == 0x2028) {
6230 : WriteStringToCharVector(dst, &d, "\\u2028");
6231 20 : s++;
6232 20 : continue;
6233 31 : } else if (static_cast<int>(src[s]) == 0x2029) {
6234 : WriteStringToCharVector(dst, &d, "\\u2029");
6235 20 : s++;
6236 20 : continue;
6237 : }
6238 89112 : dst[d++] = src[s++];
6239 : }
6240 : DCHECK_EQ(result->length(), d);
6241 1527 : return result;
6242 : }
6243 :
6244 459813 : MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
6245 : Handle<String> source) {
6246 : DCHECK(source->IsFlat());
6247 459813 : if (source->length() == 0) return isolate->factory()->query_colon_string();
6248 459813 : bool one_byte = String::IsOneByteRepresentationUnderneath(*source);
6249 : int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
6250 459813 : : CountRequiredEscapes<uc16>(source);
6251 459813 : if (escapes == 0) return source;
6252 1527 : int length = source->length() + escapes;
6253 1527 : if (one_byte) {
6254 : Handle<SeqOneByteString> result;
6255 2976 : ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
6256 : isolate->factory()->NewRawOneByteString(length),
6257 : String);
6258 1488 : return WriteEscapedRegExpSource<uint8_t>(source, result);
6259 : } else {
6260 : Handle<SeqTwoByteString> result;
6261 78 : ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
6262 : isolate->factory()->NewRawTwoByteString(length),
6263 : String);
6264 39 : return WriteEscapedRegExpSource<uc16>(source, result);
6265 : }
6266 : }
6267 :
6268 : } // namespace
6269 :
6270 : // static
6271 378291 : MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
6272 : Handle<String> source,
6273 : Handle<String> flags_string) {
6274 : Isolate* isolate = regexp->GetIsolate();
6275 378291 : bool success = false;
6276 378291 : Flags flags = RegExpFlagsFromString(isolate, flags_string, &success);
6277 378291 : if (!success) {
6278 144 : THROW_NEW_ERROR(
6279 : isolate,
6280 : NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
6281 : JSRegExp);
6282 : }
6283 378147 : return Initialize(regexp, source, flags);
6284 : }
6285 :
6286 :
6287 : // static
6288 459813 : MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
6289 : Handle<String> source, Flags flags) {
6290 : Isolate* isolate = regexp->GetIsolate();
6291 : Factory* factory = isolate->factory();
6292 : // If source is the empty string we set it to "(?:)" instead as
6293 : // suggested by ECMA-262, 5th, section 15.10.4.1.
6294 459813 : if (source->length() == 0) source = factory->query_colon_string();
6295 :
6296 459813 : source = String::Flatten(isolate, source);
6297 :
6298 : Handle<String> escaped_source;
6299 919626 : ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
6300 : EscapeRegExpSource(isolate, source), JSRegExp);
6301 :
6302 919626 : RETURN_ON_EXCEPTION(
6303 : isolate, RegExpImpl::Compile(isolate, regexp, source, flags), JSRegExp);
6304 :
6305 914030 : regexp->set_source(*escaped_source);
6306 914030 : regexp->set_flags(Smi::FromInt(flags));
6307 :
6308 457015 : Map map = regexp->map();
6309 457015 : Object constructor = map->GetConstructor();
6310 1371045 : if (constructor->IsJSFunction() &&
6311 1371045 : JSFunction::cast(constructor)->initial_map() == map) {
6312 : // If we still have the original map, set in-object properties directly.
6313 913494 : regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
6314 456747 : SKIP_WRITE_BARRIER);
6315 : } else {
6316 : // Map has changed, so use generic, but slower, method.
6317 536 : RETURN_ON_EXCEPTION(
6318 : isolate,
6319 : Object::SetProperty(isolate, regexp, factory->lastIndex_string(),
6320 : Handle<Smi>(Smi::zero(), isolate)),
6321 : JSRegExp);
6322 : }
6323 :
6324 457015 : return regexp;
6325 : }
6326 :
6327 :
6328 : // RegExpKey carries the source and flags of a regular expression as key.
6329 0 : class RegExpKey : public HashTableKey {
6330 : public:
6331 984940 : RegExpKey(Handle<String> string, JSRegExp::Flags flags)
6332 : : HashTableKey(
6333 : CompilationCacheShape::RegExpHash(*string, Smi::FromInt(flags))),
6334 : string_(string),
6335 984940 : flags_(Smi::FromInt(flags)) {}
6336 :
6337 : // Rather than storing the key in the hash table, a pointer to the
6338 : // stored value is stored where the key should be. IsMatch then
6339 : // compares the search key to the found object, rather than comparing
6340 : // a key to a key.
6341 586550 : bool IsMatch(Object obj) override {
6342 : FixedArray val = FixedArray::cast(obj);
6343 1173100 : return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
6344 1367720 : && (flags_ == val->get(JSRegExp::kFlagsIndex));
6345 : }
6346 :
6347 : Handle<String> string_;
6348 : Smi flags_;
6349 : };
6350 :
6351 41571 : Handle<String> OneByteStringKey::AsHandle(Isolate* isolate) {
6352 41571 : return isolate->factory()->NewOneByteInternalizedString(string_, HashField());
6353 : }
6354 :
6355 50 : Handle<String> TwoByteStringKey::AsHandle(Isolate* isolate) {
6356 50 : return isolate->factory()->NewTwoByteInternalizedString(string_, HashField());
6357 : }
6358 :
6359 470711 : Handle<String> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
6360 : return isolate->factory()->NewOneByteInternalizedSubString(
6361 470711 : string_, from_, length_, HashField());
6362 : }
6363 :
6364 1800917 : bool SeqOneByteSubStringKey::IsMatch(Object string) {
6365 : DisallowHeapAllocation no_gc;
6366 3601834 : Vector<const uint8_t> chars(string_->GetChars(no_gc) + from_, length_);
6367 1800917 : return String::cast(string)->IsOneByteEqualTo(chars);
6368 : }
6369 :
6370 : // InternalizedStringKey carries a string/internalized-string object as key.
6371 0 : class InternalizedStringKey : public StringTableKey {
6372 : public:
6373 10425337 : explicit InternalizedStringKey(Handle<String> string)
6374 10425337 : : StringTableKey(0), string_(string) {
6375 : DCHECK(!string->IsInternalizedString());
6376 : DCHECK(string->IsFlat());
6377 : // Make sure hash_field is computed.
6378 10425338 : string->Hash();
6379 : set_hash_field(string->hash_field());
6380 10425340 : }
6381 :
6382 13984881 : bool IsMatch(Object string) override {
6383 13984881 : return string_->SlowEquals(String::cast(string));
6384 : }
6385 :
6386 4730706 : Handle<String> AsHandle(Isolate* isolate) override {
6387 : // Internalize the string if possible.
6388 : MaybeHandle<Map> maybe_map =
6389 4730706 : isolate->factory()->InternalizedStringMapForString(string_);
6390 : Handle<Map> map;
6391 4730706 : if (maybe_map.ToHandle(&map)) {
6392 : string_->set_map_no_write_barrier(*map);
6393 : DCHECK(string_->IsInternalizedString());
6394 50922 : return string_;
6395 : }
6396 4679784 : if (FLAG_thin_strings) {
6397 : // External strings get special treatment, to avoid copying their
6398 : // contents.
6399 9359568 : if (string_->IsExternalOneByteString()) {
6400 : return isolate->factory()
6401 5 : ->InternalizeExternalString<ExternalOneByteString>(string_);
6402 9359558 : } else if (string_->IsExternalTwoByteString()) {
6403 : return isolate->factory()
6404 0 : ->InternalizeExternalString<ExternalTwoByteString>(string_);
6405 : }
6406 : }
6407 : // Otherwise allocate a new internalized string.
6408 : return isolate->factory()->NewInternalizedStringImpl(
6409 4679779 : string_, string_->length(), string_->hash_field());
6410 : }
6411 :
6412 : private:
6413 : Handle<String> string_;
6414 : };
6415 :
6416 : template <typename Derived, typename Shape>
6417 74058 : void HashTable<Derived, Shape>::IteratePrefix(ObjectVisitor* v) {
6418 : BodyDescriptorBase::IteratePointers(*this, 0, kElementsStartOffset, v);
6419 74058 : }
6420 :
6421 : template <typename Derived, typename Shape>
6422 74510 : void HashTable<Derived, Shape>::IterateElements(ObjectVisitor* v) {
6423 : BodyDescriptorBase::IteratePointers(*this, kElementsStartOffset,
6424 : SizeFor(length()), v);
6425 74510 : }
6426 :
6427 : template <typename Derived, typename Shape>
6428 1452604 : Handle<Derived> HashTable<Derived, Shape>::New(
6429 : Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
6430 : MinimumCapacity capacity_option) {
6431 : DCHECK_LE(0, at_least_space_for);
6432 : DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
6433 : base::bits::IsPowerOfTwo(at_least_space_for));
6434 :
6435 : int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
6436 : ? at_least_space_for
6437 1452604 : : ComputeCapacity(at_least_space_for);
6438 1452605 : if (capacity > HashTable::kMaxCapacity) {
6439 0 : isolate->heap()->FatalProcessOutOfMemory("invalid table size");
6440 : }
6441 1452605 : return NewInternal(isolate, capacity, pretenure);
6442 : }
6443 :
6444 : template <typename Derived, typename Shape>
6445 1452604 : Handle<Derived> HashTable<Derived, Shape>::NewInternal(
6446 : Isolate* isolate, int capacity, PretenureFlag pretenure) {
6447 : Factory* factory = isolate->factory();
6448 : int length = EntryToIndex(capacity);
6449 : RootIndex map_root_index = Shape::GetMapRootIndex();
6450 : Handle<FixedArray> array =
6451 1452604 : factory->NewFixedArrayWithMap(map_root_index, length, pretenure);
6452 1452604 : Handle<Derived> table = Handle<Derived>::cast(array);
6453 :
6454 : table->SetNumberOfElements(0);
6455 : table->SetNumberOfDeletedElements(0);
6456 : table->SetCapacity(capacity);
6457 1452605 : return table;
6458 : }
6459 :
6460 : template <typename Derived, typename Shape>
6461 235960 : void HashTable<Derived, Shape>::Rehash(Isolate* isolate, Derived new_table) {
6462 : DisallowHeapAllocation no_gc;
6463 : WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
6464 :
6465 : DCHECK_LT(NumberOfElements(), new_table->Capacity());
6466 :
6467 : // Copy prefix to new array.
6468 670223 : for (int i = kPrefixStartIndex; i < kElementsStartIndex; i++) {
6469 444398 : new_table->set(i, get(i), mode);
6470 : }
6471 :
6472 : // Rehash the elements.
6473 235960 : int capacity = this->Capacity();
6474 : ReadOnlyRoots roots(isolate);
6475 43946646 : for (int i = 0; i < capacity; i++) {
6476 43708449 : uint32_t from_index = EntryToIndex(i);
6477 43614269 : Object k = this->get(from_index);
6478 61815226 : if (!Shape::IsLive(roots, k)) continue;
6479 25507492 : uint32_t hash = Shape::HashForObject(isolate, k);
6480 : uint32_t insertion_index =
6481 51140566 : EntryToIndex(new_table->FindInsertionEntry(hash));
6482 66693833 : for (int j = 0; j < Shape::kEntrySize; j++) {
6483 82247100 : new_table->set(insertion_index + j, get(from_index + j), mode);
6484 : }
6485 : }
6486 235960 : new_table->SetNumberOfElements(NumberOfElements());
6487 : new_table->SetNumberOfDeletedElements(0);
6488 235960 : }
6489 :
6490 : template <typename Derived, typename Shape>
6491 686222011 : uint32_t HashTable<Derived, Shape>::EntryForProbe(Isolate* isolate, Object k,
6492 : int probe,
6493 : uint32_t expected) {
6494 686059176 : uint32_t hash = Shape::HashForObject(isolate, k);
6495 686222386 : uint32_t capacity = this->Capacity();
6496 : uint32_t entry = FirstProbe(hash, capacity);
6497 870703497 : for (int i = 1; i < probe; i++) {
6498 746337087 : if (entry == expected) return expected;
6499 209625340 : entry = NextProbe(entry, i, capacity);
6500 : }
6501 : return entry;
6502 : }
6503 :
6504 : template <typename Derived, typename Shape>
6505 58061525 : void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
6506 : WriteBarrierMode mode) {
6507 58061525 : int index1 = EntryToIndex(entry1);
6508 58061525 : int index2 = EntryToIndex(entry2);
6509 116124961 : Object temp[Shape::kEntrySize];
6510 58063453 : for (int j = 0; j < Shape::kEntrySize; j++) {
6511 116126906 : temp[j] = get(index1 + j);
6512 : }
6513 58063440 : for (int j = 0; j < Shape::kEntrySize; j++) {
6514 116126922 : set(index1 + j, get(index2 + j), mode);
6515 : }
6516 58063299 : for (int j = 0; j < Shape::kEntrySize; j++) {
6517 58063442 : set(index2 + j, temp[j], mode);
6518 : }
6519 58061361 : }
6520 :
6521 : template <typename Derived, typename Shape>
6522 362233 : void HashTable<Derived, Shape>::Rehash(Isolate* isolate) {
6523 : DisallowHeapAllocation no_gc;
6524 362233 : WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
6525 : ReadOnlyRoots roots(isolate);
6526 362235 : uint32_t capacity = Capacity();
6527 : bool done = false;
6528 1602782 : for (int probe = 1; !done; probe++) {
6529 : // All elements at entries given by one of the first _probe_ probes
6530 : // are placed correctly. Other elements might need to be moved.
6531 : done = true;
6532 1517357688 : for (uint32_t current = 0; current < capacity; current++) {
6533 1517357688 : Object current_key = KeyAt(current);
6534 2952253799 : if (!Shape::IsLive(roots, current_key)) continue;
6535 645363083 : uint32_t target = EntryForProbe(isolate, current_key, probe, current);
6536 645365305 : if (current == target) continue;
6537 82467409 : Object target_key = KeyAt(target);
6538 123328021 : if (!Shape::IsLive(roots, target_key) ||
6539 40860534 : EntryForProbe(isolate, target_key, probe, target) != target) {
6540 : // Put the current element into the correct position.
6541 58061476 : Swap(current, target, mode);
6542 : // The other element will be processed on the next iteration.
6543 58061358 : current--;
6544 : } else {
6545 : // The place for the current element is occupied. Leave the element
6546 : // for the next probe.
6547 : done = false;
6548 : }
6549 : }
6550 : }
6551 : // Wipe deleted entries.
6552 : Object the_hole = roots.the_hole_value();
6553 362236 : Object undefined = roots.undefined_value();
6554 182673906 : for (uint32_t current = 0; current < capacity; current++) {
6555 364623340 : if (KeyAt(current) == the_hole) {
6556 1579633 : set(EntryToIndex(current) + kEntryKeyIndex, undefined);
6557 : }
6558 : }
6559 : SetNumberOfDeletedElements(0);
6560 362236 : }
6561 :
6562 : template <typename Derived, typename Shape>
6563 32113111 : Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
6564 : Isolate* isolate, Handle<Derived> table, int n, PretenureFlag pretenure) {
6565 32113112 : if (table->HasSufficientCapacityToAdd(n)) return table;
6566 :
6567 235451 : int capacity = table->Capacity();
6568 235451 : int new_nof = table->NumberOfElements() + n;
6569 :
6570 : const int kMinCapacityForPretenure = 256;
6571 : bool should_pretenure =
6572 : pretenure == TENURED || ((capacity > kMinCapacityForPretenure) &&
6573 244166 : !Heap::InYoungGeneration(*table));
6574 : Handle<Derived> new_table = HashTable::New(
6575 235451 : isolate, new_nof, should_pretenure ? TENURED : NOT_TENURED);
6576 :
6577 235451 : table->Rehash(isolate, *new_table);
6578 235451 : return new_table;
6579 : }
6580 :
6581 : template bool
6582 : HashTable<NameDictionary, NameDictionaryShape>::HasSufficientCapacityToAdd(int);
6583 :
6584 : template <typename Derived, typename Shape>
6585 32146339 : bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
6586 : int number_of_additional_elements) {
6587 32146339 : int capacity = Capacity();
6588 32146341 : int nof = NumberOfElements() + number_of_additional_elements;
6589 32146341 : int nod = NumberOfDeletedElements();
6590 : // Return true if:
6591 : // 50% is still free after adding number_of_additional_elements elements and
6592 : // at most 50% of the free elements are deleted elements.
6593 32146342 : if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
6594 32084152 : int needed_free = nof >> 1;
6595 32084152 : if (nof + needed_free <= capacity) return true;
6596 : }
6597 235903 : return false;
6598 : }
6599 :
6600 : template <typename Derived, typename Shape>
6601 78466 : Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
6602 : Handle<Derived> table,
6603 : int additionalCapacity) {
6604 78466 : int capacity = table->Capacity();
6605 78466 : int nof = table->NumberOfElements();
6606 :
6607 : // Shrink to fit the number of elements if only a quarter of the
6608 : // capacity is filled with elements.
6609 78466 : if (nof > (capacity >> 2)) return table;
6610 : // Allocate a new dictionary with room for at least the current number of
6611 : // elements + {additionalCapacity}. The allocation method will make sure that
6612 : // there is extra room in the dictionary for additions. Don't go lower than
6613 : // room for {kMinShrinkCapacity} elements.
6614 59988 : int at_least_room_for = nof + additionalCapacity;
6615 : int new_capacity = ComputeCapacity(at_least_room_for);
6616 59988 : if (new_capacity < Derived::kMinShrinkCapacity) return table;
6617 509 : if (new_capacity == capacity) return table;
6618 :
6619 : const int kMinCapacityForPretenure = 256;
6620 : bool pretenure = (at_least_room_for > kMinCapacityForPretenure) &&
6621 748 : !Heap::InYoungGeneration(*table);
6622 : Handle<Derived> new_table =
6623 : HashTable::New(isolate, new_capacity, pretenure ? TENURED : NOT_TENURED,
6624 509 : USE_CUSTOM_MINIMUM_CAPACITY);
6625 :
6626 509 : table->Rehash(isolate, *new_table);
6627 509 : return new_table;
6628 : }
6629 :
6630 : template <typename Derived, typename Shape>
6631 57687865 : uint32_t HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
6632 57687865 : uint32_t capacity = Capacity();
6633 : uint32_t entry = FirstProbe(hash, capacity);
6634 : uint32_t count = 1;
6635 : // EnsureCapacity will guarantee the hash table is never full.
6636 57687868 : ReadOnlyRoots roots = GetReadOnlyRoots();
6637 : while (true) {
6638 147367606 : if (!Shape::IsLive(roots, KeyAt(entry))) break;
6639 89679740 : entry = NextProbe(entry, count++, capacity);
6640 : }
6641 89679740 : return entry;
6642 : }
6643 :
6644 :
6645 : // This class is used for looking up two character strings in the string table.
6646 : // If we don't have a hit we don't want to waste much time so we unroll the
6647 : // string hash calculation loop here for speed. Doesn't work if the two
6648 : // characters form a decimal integer, since such strings have a different hash
6649 : // algorithm.
6650 0 : class TwoCharHashTableKey : public StringTableKey {
6651 : public:
6652 : TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint64_t seed)
6653 3411896 : : StringTableKey(ComputeHashField(c1, c2, seed)), c1_(c1), c2_(c2) {}
6654 :
6655 2572344 : bool IsMatch(Object o) override {
6656 2572344 : String other = String::cast(o);
6657 2572344 : if (other->length() != 2) return false;
6658 101254 : if (other->Get(0) != c1_) return false;
6659 15326 : return other->Get(1) == c2_;
6660 : }
6661 :
6662 0 : Handle<String> AsHandle(Isolate* isolate) override {
6663 : // The TwoCharHashTableKey is only used for looking in the string
6664 : // table, not for adding to it.
6665 0 : UNREACHABLE();
6666 : }
6667 :
6668 : private:
6669 1705948 : uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint64_t seed) {
6670 : // Char 1.
6671 1705948 : uint32_t hash = static_cast<uint32_t>(seed);
6672 1705948 : hash += c1;
6673 1705948 : hash += hash << 10;
6674 1705948 : hash ^= hash >> 6;
6675 : // Char 2.
6676 1705948 : hash += c2;
6677 1705948 : hash += hash << 10;
6678 1705948 : hash ^= hash >> 6;
6679 : // GetHash.
6680 1705948 : hash += hash << 3;
6681 1705948 : hash ^= hash >> 11;
6682 1705948 : hash += hash << 15;
6683 1705948 : if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
6684 1705948 : hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
6685 : #ifdef DEBUG
6686 : // If this assert fails then we failed to reproduce the two-character
6687 : // version of the string hashing algorithm above. One reason could be
6688 : // that we were passed two digits as characters, since the hash
6689 : // algorithm is different in that case.
6690 : uint16_t chars[2] = {c1, c2};
6691 : uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
6692 : DCHECK_EQ(hash, check_hash);
6693 : #endif
6694 1705948 : return hash;
6695 : }
6696 :
6697 : uint16_t c1_;
6698 : uint16_t c2_;
6699 : };
6700 :
6701 1705948 : MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
6702 : Isolate* isolate,
6703 : uint16_t c1,
6704 : uint16_t c2) {
6705 1705948 : TwoCharHashTableKey key(c1, c2, HashSeed(isolate));
6706 : Handle<StringTable> string_table = isolate->factory()->string_table();
6707 1705948 : int entry = string_table->FindEntry(isolate, &key);
6708 1705948 : if (entry == kNotFound) return MaybeHandle<String>();
6709 :
6710 27444 : Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
6711 : DCHECK(StringShape(*result).IsInternalized());
6712 : DCHECK_EQ(result->Hash(), key.Hash());
6713 13722 : return result;
6714 : }
6715 :
6716 209 : void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
6717 : int expected) {
6718 : Handle<StringTable> table = isolate->factory()->string_table();
6719 : // We need a key instance for the virtual hash function.
6720 209 : table = StringTable::EnsureCapacity(isolate, table, expected);
6721 209 : isolate->heap()->SetRootStringTable(*table);
6722 209 : }
6723 :
6724 : namespace {
6725 :
6726 : template <class StringClass>
6727 14 : void MigrateExternalStringResource(Isolate* isolate, String from, String to) {
6728 14 : StringClass cast_from = StringClass::cast(from);
6729 14 : StringClass cast_to = StringClass::cast(to);
6730 : const typename StringClass::Resource* to_resource = cast_to->resource();
6731 14 : if (to_resource == nullptr) {
6732 : // |to| is a just-created internalized copy of |from|. Migrate the resource.
6733 5 : cast_to->SetResource(isolate, cast_from->resource());
6734 : // Zap |from|'s resource pointer to reflect the fact that |from| has
6735 : // relinquished ownership of its resource.
6736 5 : isolate->heap()->UpdateExternalString(
6737 10 : from, ExternalString::cast(from)->ExternalPayloadSize(), 0);
6738 5 : cast_from->SetResource(isolate, nullptr);
6739 9 : } else if (to_resource != cast_from->resource()) {
6740 : // |to| already existed and has its own resource. Finalize |from|.
6741 9 : isolate->heap()->FinalizeExternalString(from);
6742 : }
6743 14 : }
6744 :
6745 11945078 : void MakeStringThin(String string, String internalized, Isolate* isolate) {
6746 : DCHECK_NE(string, internalized);
6747 : DCHECK(internalized->IsInternalizedString());
6748 :
6749 11945079 : if (string->IsExternalString()) {
6750 14 : if (internalized->IsExternalOneByteString()) {
6751 : MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
6752 14 : internalized);
6753 0 : } else if (internalized->IsExternalTwoByteString()) {
6754 : MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
6755 0 : internalized);
6756 : } else {
6757 : // If the external string is duped into an existing non-external
6758 : // internalized string, free its resource (it's about to be rewritten
6759 : // into a ThinString below).
6760 0 : isolate->heap()->FinalizeExternalString(string);
6761 : }
6762 : }
6763 :
6764 : DisallowHeapAllocation no_gc;
6765 11945079 : int old_size = string->Size();
6766 11945079 : isolate->heap()->NotifyObjectLayoutChange(string, old_size, no_gc);
6767 11945082 : bool one_byte = internalized->IsOneByteRepresentation();
6768 : Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
6769 11945082 : : isolate->factory()->thin_string_map();
6770 : DCHECK_GE(old_size, ThinString::kSize);
6771 11945082 : string->synchronized_set_map(*map);
6772 11945081 : ThinString thin = ThinString::cast(string);
6773 11945081 : thin->set_actual(internalized);
6774 11945080 : Address thin_end = thin->address() + ThinString::kSize;
6775 11945080 : int size_delta = old_size - ThinString::kSize;
6776 11945080 : if (size_delta != 0) {
6777 : Heap* heap = isolate->heap();
6778 5400512 : heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
6779 : }
6780 11945080 : }
6781 :
6782 : } // namespace
6783 :
6784 : // static
6785 11291559 : Handle<String> StringTable::LookupString(Isolate* isolate,
6786 : Handle<String> string) {
6787 11291559 : string = String::Flatten(isolate, string);
6788 22583118 : if (string->IsInternalizedString()) return string;
6789 :
6790 10425338 : InternalizedStringKey key(string);
6791 10425340 : Handle<String> result = LookupKey(isolate, &key);
6792 :
6793 10425340 : if (FLAG_thin_strings) {
6794 20850681 : if (!string->IsInternalizedString()) {
6795 10374419 : MakeStringThin(*string, *result, isolate);
6796 : }
6797 : } else { // !FLAG_thin_strings
6798 0 : if (string->IsConsString()) {
6799 0 : Handle<ConsString> cons = Handle<ConsString>::cast(string);
6800 0 : cons->set_first(isolate, *result);
6801 0 : cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
6802 0 : } else if (string->IsSlicedString()) {
6803 : STATIC_ASSERT(static_cast<int>(ConsString::kSize) ==
6804 : static_cast<int>(SlicedString::kSize));
6805 : DisallowHeapAllocation no_gc;
6806 0 : bool one_byte = result->IsOneByteRepresentation();
6807 : Handle<Map> map = one_byte
6808 : ? isolate->factory()->cons_one_byte_string_map()
6809 0 : : isolate->factory()->cons_string_map();
6810 0 : string->set_map(*map);
6811 0 : Handle<ConsString> cons = Handle<ConsString>::cast(string);
6812 0 : cons->set_first(isolate, *result);
6813 0 : cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
6814 : }
6815 : }
6816 10425341 : return result;
6817 : }
6818 :
6819 : // static
6820 51457744 : Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
6821 : Handle<StringTable> table = isolate->factory()->string_table();
6822 51457740 : int entry = table->FindEntry(isolate, key);
6823 :
6824 : // String already in table.
6825 51457775 : if (entry != kNotFound) {
6826 73919300 : return handle(String::cast(table->KeyAt(entry)), isolate);
6827 : }
6828 :
6829 14498123 : table = StringTable::CautiousShrink(isolate, table);
6830 : // Adding new string. Grow table if needed.
6831 14498120 : table = StringTable::EnsureCapacity(isolate, table, 1);
6832 14498121 : isolate->heap()->SetRootStringTable(*table);
6833 :
6834 14498121 : return AddKeyNoResize(isolate, key);
6835 : }
6836 :
6837 14502803 : Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
6838 : StringTableKey* key) {
6839 : Handle<StringTable> table = isolate->factory()->string_table();
6840 : DCHECK(table->HasSufficientCapacityToAdd(1));
6841 : // Create string object.
6842 14502803 : Handle<String> string = key->AsHandle(isolate);
6843 : // There must be no attempts to internalize strings that could throw
6844 : // InvalidStringLength error.
6845 14502804 : CHECK(!string.is_null());
6846 : DCHECK(string->HasHashCode());
6847 : DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
6848 :
6849 : // Add the new string and return it along with the string table.
6850 29005607 : int entry = table->FindInsertionEntry(key->Hash());
6851 29005608 : table->set(EntryToIndex(entry), *string);
6852 14502803 : table->ElementAdded();
6853 :
6854 14502804 : return Handle<String>::cast(string);
6855 : }
6856 :
6857 14498123 : Handle<StringTable> StringTable::CautiousShrink(Isolate* isolate,
6858 : Handle<StringTable> table) {
6859 : // Only shrink if the table is very empty to avoid performance penalty.
6860 14498123 : int capacity = table->Capacity();
6861 14498122 : int nof = table->NumberOfElements();
6862 14498120 : if (capacity <= StringTable::kMinCapacity) return table;
6863 7458572 : if (nof > (capacity / kMaxEmptyFactor)) return table;
6864 : // Keep capacity for at least half of the current nof elements.
6865 30909 : int slack_capacity = nof >> 2;
6866 30909 : return Shrink(isolate, table, slack_capacity);
6867 : }
6868 :
6869 : namespace {
6870 :
6871 : class StringTableNoAllocateKey : public StringTableKey {
6872 : public:
6873 1958489 : StringTableNoAllocateKey(String string, uint64_t seed)
6874 1958489 : : StringTableKey(0), string_(string) {
6875 : StringShape shape(string);
6876 1958489 : one_byte_ = shape.HasOnlyOneByteChars();
6877 : DCHECK(!shape.IsInternalized());
6878 : DCHECK(!shape.IsThin());
6879 : int length = string->length();
6880 1958489 : if (shape.IsCons() && length <= String::kMaxHashCalcLength) {
6881 287748 : special_flattening_ = true;
6882 : uint32_t hash_field = 0;
6883 287748 : if (one_byte_) {
6884 287748 : if (V8_LIKELY(length <=
6885 : static_cast<int>(arraysize(one_byte_buffer_)))) {
6886 287748 : one_byte_content_ = one_byte_buffer_;
6887 : } else {
6888 0 : one_byte_content_ = new uint8_t[length];
6889 : }
6890 287748 : String::WriteToFlat(string, one_byte_content_, 0, length);
6891 : hash_field =
6892 287748 : StringHasher::HashSequentialString(one_byte_content_, length, seed);
6893 : } else {
6894 0 : if (V8_LIKELY(length <=
6895 : static_cast<int>(arraysize(two_byte_buffer_)))) {
6896 0 : two_byte_content_ = two_byte_buffer_;
6897 : } else {
6898 0 : two_byte_content_ = new uint16_t[length];
6899 : }
6900 0 : String::WriteToFlat(string, two_byte_content_, 0, length);
6901 : hash_field =
6902 0 : StringHasher::HashSequentialString(two_byte_content_, length, seed);
6903 : }
6904 : string->set_hash_field(hash_field);
6905 : } else {
6906 1670741 : special_flattening_ = false;
6907 1670741 : one_byte_content_ = nullptr;
6908 1670741 : string->Hash();
6909 : }
6910 :
6911 : DCHECK(string->HasHashCode());
6912 : set_hash_field(string->hash_field());
6913 1958489 : }
6914 :
6915 1958489 : ~StringTableNoAllocateKey() override {
6916 1958489 : if (one_byte_) {
6917 1217504 : if (one_byte_content_ != one_byte_buffer_) delete[] one_byte_content_;
6918 : } else {
6919 740985 : if (two_byte_content_ != two_byte_buffer_) delete[] two_byte_content_;
6920 : }
6921 1958489 : }
6922 :
6923 3585763 : bool IsMatch(Object otherstring) override {
6924 3585763 : String other = String::cast(otherstring);
6925 : DCHECK(other->IsInternalizedString());
6926 : DCHECK(other->IsFlat());
6927 3585763 : if (Hash() != other->Hash()) return false;
6928 : int len = string_->length();
6929 1570088 : if (len != other->length()) return false;
6930 :
6931 : DisallowHeapAllocation no_gc;
6932 1570088 : if (!special_flattening_) {
6933 2867476 : if (string_->Get(0) != other->Get(0)) return false;
6934 1433738 : if (string_->IsFlat()) {
6935 : StringShape shape1(string_);
6936 : StringShape shape2(other);
6937 2144776 : if (shape1.encoding_tag() == kOneByteStringTag &&
6938 : shape2.encoding_tag() == kOneByteStringTag) {
6939 711038 : String::FlatContent flat1 = string_->GetFlatContent(no_gc);
6940 711038 : String::FlatContent flat2 = other->GetFlatContent(no_gc);
6941 711038 : return CompareRawStringContents(flat1.ToOneByteVector().start(),
6942 711038 : flat2.ToOneByteVector().start(), len);
6943 : }
6944 1445400 : if (shape1.encoding_tag() == kTwoByteStringTag &&
6945 : shape2.encoding_tag() == kTwoByteStringTag) {
6946 722700 : String::FlatContent flat1 = string_->GetFlatContent(no_gc);
6947 722700 : String::FlatContent flat2 = other->GetFlatContent(no_gc);
6948 722700 : return CompareRawStringContents(flat1.ToUC16Vector().start(),
6949 722700 : flat2.ToUC16Vector().start(), len);
6950 : }
6951 : }
6952 0 : StringComparator comparator;
6953 0 : return comparator.Equals(string_, other);
6954 : }
6955 :
6956 136350 : String::FlatContent flat_content = other->GetFlatContent(no_gc);
6957 136350 : if (one_byte_) {
6958 136350 : if (flat_content.IsOneByte()) {
6959 : return CompareRawStringContents(
6960 136350 : one_byte_content_, flat_content.ToOneByteVector().start(), len);
6961 : } else {
6962 : DCHECK(flat_content.IsTwoByte());
6963 0 : for (int i = 0; i < len; i++) {
6964 0 : if (flat_content.Get(i) != one_byte_content_[i]) return false;
6965 : }
6966 : return true;
6967 : }
6968 : } else {
6969 0 : if (flat_content.IsTwoByte()) {
6970 : return CompareRawStringContents(
6971 0 : two_byte_content_, flat_content.ToUC16Vector().start(), len);
6972 : } else {
6973 : DCHECK(flat_content.IsOneByte());
6974 0 : for (int i = 0; i < len; i++) {
6975 0 : if (flat_content.Get(i) != two_byte_content_[i]) return false;
6976 : }
6977 : return true;
6978 : }
6979 : }
6980 : }
6981 :
6982 0 : V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override {
6983 0 : UNREACHABLE();
6984 : }
6985 :
6986 : private:
6987 : String string_;
6988 : bool one_byte_;
6989 : bool special_flattening_;
6990 : union {
6991 : uint8_t* one_byte_content_;
6992 : uint16_t* two_byte_content_;
6993 : };
6994 : union {
6995 : uint8_t one_byte_buffer_[256];
6996 : uint16_t two_byte_buffer_[128];
6997 : };
6998 : };
6999 :
7000 : } // namespace
7001 :
7002 : // static
7003 1958489 : Address StringTable::LookupStringIfExists_NoAllocate(Isolate* isolate,
7004 : Address raw_string) {
7005 : DisallowHeapAllocation no_gc;
7006 : String string = String::cast(Object(raw_string));
7007 1958489 : Heap* heap = isolate->heap();
7008 1958489 : StringTable table = heap->string_table();
7009 :
7010 1958489 : StringTableNoAllocateKey key(string, HashSeed(isolate));
7011 :
7012 : // String could be an array index.
7013 : uint32_t hash = string->hash_field();
7014 :
7015 : // Valid array indices are >= 0, so they cannot be mixed up with any of
7016 : // the result sentinels, which are negative.
7017 : STATIC_ASSERT(
7018 : !String::ArrayIndexValueBits::is_valid(ResultSentinel::kUnsupported));
7019 : STATIC_ASSERT(
7020 : !String::ArrayIndexValueBits::is_valid(ResultSentinel::kNotFound));
7021 :
7022 1958489 : if (Name::ContainsCachedArrayIndex(hash)) {
7023 65 : return Smi::FromInt(String::ArrayIndexValueBits::decode(hash)).ptr();
7024 : }
7025 1958424 : if ((hash & Name::kIsNotArrayIndexMask) == 0) {
7026 : // It is an indexed, but it's not cached.
7027 : return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
7028 : }
7029 :
7030 : DCHECK(!string->IsInternalizedString());
7031 3916700 : int entry = table->FindEntry(ReadOnlyRoots(isolate), &key, key.Hash());
7032 1958350 : if (entry != kNotFound) {
7033 1570088 : String internalized = String::cast(table->KeyAt(entry));
7034 1570088 : if (FLAG_thin_strings) {
7035 1570088 : MakeStringThin(string, internalized, isolate);
7036 : }
7037 : return internalized.ptr();
7038 : }
7039 : // A string that's not an array index, and not in the string table,
7040 : // cannot have been used as a property name before.
7041 1958489 : return Smi::FromInt(ResultSentinel::kNotFound).ptr();
7042 : }
7043 :
7044 5255 : String StringTable::ForwardStringIfExists(Isolate* isolate, StringTableKey* key,
7045 : String string) {
7046 : Handle<StringTable> table = isolate->factory()->string_table();
7047 5255 : int entry = table->FindEntry(isolate, key);
7048 5255 : if (entry == kNotFound) return String();
7049 :
7050 1146 : String canonical = String::cast(table->KeyAt(entry));
7051 573 : if (canonical != string) MakeStringThin(string, canonical, isolate);
7052 573 : return canonical;
7053 : }
7054 :
7055 12376 : Handle<StringSet> StringSet::New(Isolate* isolate) {
7056 12376 : return HashTable::New(isolate, 0);
7057 : }
7058 :
7059 16545 : Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
7060 : Handle<String> name) {
7061 16545 : if (!stringset->Has(isolate, name)) {
7062 11651 : stringset = EnsureCapacity(isolate, stringset, 1);
7063 : uint32_t hash = ShapeT::Hash(isolate, *name);
7064 11651 : int entry = stringset->FindInsertionEntry(hash);
7065 23302 : stringset->set(EntryToIndex(entry), *name);
7066 11651 : stringset->ElementAdded();
7067 : }
7068 16545 : return stringset;
7069 : }
7070 :
7071 21646 : bool StringSet::Has(Isolate* isolate, Handle<String> name) {
7072 21646 : return FindEntry(isolate, *name) != kNotFound;
7073 : }
7074 :
7075 107853 : Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
7076 : Handle<ObjectHashSet> set,
7077 : Handle<Object> key) {
7078 215706 : int32_t hash = key->GetOrCreateHash(isolate)->value();
7079 107853 : if (!set->Has(isolate, key, hash)) {
7080 106222 : set = EnsureCapacity(isolate, set, 1);
7081 212444 : int entry = set->FindInsertionEntry(hash);
7082 106222 : set->set(EntryToIndex(entry), *key);
7083 106222 : set->ElementAdded();
7084 : }
7085 107853 : return set;
7086 : }
7087 :
7088 : namespace {
7089 :
7090 : const int kLiteralEntryLength = 2;
7091 : const int kLiteralInitialLength = 2;
7092 : const int kLiteralContextOffset = 0;
7093 : const int kLiteralLiteralsOffset = 1;
7094 :
7095 2976476 : int SearchLiteralsMapEntry(CompilationCacheTable cache, int cache_entry,
7096 : Context native_context) {
7097 : DisallowHeapAllocation no_gc;
7098 : DCHECK(native_context->IsNativeContext());
7099 2976476 : Object obj = cache->get(cache_entry);
7100 :
7101 : // Check that there's no confusion between FixedArray and WeakFixedArray (the
7102 : // object used to be a FixedArray here).
7103 : DCHECK(!obj->IsFixedArray());
7104 2976476 : if (obj->IsWeakFixedArray()) {
7105 2976476 : WeakFixedArray literals_map = WeakFixedArray::cast(obj);
7106 : int length = literals_map->length();
7107 6872275 : for (int i = 0; i < length; i += kLiteralEntryLength) {
7108 : DCHECK(literals_map->Get(i + kLiteralContextOffset)->IsWeakOrCleared());
7109 12276838 : if (literals_map->Get(i + kLiteralContextOffset) ==
7110 : HeapObjectReference::Weak(native_context)) {
7111 2242620 : return i;
7112 : }
7113 : }
7114 : }
7115 : return -1;
7116 : }
7117 :
7118 559687 : void AddToFeedbackCellsMap(Handle<CompilationCacheTable> cache, int cache_entry,
7119 : Handle<Context> native_context,
7120 : Handle<FeedbackCell> feedback_cell) {
7121 : Isolate* isolate = native_context->GetIsolate();
7122 : DCHECK(native_context->IsNativeContext());
7123 : STATIC_ASSERT(kLiteralEntryLength == 2);
7124 : Handle<WeakFixedArray> new_literals_map;
7125 : int entry;
7126 :
7127 559687 : Object obj = cache->get(cache_entry);
7128 :
7129 : // Check that there's no confusion between FixedArray and WeakFixedArray (the
7130 : // object used to be a FixedArray here).
7131 : DCHECK(!obj->IsFixedArray());
7132 936242 : if (!obj->IsWeakFixedArray() || WeakFixedArray::cast(obj)->length() == 0) {
7133 : new_literals_map =
7134 183132 : isolate->factory()->NewWeakFixedArray(kLiteralInitialLength, TENURED);
7135 : entry = 0;
7136 : } else {
7137 : Handle<WeakFixedArray> old_literals_map(WeakFixedArray::cast(obj), isolate);
7138 376555 : entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context);
7139 376555 : if (entry >= 0) {
7140 : // Just set the code of the entry.
7141 : old_literals_map->Set(entry + kLiteralLiteralsOffset,
7142 11878 : HeapObjectReference::Weak(*feedback_cell));
7143 559687 : return;
7144 : }
7145 :
7146 : // Can we reuse an entry?
7147 : DCHECK_LT(entry, 0);
7148 : int length = old_literals_map->length();
7149 1094135 : for (int i = 0; i < length; i += kLiteralEntryLength) {
7150 1476432 : if (old_literals_map->Get(i + kLiteralContextOffset)->IsCleared()) {
7151 : new_literals_map = old_literals_map;
7152 : entry = i;
7153 : break;
7154 : }
7155 : }
7156 :
7157 370616 : if (entry < 0) {
7158 : // Copy old optimized code map and append one new entry.
7159 : new_literals_map = isolate->factory()->CopyWeakFixedArrayAndGrow(
7160 355919 : old_literals_map, kLiteralEntryLength, TENURED);
7161 : entry = old_literals_map->length();
7162 : }
7163 : }
7164 :
7165 : new_literals_map->Set(entry + kLiteralContextOffset,
7166 1107496 : HeapObjectReference::Weak(*native_context));
7167 : new_literals_map->Set(entry + kLiteralLiteralsOffset,
7168 1107496 : HeapObjectReference::Weak(*feedback_cell));
7169 :
7170 : #ifdef DEBUG
7171 : for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) {
7172 : MaybeObject object = new_literals_map->Get(i + kLiteralContextOffset);
7173 : DCHECK(object->IsCleared() ||
7174 : object->GetHeapObjectAssumeWeak()->IsNativeContext());
7175 : object = new_literals_map->Get(i + kLiteralLiteralsOffset);
7176 : DCHECK(object->IsCleared() ||
7177 : object->GetHeapObjectAssumeWeak()->IsFeedbackCell());
7178 : }
7179 : #endif
7180 :
7181 : Object old_literals_map = cache->get(cache_entry);
7182 553748 : if (old_literals_map != *new_literals_map) {
7183 1078102 : cache->set(cache_entry, *new_literals_map);
7184 : }
7185 : }
7186 :
7187 2599921 : FeedbackCell SearchLiteralsMap(CompilationCacheTable cache, int cache_entry,
7188 : Context native_context) {
7189 : FeedbackCell result;
7190 2599921 : int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context);
7191 2599921 : if (entry >= 0) {
7192 2236681 : WeakFixedArray literals_map = WeakFixedArray::cast(cache->get(cache_entry));
7193 : DCHECK_LE(entry + kLiteralEntryLength, literals_map->length());
7194 2236681 : MaybeObject object = literals_map->Get(entry + kLiteralLiteralsOffset);
7195 :
7196 2236681 : if (!object->IsCleared()) {
7197 : result = FeedbackCell::cast(object->GetHeapObjectAssumeWeak());
7198 : }
7199 : }
7200 : DCHECK(result.is_null() || result->IsFeedbackCell());
7201 2599921 : return result;
7202 : }
7203 :
7204 : } // namespace
7205 :
7206 268326 : MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
7207 : Handle<CompilationCacheTable> table, Handle<String> src,
7208 : Handle<Context> native_context, LanguageMode language_mode) {
7209 : // We use the empty function SFI as part of the key. Although the
7210 : // empty_function is native context dependent, the SFI is de-duped on
7211 : // snapshot builds by the PartialSnapshotCache, and so this does not prevent
7212 : // reuse of scripts in the compilation cache across native contexts.
7213 536652 : Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
7214 536652 : native_context->GetIsolate());
7215 : Isolate* isolate = native_context->GetIsolate();
7216 268326 : src = String::Flatten(isolate, src);
7217 268326 : StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
7218 268326 : int entry = table->FindEntry(isolate, &key);
7219 268326 : if (entry == kNotFound) return MaybeHandle<SharedFunctionInfo>();
7220 : int index = EntryToIndex(entry);
7221 259296 : if (!table->get(index)->IsFixedArray()) {
7222 0 : return MaybeHandle<SharedFunctionInfo>();
7223 : }
7224 259296 : Object obj = table->get(index + 1);
7225 129648 : if (obj->IsSharedFunctionInfo()) {
7226 129648 : return handle(SharedFunctionInfo::cast(obj), native_context->GetIsolate());
7227 : }
7228 0 : return MaybeHandle<SharedFunctionInfo>();
7229 : }
7230 :
7231 3523725 : InfoCellPair CompilationCacheTable::LookupEval(
7232 : Handle<CompilationCacheTable> table, Handle<String> src,
7233 : Handle<SharedFunctionInfo> outer_info, Handle<Context> native_context,
7234 : LanguageMode language_mode, int position) {
7235 : InfoCellPair empty_result;
7236 : Isolate* isolate = native_context->GetIsolate();
7237 3523725 : src = String::Flatten(isolate, src);
7238 3523725 : StringSharedKey key(src, outer_info, language_mode, position);
7239 3523725 : int entry = table->FindEntry(isolate, &key);
7240 3523725 : if (entry == kNotFound) return empty_result;
7241 : int index = EntryToIndex(entry);
7242 5561554 : if (!table->get(index)->IsFixedArray()) return empty_result;
7243 5199842 : Object obj = table->get(EntryToIndex(entry) + 1);
7244 2599921 : if (obj->IsSharedFunctionInfo()) {
7245 : FeedbackCell feedback_cell =
7246 5199842 : SearchLiteralsMap(*table, EntryToIndex(entry) + 2, *native_context);
7247 2599921 : return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
7248 : }
7249 0 : return empty_result;
7250 : }
7251 :
7252 723165 : Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
7253 : JSRegExp::Flags flags) {
7254 : Isolate* isolate = GetIsolate();
7255 : DisallowHeapAllocation no_allocation;
7256 723165 : RegExpKey key(src, flags);
7257 723165 : int entry = FindEntry(isolate, &key);
7258 1251811 : if (entry == kNotFound) return isolate->factory()->undefined_value();
7259 389038 : return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
7260 : }
7261 :
7262 136991 : Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
7263 : Handle<CompilationCacheTable> cache, Handle<String> src,
7264 : Handle<Context> native_context, LanguageMode language_mode,
7265 : Handle<SharedFunctionInfo> value) {
7266 : Isolate* isolate = native_context->GetIsolate();
7267 : // We use the empty function SFI as part of the key. Although the
7268 : // empty_function is native context dependent, the SFI is de-duped on
7269 : // snapshot builds by the PartialSnapshotCache, and so this does not prevent
7270 : // reuse of scripts in the compilation cache across native contexts.
7271 273982 : Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
7272 273982 : isolate);
7273 136991 : src = String::Flatten(isolate, src);
7274 136992 : StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
7275 136992 : Handle<Object> k = key.AsHandle(isolate);
7276 136992 : cache = EnsureCapacity(isolate, cache, 1);
7277 273983 : int entry = cache->FindInsertionEntry(key.Hash());
7278 136992 : cache->set(EntryToIndex(entry), *k);
7279 273984 : cache->set(EntryToIndex(entry) + 1, *value);
7280 136991 : cache->ElementAdded();
7281 136992 : return cache;
7282 : }
7283 :
7284 1185393 : Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
7285 : Handle<CompilationCacheTable> cache, Handle<String> src,
7286 : Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
7287 : Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
7288 : int position) {
7289 : Isolate* isolate = native_context->GetIsolate();
7290 1185393 : src = String::Flatten(isolate, src);
7291 1185393 : StringSharedKey key(src, outer_info, value->language_mode(), position);
7292 : {
7293 1185393 : Handle<Object> k = key.AsHandle(isolate);
7294 1185393 : int entry = cache->FindEntry(isolate, &key);
7295 1185393 : if (entry != kNotFound) {
7296 559687 : cache->set(EntryToIndex(entry), *k);
7297 1119374 : cache->set(EntryToIndex(entry) + 1, *value);
7298 : // AddToFeedbackCellsMap may allocate a new sub-array to live in the
7299 : // entry, but it won't change the cache array. Therefore EntryToIndex
7300 : // and entry remains correct.
7301 : AddToFeedbackCellsMap(cache, EntryToIndex(entry) + 2, native_context,
7302 559687 : feedback_cell);
7303 559687 : return cache;
7304 : }
7305 : }
7306 :
7307 625706 : cache = EnsureCapacity(isolate, cache, 1);
7308 1251412 : int entry = cache->FindInsertionEntry(key.Hash());
7309 : Handle<Object> k =
7310 625706 : isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
7311 625706 : cache->set(EntryToIndex(entry), *k);
7312 : cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
7313 625706 : cache->ElementAdded();
7314 625706 : return cache;
7315 : }
7316 :
7317 261775 : Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
7318 : Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
7319 : JSRegExp::Flags flags, Handle<FixedArray> value) {
7320 261775 : RegExpKey key(src, flags);
7321 261775 : cache = EnsureCapacity(isolate, cache, 1);
7322 523550 : int entry = cache->FindInsertionEntry(key.Hash());
7323 : // We store the value in the key slot, and compare the search key
7324 : // to the stored value with a custon IsMatch function during lookups.
7325 523550 : cache->set(EntryToIndex(entry), *value);
7326 523550 : cache->set(EntryToIndex(entry) + 1, *value);
7327 261775 : cache->ElementAdded();
7328 261775 : return cache;
7329 : }
7330 :
7331 :
7332 66929 : void CompilationCacheTable::Age() {
7333 : DisallowHeapAllocation no_allocation;
7334 133858 : Object the_hole_value = GetReadOnlyRoots().the_hole_value();
7335 11599622 : for (int entry = 0, size = Capacity(); entry < size; entry++) {
7336 : int entry_index = EntryToIndex(entry);
7337 11465764 : int value_index = entry_index + 1;
7338 :
7339 22931528 : if (get(entry_index)->IsNumber()) {
7340 : Smi count = Smi::cast(get(value_index));
7341 1049839 : count = Smi::FromInt(count->value() - 1);
7342 1049839 : if (count->value() == 0) {
7343 : NoWriteBarrierSet(*this, entry_index, the_hole_value);
7344 : NoWriteBarrierSet(*this, value_index, the_hole_value);
7345 73388 : ElementRemoved();
7346 : } else {
7347 : NoWriteBarrierSet(*this, value_index, count);
7348 : }
7349 20831850 : } else if (get(entry_index)->IsFixedArray()) {
7350 494239 : SharedFunctionInfo info = SharedFunctionInfo::cast(get(value_index));
7351 494239 : if (info->IsInterpreted() && info->GetBytecodeArray()->IsOld()) {
7352 67998 : for (int i = 0; i < kEntrySize; i++) {
7353 67998 : NoWriteBarrierSet(*this, entry_index + i, the_hole_value);
7354 : }
7355 22666 : ElementRemoved();
7356 : }
7357 : }
7358 : }
7359 66929 : }
7360 :
7361 804 : void CompilationCacheTable::Remove(Object value) {
7362 : DisallowHeapAllocation no_allocation;
7363 1608 : Object the_hole_value = GetReadOnlyRoots().the_hole_value();
7364 104520 : for (int entry = 0, size = Capacity(); entry < size; entry++) {
7365 : int entry_index = EntryToIndex(entry);
7366 102912 : int value_index = entry_index + 1;
7367 102912 : if (get(value_index) == value) {
7368 426 : for (int i = 0; i < kEntrySize; i++) {
7369 426 : NoWriteBarrierSet(*this, entry_index + i, the_hole_value);
7370 : }
7371 142 : ElementRemoved();
7372 : }
7373 : }
7374 804 : return;
7375 : }
7376 :
7377 : template <typename Derived, typename Shape>
7378 772956 : Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
7379 : Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
7380 : MinimumCapacity capacity_option) {
7381 : DCHECK_LE(0, at_least_space_for);
7382 : Handle<Derived> dict = Dictionary<Derived, Shape>::New(
7383 772956 : isolate, at_least_space_for, pretenure, capacity_option);
7384 : dict->SetHash(PropertyArray::kNoHashSentinel);
7385 : dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
7386 772958 : return dict;
7387 : }
7388 :
7389 : template <typename Derived, typename Shape>
7390 12598900 : Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
7391 : Isolate* isolate, Handle<Derived> dictionary, int n) {
7392 : // Check whether there are enough enumeration indices to add n elements.
7393 25197802 : if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
7394 : // If not, we generate new indices for the properties.
7395 0 : int length = dictionary->NumberOfElements();
7396 :
7397 0 : Handle<FixedArray> iteration_order = IterationIndices(isolate, dictionary);
7398 : DCHECK_EQ(length, iteration_order->length());
7399 :
7400 : // Iterate over the dictionary using the enumeration order and update
7401 : // the dictionary with new enumeration indices.
7402 0 : for (int i = 0; i < length; i++) {
7403 0 : int index = Smi::ToInt(iteration_order->get(i));
7404 : DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
7405 : dictionary->KeyAt(index)));
7406 :
7407 0 : int enum_index = PropertyDetails::kInitialIndex + i;
7408 :
7409 0 : PropertyDetails details = dictionary->DetailsAt(index);
7410 0 : PropertyDetails new_details = details.set_index(enum_index);
7411 0 : dictionary->DetailsAtPut(isolate, index, new_details);
7412 : }
7413 :
7414 : // Set the next enumeration index.
7415 0 : dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
7416 : length);
7417 : }
7418 12598901 : return HashTable<Derived, Shape>::EnsureCapacity(isolate, dictionary, n);
7419 : }
7420 :
7421 : template <typename Derived, typename Shape>
7422 47158 : Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
7423 : Isolate* isolate, Handle<Derived> dictionary, int entry) {
7424 : DCHECK(Shape::kEntrySize != 3 ||
7425 : dictionary->DetailsAt(entry).IsConfigurable());
7426 47158 : dictionary->ClearEntry(isolate, entry);
7427 47158 : dictionary->ElementRemoved();
7428 47158 : return Shrink(isolate, dictionary);
7429 : }
7430 :
7431 : template <typename Derived, typename Shape>
7432 479532 : Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
7433 : Handle<Derived> dictionary,
7434 : Key key, Handle<Object> value,
7435 : PropertyDetails details) {
7436 479532 : int entry = dictionary->FindEntry(isolate, key);
7437 :
7438 : // If the entry is present set the value;
7439 479532 : if (entry == Dictionary::kNotFound) {
7440 477139 : return Derived::Add(isolate, dictionary, key, value, details);
7441 : }
7442 :
7443 : // We don't need to copy over the enumeration index.
7444 4786 : dictionary->ValueAtPut(entry, *value);
7445 2345 : if (Shape::kEntrySize == 3) dictionary->DetailsAtPut(isolate, entry, details);
7446 2393 : return dictionary;
7447 : }
7448 :
7449 : template <typename Derived, typename Shape>
7450 : Handle<Derived>
7451 4450929 : BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
7452 : Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
7453 : PropertyDetails details, int* entry_out) {
7454 : // Insert element at empty or deleted entry
7455 : return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
7456 12598900 : details, entry_out);
7457 : }
7458 :
7459 : // GCC workaround: Explicitly instantiate template method for NameDictionary
7460 : // to avoid "undefined reference" issues during linking.
7461 : template Handle<NameDictionary>
7462 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::
7463 : AddNoUpdateNextEnumerationIndex(Isolate* isolate, Handle<NameDictionary>,
7464 : Handle<Name>, Handle<Object>,
7465 : PropertyDetails, int*);
7466 :
7467 : template <typename Derived, typename Shape>
7468 12563172 : Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
7469 : Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
7470 : PropertyDetails details, int* entry_out) {
7471 : // Insert element at empty or deleted entry
7472 : DCHECK_EQ(0, details.dictionary_index());
7473 : // Assign an enumeration index to the property and update
7474 : // SetNextEnumerationIndex.
7475 12563174 : int index = dictionary->NextEnumerationIndex();
7476 : details = details.set_index(index);
7477 4415202 : dictionary = AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
7478 : details, entry_out);
7479 : // Update enumeration index here in order to avoid potential modification of
7480 : // the canonical empty dictionary which lives in read only space.
7481 12563172 : dictionary->SetNextEnumerationIndex(index + 1);
7482 12563172 : return dictionary;
7483 : }
7484 :
7485 : template <typename Derived, typename Shape>
7486 16439207 : Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
7487 : Handle<Derived> dictionary,
7488 : Key key, Handle<Object> value,
7489 : PropertyDetails details,
7490 : int* entry_out) {
7491 16439207 : uint32_t hash = Shape::Hash(isolate, key);
7492 : // Valdate key is absent.
7493 : SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
7494 : // Check whether the dictionary should be extended.
7495 16439209 : dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
7496 :
7497 : // Compute the key object.
7498 : Handle<Object> k = Shape::AsHandle(isolate, key);
7499 :
7500 16439209 : uint32_t entry = dictionary->FindInsertionEntry(hash);
7501 32878416 : dictionary->SetEntry(isolate, entry, *k, *value, details);
7502 : DCHECK(dictionary->KeyAt(entry)->IsNumber() ||
7503 : Shape::Unwrap(dictionary->KeyAt(entry))->IsUniqueName());
7504 16439208 : dictionary->ElementAdded();
7505 16439207 : if (entry_out) *entry_out = entry;
7506 16439207 : return dictionary;
7507 : }
7508 :
7509 : // static
7510 73608 : Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
7511 : Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
7512 : Handle<Object> value) {
7513 73608 : return AtPut(isolate, dictionary, key, value, PropertyDetails::Empty());
7514 : }
7515 :
7516 0 : bool NumberDictionary::HasComplexElements() {
7517 0 : if (!requires_slow_elements()) return false;
7518 0 : ReadOnlyRoots roots = GetReadOnlyRoots();
7519 0 : int capacity = this->Capacity();
7520 0 : for (int i = 0; i < capacity; i++) {
7521 0 : Object k;
7522 0 : if (!this->ToKey(roots, i, &k)) continue;
7523 0 : PropertyDetails details = this->DetailsAt(i);
7524 0 : if (details.kind() == kAccessor) return true;
7525 : PropertyAttributes attr = details.attributes();
7526 0 : if (attr & ALL_ATTRIBUTES_MASK) return true;
7527 : }
7528 : return false;
7529 : }
7530 :
7531 1480766 : void NumberDictionary::UpdateMaxNumberKey(uint32_t key,
7532 : Handle<JSObject> dictionary_holder) {
7533 : DisallowHeapAllocation no_allocation;
7534 : // If the dictionary requires slow elements an element has already
7535 : // been added at a high index.
7536 1528293 : if (requires_slow_elements()) return;
7537 : // Check if this index is high enough that we should require slow
7538 : // elements.
7539 1434944 : if (key > kRequiresSlowElementsLimit) {
7540 1705 : if (!dictionary_holder.is_null()) {
7541 1453 : dictionary_holder->RequireSlowElements(*this);
7542 : }
7543 : set_requires_slow_elements();
7544 : return;
7545 : }
7546 : // Update max key value.
7547 1433239 : Object max_index_object = get(kMaxNumberKeyIndex);
7548 1433239 : if (!max_index_object->IsSmi() || max_number_key() < key) {
7549 : FixedArray::set(kMaxNumberKeyIndex,
7550 1146096 : Smi::FromInt(key << kRequiresSlowElementsTagSize));
7551 : }
7552 : }
7553 :
7554 405924 : Handle<NumberDictionary> NumberDictionary::Set(
7555 : Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
7556 : Handle<Object> value, Handle<JSObject> dictionary_holder,
7557 : PropertyDetails details) {
7558 405924 : dictionary->UpdateMaxNumberKey(key, dictionary_holder);
7559 405924 : return AtPut(isolate, dictionary, key, value, details);
7560 : }
7561 :
7562 36 : void NumberDictionary::CopyValuesTo(FixedArray elements) {
7563 36 : ReadOnlyRoots roots = GetReadOnlyRoots();
7564 : int pos = 0;
7565 36 : int capacity = this->Capacity();
7566 : DisallowHeapAllocation no_gc;
7567 : WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
7568 612 : for (int i = 0; i < capacity; i++) {
7569 576 : Object k;
7570 576 : if (this->ToKey(roots, i, &k)) {
7571 270 : elements->set(pos++, this->ValueAt(i), mode);
7572 : }
7573 : }
7574 : DCHECK_EQ(pos, elements->length());
7575 36 : }
7576 :
7577 : template <typename Derived, typename Shape>
7578 43083 : int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
7579 43083 : ReadOnlyRoots roots = this->GetReadOnlyRoots();
7580 43083 : int capacity = this->Capacity();
7581 : int result = 0;
7582 14588031 : for (int i = 0; i < capacity; i++) {
7583 14544948 : Object k;
7584 22122018 : if (!this->ToKey(roots, i, &k)) continue;
7585 7004380 : if (k->FilterKey(ENUMERABLE_STRINGS)) continue;
7586 6967878 : PropertyDetails details = this->DetailsAt(i);
7587 : PropertyAttributes attr = details.attributes();
7588 6967878 : if ((attr & ONLY_ENUMERABLE) == 0) result++;
7589 : }
7590 43083 : return result;
7591 : }
7592 :
7593 :
7594 : template <typename Dictionary>
7595 : struct EnumIndexComparator {
7596 490590 : explicit EnumIndexComparator(Dictionary dict) : dict(dict) {}
7597 120248396 : bool operator()(Tagged_t a, Tagged_t b) {
7598 : // TODO(ishell): revisit the code below
7599 : STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
7600 120248396 : PropertyDetails da(dict->DetailsAt(Smi(a).value()));
7601 120248366 : PropertyDetails db(dict->DetailsAt(Smi(b).value()));
7602 120248384 : return da.dictionary_index() < db.dictionary_index();
7603 : }
7604 : Dictionary dict;
7605 : };
7606 :
7607 : template <typename Derived, typename Shape>
7608 42867 : void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
7609 : Isolate* isolate, Handle<Derived> dictionary, Handle<FixedArray> storage,
7610 : KeyCollectionMode mode, KeyAccumulator* accumulator) {
7611 : DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
7612 : int length = storage->length();
7613 42867 : int capacity = dictionary->Capacity();
7614 : int properties = 0;
7615 : ReadOnlyRoots roots(isolate);
7616 14474977 : for (int i = 0; i < capacity; i++) {
7617 14474538 : Object key;
7618 24119682 : if (!dictionary->ToKey(roots, i, &key)) continue;
7619 : bool is_shadowing_key = false;
7620 7003039 : if (key->IsSymbol()) continue;
7621 6966583 : PropertyDetails details = dictionary->DetailsAt(i);
7622 6966583 : if (details.IsDontEnum()) {
7623 2137189 : if (mode == KeyCollectionMode::kIncludePrototypes) {
7624 : is_shadowing_key = true;
7625 : } else {
7626 : continue;
7627 : }
7628 : }
7629 4832660 : if (is_shadowing_key) {
7630 3266 : accumulator->AddShadowingKey(key);
7631 3266 : continue;
7632 : } else {
7633 : storage->set(properties, Smi::FromInt(i));
7634 : }
7635 4829394 : properties++;
7636 4829394 : if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
7637 : }
7638 :
7639 42867 : CHECK_EQ(length, properties);
7640 : DisallowHeapAllocation no_gc;
7641 42867 : Derived raw_dictionary = *dictionary;
7642 42867 : FixedArray raw_storage = *storage;
7643 : EnumIndexComparator<Derived> cmp(raw_dictionary);
7644 : // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
7645 : // store operations that are safe for concurrent marking.
7646 : AtomicSlot start(storage->GetFirstElementAddress());
7647 42867 : std::sort(start, start + length, cmp);
7648 4872261 : for (int i = 0; i < length; i++) {
7649 4829394 : int index = Smi::ToInt(raw_storage->get(i));
7650 4829394 : raw_storage->set(i, raw_dictionary->NameAt(index));
7651 : }
7652 42867 : }
7653 :
7654 : template <typename Derived, typename Shape>
7655 424342 : Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
7656 : Isolate* isolate, Handle<Derived> dictionary) {
7657 424343 : int capacity = dictionary->Capacity();
7658 424343 : int length = dictionary->NumberOfElements();
7659 424343 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
7660 : ReadOnlyRoots roots(isolate);
7661 : int array_size = 0;
7662 : {
7663 : DisallowHeapAllocation no_gc;
7664 424342 : Derived raw_dictionary = *dictionary;
7665 15974089 : for (int i = 0; i < capacity; i++) {
7666 15549745 : Object k;
7667 24488800 : if (!raw_dictionary->ToKey(roots, i, &k)) continue;
7668 6610726 : array->set(array_size++, Smi::FromInt(i));
7669 : }
7670 :
7671 : DCHECK_EQ(array_size, length);
7672 :
7673 : EnumIndexComparator<Derived> cmp(raw_dictionary);
7674 : // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
7675 : // store operations that are safe for concurrent marking.
7676 : AtomicSlot start(array->GetFirstElementAddress());
7677 424344 : std::sort(start, start + array_size, cmp);
7678 : }
7679 424343 : return FixedArray::ShrinkOrEmpty(isolate, array, array_size);
7680 : }
7681 :
7682 : template <typename Derived, typename Shape>
7683 23379 : void BaseNameDictionary<Derived, Shape>::CollectKeysTo(
7684 : Handle<Derived> dictionary, KeyAccumulator* keys) {
7685 : Isolate* isolate = keys->isolate();
7686 : ReadOnlyRoots roots(isolate);
7687 23379 : int capacity = dictionary->Capacity();
7688 : Handle<FixedArray> array =
7689 23379 : isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
7690 : int array_size = 0;
7691 : PropertyFilter filter = keys->filter();
7692 : {
7693 : DisallowHeapAllocation no_gc;
7694 23379 : Derived raw_dictionary = *dictionary;
7695 6278323 : for (int i = 0; i < capacity; i++) {
7696 6254944 : Object k;
7697 9598490 : if (!raw_dictionary->ToKey(roots, i, &k)) continue;
7698 2926853 : if (k->FilterKey(filter)) continue;
7699 2912355 : PropertyDetails details = raw_dictionary->DetailsAt(i);
7700 2912355 : if ((details.attributes() & filter) != 0) {
7701 588 : keys->AddShadowingKey(k);
7702 588 : continue;
7703 : }
7704 2911767 : if (filter & ONLY_ALL_CAN_READ) {
7705 754 : if (details.kind() != kAccessor) continue;
7706 26 : Object accessors = raw_dictionary->ValueAt(i);
7707 26 : if (!accessors->IsAccessorInfo()) continue;
7708 26 : if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
7709 : }
7710 2911398 : array->set(array_size++, Smi::FromInt(i));
7711 : }
7712 :
7713 : EnumIndexComparator<Derived> cmp(raw_dictionary);
7714 : // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
7715 : // store operations that are safe for concurrent marking.
7716 : AtomicSlot start(array->GetFirstElementAddress());
7717 23379 : std::sort(start, start + array_size, cmp);
7718 : }
7719 :
7720 : bool has_seen_symbol = false;
7721 2934777 : for (int i = 0; i < array_size; i++) {
7722 2911398 : int index = Smi::ToInt(array->get(i));
7723 5766393 : Object key = dictionary->NameAt(index);
7724 2911398 : if (key->IsSymbol()) {
7725 : has_seen_symbol = true;
7726 18211 : continue;
7727 : }
7728 2893187 : keys->AddKey(key, DO_NOT_CONVERT);
7729 : }
7730 23379 : if (has_seen_symbol) {
7731 2304096 : for (int i = 0; i < array_size; i++) {
7732 2304096 : int index = Smi::ToInt(array->get(i));
7733 4607693 : Object key = dictionary->NameAt(index);
7734 4589981 : if (!key->IsSymbol()) continue;
7735 18211 : keys->AddKey(key, DO_NOT_CONVERT);
7736 : }
7737 : }
7738 23379 : }
7739 :
7740 : // Backwards lookup (slow).
7741 : template <typename Derived, typename Shape>
7742 57 : Object Dictionary<Derived, Shape>::SlowReverseLookup(Object value) {
7743 57 : Derived dictionary = Derived::cast(*this);
7744 57 : ReadOnlyRoots roots = dictionary->GetReadOnlyRoots();
7745 57 : int capacity = dictionary->Capacity();
7746 14649 : for (int i = 0; i < capacity; i++) {
7747 14592 : Object k;
7748 21304 : if (!dictionary->ToKey(roots, i, &k)) continue;
7749 0 : Object e = dictionary->ValueAt(i);
7750 7880 : if (e == value) return k;
7751 : }
7752 57 : return roots.undefined_value();
7753 : }
7754 :
7755 : template <typename Derived, typename Shape>
7756 352 : void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
7757 : Handle<Derived> table) {
7758 : int length = table->length();
7759 49144 : for (int i = Derived::EntryToIndex(0); i < length; i++) {
7760 48792 : table->set_the_hole(i);
7761 : }
7762 352 : }
7763 :
7764 : template <typename Derived, typename Shape>
7765 36940 : Object ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
7766 : Handle<Object> key,
7767 : int32_t hash) {
7768 : DisallowHeapAllocation no_gc;
7769 : DCHECK(this->IsKey(roots, *key));
7770 :
7771 36940 : int entry = this->FindEntry(roots, key, hash);
7772 37834 : if (entry == kNotFound) return roots.the_hole_value();
7773 36046 : return this->get(Derived::EntryToIndex(entry) + 1);
7774 : }
7775 :
7776 : template <typename Derived, typename Shape>
7777 37601 : Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key) {
7778 : DisallowHeapAllocation no_gc;
7779 :
7780 37601 : ReadOnlyRoots roots = this->GetReadOnlyRoots();
7781 : DCHECK(this->IsKey(roots, *key));
7782 :
7783 : // If the object does not have an identity hash, it was never used as a key.
7784 37601 : Object hash = key->GetHash();
7785 37601 : if (hash->IsUndefined(roots)) {
7786 668 : return roots.the_hole_value();
7787 : }
7788 36933 : return Lookup(roots, key, Smi::ToInt(hash));
7789 : }
7790 :
7791 : template <typename Derived, typename Shape>
7792 0 : Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
7793 : int32_t hash) {
7794 0 : return Lookup(this->GetReadOnlyRoots(), key, hash);
7795 : }
7796 :
7797 : template <typename Derived, typename Shape>
7798 242 : Object ObjectHashTableBase<Derived, Shape>::ValueAt(int entry) {
7799 242 : return this->get(EntryToValueIndex(entry));
7800 : }
7801 :
7802 : template <typename Derived, typename Shape>
7803 32730 : Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Handle<Derived> table,
7804 : Handle<Object> key,
7805 : Handle<Object> value) {
7806 : Isolate* isolate = Heap::FromWritableHeapObject(*table)->isolate();
7807 : DCHECK(table->IsKey(ReadOnlyRoots(isolate), *key));
7808 : DCHECK(!value->IsTheHole(ReadOnlyRoots(isolate)));
7809 :
7810 : // Make sure the key object has an identity hash code.
7811 65460 : int32_t hash = key->GetOrCreateHash(isolate)->value();
7812 :
7813 : return ObjectHashTableBase<Derived, Shape>::Put(isolate, table, key, value,
7814 32730 : hash);
7815 : }
7816 :
7817 : template <typename Derived, typename Shape>
7818 33712 : Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
7819 : Handle<Derived> table,
7820 : Handle<Object> key,
7821 : Handle<Object> value,
7822 : int32_t hash) {
7823 : ReadOnlyRoots roots(isolate);
7824 : DCHECK(table->IsKey(roots, *key));
7825 : DCHECK(!value->IsTheHole(roots));
7826 :
7827 33712 : int entry = table->FindEntry(roots, key, hash);
7828 :
7829 : // Key is already in table, just overwrite value.
7830 33712 : if (entry != kNotFound) {
7831 970 : table->set(Derived::EntryToIndex(entry) + 1, *value);
7832 485 : return table;
7833 : }
7834 :
7835 : // Rehash if more than 33% of the entries are deleted entries.
7836 : // TODO(jochen): Consider to shrink the fixed array in place.
7837 66454 : if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
7838 5 : table->Rehash(isolate);
7839 : }
7840 : // If we're out of luck, we didn't get a GC recently, and so rehashing
7841 : // isn't enough to avoid a crash.
7842 33227 : if (!table->HasSufficientCapacityToAdd(1)) {
7843 452 : int nof = table->NumberOfElements() + 1;
7844 452 : int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
7845 452 : if (capacity > ObjectHashTable::kMaxCapacity) {
7846 0 : for (size_t i = 0; i < 2; ++i) {
7847 0 : isolate->heap()->CollectAllGarbage(
7848 0 : Heap::kNoGCFlags, GarbageCollectionReason::kFullHashtable);
7849 : }
7850 0 : table->Rehash(isolate);
7851 : }
7852 : }
7853 :
7854 : // Check whether the hash table should be extended.
7855 33227 : table = Derived::EnsureCapacity(isolate, table, 1);
7856 99681 : table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
7857 33227 : return table;
7858 : }
7859 :
7860 : template <typename Derived, typename Shape>
7861 184 : Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
7862 : Isolate* isolate, Handle<Derived> table, Handle<Object> key,
7863 : bool* was_present) {
7864 : DCHECK(table->IsKey(table->GetReadOnlyRoots(), *key));
7865 :
7866 184 : Object hash = key->GetHash();
7867 184 : if (hash->IsUndefined()) {
7868 0 : *was_present = false;
7869 0 : return table;
7870 : }
7871 :
7872 184 : return Remove(isolate, table, key, was_present, Smi::ToInt(hash));
7873 : }
7874 :
7875 : template <typename Derived, typename Shape>
7876 184 : Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
7877 : Isolate* isolate, Handle<Derived> table, Handle<Object> key,
7878 : bool* was_present, int32_t hash) {
7879 184 : ReadOnlyRoots roots = table->GetReadOnlyRoots();
7880 : DCHECK(table->IsKey(roots, *key));
7881 :
7882 184 : int entry = table->FindEntry(roots, key, hash);
7883 184 : if (entry == kNotFound) {
7884 46 : *was_present = false;
7885 46 : return table;
7886 : }
7887 :
7888 138 : *was_present = true;
7889 138 : table->RemoveEntry(entry);
7890 138 : return Derived::Shrink(isolate, table);
7891 : }
7892 :
7893 : template <typename Derived, typename Shape>
7894 33227 : void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object key,
7895 : Object value) {
7896 33227 : this->set(Derived::EntryToIndex(entry), key);
7897 33227 : this->set(Derived::EntryToIndex(entry) + 1, value);
7898 33227 : this->ElementAdded();
7899 33227 : }
7900 :
7901 : template <typename Derived, typename Shape>
7902 226 : void ObjectHashTableBase<Derived, Shape>::RemoveEntry(int entry) {
7903 226 : this->set_the_hole(Derived::EntryToIndex(entry));
7904 226 : this->set_the_hole(Derived::EntryToIndex(entry) + 1);
7905 226 : this->ElementRemoved();
7906 226 : }
7907 :
7908 :
7909 79596 : void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
7910 79596 : Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
7911 159192 : set->set_table(*table);
7912 79596 : }
7913 :
7914 42 : void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) {
7915 : Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
7916 42 : table = OrderedHashSet::Clear(isolate, table);
7917 84 : set->set_table(*table);
7918 42 : }
7919 :
7920 :
7921 13 : void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
7922 13 : Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
7923 26 : map->set_table(*table);
7924 13 : }
7925 :
7926 212 : void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
7927 : Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
7928 212 : table = OrderedHashMap::Clear(isolate, table);
7929 424 : map->set_table(*table);
7930 212 : }
7931 :
7932 :
7933 50099 : void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
7934 : Isolate* isolate) {
7935 50099 : Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);
7936 100198 : weak_collection->set_table(*table);
7937 50099 : }
7938 :
7939 :
7940 982 : void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
7941 : Handle<Object> key, Handle<Object> value,
7942 : int32_t hash) {
7943 : DCHECK(key->IsJSReceiver() || key->IsSymbol());
7944 : Handle<EphemeronHashTable> table(
7945 : EphemeronHashTable::cast(weak_collection->table()),
7946 : weak_collection->GetIsolate());
7947 : DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
7948 : Handle<EphemeronHashTable> new_table = EphemeronHashTable::Put(
7949 982 : weak_collection->GetIsolate(), table, key, value, hash);
7950 1964 : weak_collection->set_table(*new_table);
7951 982 : if (*table != *new_table) {
7952 : // Zap the old table since we didn't record slots for its elements.
7953 352 : EphemeronHashTable::FillEntriesWithHoles(table);
7954 : }
7955 982 : }
7956 :
7957 :
7958 0 : bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
7959 : Handle<Object> key, int32_t hash) {
7960 : DCHECK(key->IsJSReceiver() || key->IsSymbol());
7961 : Handle<EphemeronHashTable> table(
7962 : EphemeronHashTable::cast(weak_collection->table()),
7963 : weak_collection->GetIsolate());
7964 : DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
7965 0 : bool was_present = false;
7966 : Handle<EphemeronHashTable> new_table = EphemeronHashTable::Remove(
7967 0 : weak_collection->GetIsolate(), table, key, &was_present, hash);
7968 0 : weak_collection->set_table(*new_table);
7969 0 : if (*table != *new_table) {
7970 : // Zap the old table since we didn't record slots for its elements.
7971 0 : EphemeronHashTable::FillEntriesWithHoles(table);
7972 : }
7973 0 : return was_present;
7974 : }
7975 :
7976 98 : Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
7977 : int max_entries) {
7978 : Isolate* isolate = holder->GetIsolate();
7979 : Handle<EphemeronHashTable> table(EphemeronHashTable::cast(holder->table()),
7980 : isolate);
7981 98 : if (max_entries == 0 || max_entries > table->NumberOfElements()) {
7982 98 : max_entries = table->NumberOfElements();
7983 : }
7984 196 : int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
7985 : Handle<FixedArray> entries =
7986 98 : isolate->factory()->NewFixedArray(max_entries * values_per_entry);
7987 : // Recompute max_values because GC could have removed elements from the table.
7988 98 : if (max_entries > table->NumberOfElements()) {
7989 0 : max_entries = table->NumberOfElements();
7990 : }
7991 :
7992 : {
7993 : DisallowHeapAllocation no_gc;
7994 : ReadOnlyRoots roots = ReadOnlyRoots(isolate);
7995 : int count = 0;
7996 484 : for (int i = 0;
7997 383 : count / values_per_entry < max_entries && i < table->Capacity(); i++) {
7998 95 : Object key;
7999 95 : if (table->ToKey(roots, i, &key)) {
8000 100 : entries->set(count++, key);
8001 50 : if (values_per_entry > 1) {
8002 25 : Object value = table->Lookup(handle(key, isolate));
8003 50 : entries->set(count++, value);
8004 : }
8005 : }
8006 : }
8007 : DCHECK_EQ(max_entries * values_per_entry, count);
8008 : }
8009 98 : return isolate->factory()->NewJSArrayWithElements(entries);
8010 : }
8011 :
8012 :
8013 19994 : Handle<PropertyCell> PropertyCell::InvalidateEntry(
8014 : Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry) {
8015 : // Swap with a copy.
8016 39988 : Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
8017 39988 : Handle<Name> name(cell->name(), isolate);
8018 19994 : Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(name);
8019 19994 : new_cell->set_value(cell->value());
8020 39988 : dictionary->ValueAtPut(entry, *new_cell);
8021 39988 : bool is_the_hole = cell->value()->IsTheHole(isolate);
8022 : // Cell is officially mutable henceforth.
8023 19994 : PropertyDetails details = cell->property_details();
8024 : details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
8025 19994 : : PropertyCellType::kMutable);
8026 39988 : new_cell->set_property_details(details);
8027 : // Old cell is ready for invalidation.
8028 19994 : if (is_the_hole) {
8029 16594 : cell->set_value(ReadOnlyRoots(isolate).undefined_value());
8030 : } else {
8031 23394 : cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
8032 : }
8033 : details = details.set_cell_type(PropertyCellType::kInvalidated);
8034 39988 : cell->set_property_details(details);
8035 39988 : cell->dependent_code()->DeoptimizeDependentCodeGroup(
8036 19994 : isolate, DependentCode::kPropertyCellChangedGroup);
8037 19994 : return new_cell;
8038 : }
8039 :
8040 :
8041 0 : PropertyCellConstantType PropertyCell::GetConstantType() {
8042 0 : if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
8043 0 : return PropertyCellConstantType::kStableMap;
8044 : }
8045 :
8046 :
8047 1087128 : static bool RemainsConstantType(Handle<PropertyCell> cell,
8048 : Handle<Object> value) {
8049 : // TODO(dcarney): double->smi and smi->double transition from kConstant
8050 3982882 : if (cell->value()->IsSmi() && value->IsSmi()) {
8051 : return true;
8052 734674 : } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
8053 : return HeapObject::cast(cell->value())->map() ==
8054 355593 : HeapObject::cast(*value)->map() &&
8055 355593 : HeapObject::cast(*value)->map()->is_stable();
8056 : }
8057 : return false;
8058 : }
8059 :
8060 12737278 : PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
8061 : Handle<PropertyCell> cell,
8062 : Handle<Object> value,
8063 : PropertyDetails details) {
8064 : PropertyCellType type = details.cell_type();
8065 : DCHECK(!value->IsTheHole(isolate));
8066 25474558 : if (cell->value()->IsTheHole(isolate)) {
8067 8157774 : switch (type) {
8068 : // Only allow a cell to transition once into constant state.
8069 : case PropertyCellType::kUninitialized:
8070 16315548 : if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
8071 6453277 : return PropertyCellType::kConstant;
8072 : case PropertyCellType::kInvalidated:
8073 : return PropertyCellType::kMutable;
8074 : default:
8075 0 : UNREACHABLE();
8076 : }
8077 : }
8078 4579505 : switch (type) {
8079 : case PropertyCellType::kUndefined:
8080 : return PropertyCellType::kConstant;
8081 : case PropertyCellType::kConstant:
8082 1619409 : if (*value == cell->value()) return PropertyCellType::kConstant;
8083 : V8_FALLTHROUGH;
8084 : case PropertyCellType::kConstantType:
8085 1087128 : if (RemainsConstantType(cell, value)) {
8086 : return PropertyCellType::kConstantType;
8087 : }
8088 : V8_FALLTHROUGH;
8089 : case PropertyCellType::kMutable:
8090 : return PropertyCellType::kMutable;
8091 : }
8092 0 : UNREACHABLE();
8093 : }
8094 :
8095 4587321 : Handle<PropertyCell> PropertyCell::PrepareForValue(
8096 : Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
8097 : Handle<Object> value, PropertyDetails details) {
8098 : DCHECK(!value->IsTheHole(isolate));
8099 9174642 : Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
8100 4587321 : const PropertyDetails original_details = cell->property_details();
8101 : // Data accesses could be cached in ics or optimized code.
8102 : bool invalidate =
8103 13753275 : (original_details.kind() == kData && details.kind() == kAccessor) ||
8104 4579238 : (!original_details.IsReadOnly() && details.IsReadOnly());
8105 : int index;
8106 : PropertyCellType old_type = original_details.cell_type();
8107 : // Preserve the enumeration index unless the property was deleted or never
8108 : // initialized.
8109 9174642 : if (cell->value()->IsTheHole(isolate)) {
8110 7816 : index = dictionary->NextEnumerationIndex();
8111 7816 : dictionary->SetNextEnumerationIndex(index + 1);
8112 : } else {
8113 : index = original_details.dictionary_index();
8114 : }
8115 : DCHECK_LT(0, index);
8116 : details = details.set_index(index);
8117 :
8118 : PropertyCellType new_type =
8119 4587321 : UpdatedType(isolate, cell, value, original_details);
8120 4587321 : if (invalidate) {
8121 8143 : cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
8122 : }
8123 :
8124 : // Install new property details.
8125 : details = details.set_cell_type(new_type);
8126 9174642 : cell->set_property_details(details);
8127 :
8128 4587321 : if (new_type == PropertyCellType::kConstant ||
8129 : new_type == PropertyCellType::kConstantType) {
8130 : // Store the value now to ensure that the cell contains the constant or
8131 : // type information. Otherwise subsequent store operation will turn
8132 : // the cell to mutable.
8133 4226842 : cell->set_value(*value);
8134 : }
8135 :
8136 : // Deopt when transitioning from a constant type.
8137 7549665 : if (!invalidate && (old_type != new_type ||
8138 : original_details.IsReadOnly() != details.IsReadOnly())) {
8139 3233686 : cell->dependent_code()->DeoptimizeDependentCodeGroup(
8140 1616843 : isolate, DependentCode::kPropertyCellChangedGroup);
8141 : }
8142 4587321 : return cell;
8143 : }
8144 :
8145 :
8146 : // static
8147 4825 : void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
8148 : Handle<PropertyCell> cell,
8149 : Handle<Object> new_value) {
8150 4825 : if (cell->value() != *new_value) {
8151 4825 : cell->set_value(*new_value);
8152 9650 : cell->dependent_code()->DeoptimizeDependentCodeGroup(
8153 4825 : isolate, DependentCode::kPropertyCellChangedGroup);
8154 : }
8155 4825 : }
8156 :
8157 1430 : int JSGeneratorObject::source_position() const {
8158 1430 : CHECK(is_suspended());
8159 : DCHECK(function()->shared()->HasBytecodeArray());
8160 : DCHECK(function()->shared()->GetBytecodeArray()->HasSourcePositionTable());
8161 :
8162 1430 : int code_offset = Smi::ToInt(input_or_debug_pos());
8163 :
8164 : // The stored bytecode offset is relative to a different base than what
8165 : // is used in the source position table, hence the subtraction.
8166 1430 : code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
8167 : AbstractCode code =
8168 2860 : AbstractCode::cast(function()->shared()->GetBytecodeArray());
8169 1430 : return code->SourcePosition(code_offset);
8170 : }
8171 :
8172 : // static
8173 4705 : AccessCheckInfo AccessCheckInfo::Get(Isolate* isolate,
8174 : Handle<JSObject> receiver) {
8175 : DisallowHeapAllocation no_gc;
8176 : DCHECK(receiver->map()->is_access_check_needed());
8177 4705 : Object maybe_constructor = receiver->map()->GetConstructor();
8178 4705 : if (maybe_constructor->IsFunctionTemplateInfo()) {
8179 : Object data_obj =
8180 145 : FunctionTemplateInfo::cast(maybe_constructor)->GetAccessCheckInfo();
8181 145 : if (data_obj->IsUndefined(isolate)) return AccessCheckInfo();
8182 : return AccessCheckInfo::cast(data_obj);
8183 : }
8184 : // Might happen for a detached context.
8185 4560 : if (!maybe_constructor->IsJSFunction()) return AccessCheckInfo();
8186 4535 : JSFunction constructor = JSFunction::cast(maybe_constructor);
8187 : // Might happen for the debug context.
8188 4535 : if (!constructor->shared()->IsApiFunction()) return AccessCheckInfo();
8189 :
8190 : Object data_obj =
8191 4117 : constructor->shared()->get_api_func_data()->GetAccessCheckInfo();
8192 4117 : if (data_obj->IsUndefined(isolate)) return AccessCheckInfo();
8193 :
8194 : return AccessCheckInfo::cast(data_obj);
8195 : }
8196 :
8197 :
8198 334447 : MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
8199 : Isolate* isolate, Handle<Object> getter) {
8200 668896 : if (getter->IsFunctionTemplateInfo()) {
8201 : Handle<FunctionTemplateInfo> fti =
8202 101244 : Handle<FunctionTemplateInfo>::cast(getter);
8203 : // Check if the accessor uses a cached property.
8204 202488 : if (!fti->cached_property_name()->IsTheHole(isolate)) {
8205 84 : return handle(Name::cast(fti->cached_property_name()), isolate);
8206 : }
8207 : }
8208 334364 : return MaybeHandle<Name>();
8209 : }
8210 :
8211 4459145 : Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
8212 : DisallowHeapAllocation no_allocation;
8213 4459145 : DisallowJavascriptExecution no_js(isolate);
8214 :
8215 4459145 : int x_value = Smi::ToInt(x);
8216 4459145 : int y_value = Smi::ToInt(y);
8217 :
8218 : // If the integers are equal so are the string representations.
8219 4459145 : if (x_value == y_value) return Smi::FromInt(0).ptr();
8220 :
8221 : // If one of the integers is zero the normal integer order is the
8222 : // same as the lexicographic order of the string representations.
8223 4455123 : if (x_value == 0 || y_value == 0) {
8224 7755 : return Smi::FromInt(x_value < y_value ? -1 : 1).ptr();
8225 : }
8226 :
8227 : // If only one of the integers is negative the negative number is
8228 : // smallest because the char code of '-' is less than the char code
8229 : // of any digit. Otherwise, we make both values positive.
8230 :
8231 : // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
8232 : // architectures using 32-bit Smis.
8233 4447368 : uint32_t x_scaled = x_value;
8234 4447368 : uint32_t y_scaled = y_value;
8235 4447368 : if (x_value < 0) {
8236 1315995 : if (y_value >= 0) {
8237 : return Smi::FromInt(-1).ptr();
8238 : } else {
8239 657129 : y_scaled = base::NegateWithWraparound(y_value);
8240 : }
8241 657129 : x_scaled = base::NegateWithWraparound(x_value);
8242 3131373 : } else if (y_value < 0) {
8243 : return Smi::FromInt(1).ptr();
8244 : }
8245 :
8246 : // clang-format off
8247 : static const uint32_t kPowersOf10[] = {
8248 : 1, 10, 100, 1000,
8249 : 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000,
8250 : 100 * 1000 * 1000, 1000 * 1000 * 1000};
8251 : // clang-format on
8252 :
8253 : // If the integers have the same number of decimal digits they can be
8254 : // compared directly as the numeric order is the same as the
8255 : // lexicographic order. If one integer has fewer digits, it is scaled
8256 : // by some power of 10 to have the same number of digits as the longer
8257 : // integer. If the scaled integers are equal it means the shorter
8258 : // integer comes first in the lexicographic order.
8259 :
8260 : // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
8261 3129648 : int x_log2 = 31 - base::bits::CountLeadingZeros(x_scaled);
8262 3129648 : int x_log10 = ((x_log2 + 1) * 1233) >> 12;
8263 3129648 : x_log10 -= x_scaled < kPowersOf10[x_log10];
8264 :
8265 3129648 : int y_log2 = 31 - base::bits::CountLeadingZeros(y_scaled);
8266 3129648 : int y_log10 = ((y_log2 + 1) * 1233) >> 12;
8267 3129648 : y_log10 -= y_scaled < kPowersOf10[y_log10];
8268 :
8269 : int tie = 0;
8270 :
8271 3129648 : if (x_log10 < y_log10) {
8272 : // X has fewer digits. We would like to simply scale up X but that
8273 : // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
8274 : // be scaled up to 9_000_000_000. So we scale up by the next
8275 : // smallest power and scale down Y to drop one digit. It is OK to
8276 : // drop one digit from the longer integer since the final digit is
8277 : // past the length of the shorter integer.
8278 585100 : x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
8279 585100 : y_scaled /= 10;
8280 : tie = -1;
8281 2544548 : } else if (y_log10 < x_log10) {
8282 1447453 : y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
8283 1447453 : x_scaled /= 10;
8284 : tie = 1;
8285 : }
8286 :
8287 3129648 : if (x_scaled < y_scaled) return Smi::FromInt(-1).ptr();
8288 1908076 : if (x_scaled > y_scaled) return Smi::FromInt(1).ptr();
8289 4459145 : return Smi::FromInt(tie).ptr();
8290 : }
8291 :
8292 : // Force instantiation of template instances class.
8293 : // Please note this list is compiler dependent.
8294 : // Keep this at the end of this file
8295 :
8296 : template class HashTable<StringTable, StringTableShape>;
8297 :
8298 : template class HashTable<CompilationCacheTable, CompilationCacheShape>;
8299 :
8300 : template class HashTable<ObjectHashTable, ObjectHashTableShape>;
8301 :
8302 : template class HashTable<EphemeronHashTable, EphemeronHashTableShape>;
8303 :
8304 : template class ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>;
8305 :
8306 : template class ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
8307 :
8308 : template class Dictionary<NameDictionary, NameDictionaryShape>;
8309 :
8310 : template class Dictionary<GlobalDictionary, GlobalDictionaryShape>;
8311 :
8312 : template class EXPORT_TEMPLATE_DEFINE(
8313 : V8_EXPORT_PRIVATE) HashTable<NumberDictionary, NumberDictionaryShape>;
8314 :
8315 : template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
8316 : Dictionary<NumberDictionary, NumberDictionaryShape>;
8317 :
8318 : template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
8319 : HashTable<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
8320 :
8321 : template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
8322 : Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
8323 :
8324 : template Handle<NameDictionary>
8325 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::New(
8326 : Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
8327 :
8328 : template Handle<GlobalDictionary>
8329 : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::New(
8330 : Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
8331 :
8332 : template Handle<NameDictionary>
8333 : HashTable<NameDictionary, NameDictionaryShape>::New(Isolate*, int,
8334 : PretenureFlag,
8335 : MinimumCapacity);
8336 :
8337 : template Handle<ObjectHashSet>
8338 : HashTable<ObjectHashSet, ObjectHashSetShape>::New(Isolate*, int n,
8339 : PretenureFlag,
8340 : MinimumCapacity);
8341 :
8342 : template Handle<NameDictionary>
8343 : HashTable<NameDictionary, NameDictionaryShape>::Shrink(Isolate* isolate,
8344 : Handle<NameDictionary>,
8345 : int additionalCapacity);
8346 :
8347 : template Handle<NameDictionary>
8348 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::Add(
8349 : Isolate* isolate, Handle<NameDictionary>, Handle<Name>, Handle<Object>,
8350 : PropertyDetails, int*);
8351 :
8352 : template Handle<GlobalDictionary>
8353 : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::Add(
8354 : Isolate* isolate, Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
8355 : PropertyDetails, int*);
8356 :
8357 : template void HashTable<GlobalDictionary, GlobalDictionaryShape>::Rehash(
8358 : Isolate* isolate);
8359 :
8360 : template Handle<NameDictionary>
8361 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::EnsureCapacity(
8362 : Isolate* isolate, Handle<NameDictionary>, int);
8363 :
8364 : template void
8365 : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CopyEnumKeysTo(
8366 : Isolate* isolate, Handle<GlobalDictionary> dictionary,
8367 : Handle<FixedArray> storage, KeyCollectionMode mode,
8368 : KeyAccumulator* accumulator);
8369 :
8370 : template void
8371 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::CopyEnumKeysTo(
8372 : Isolate* isolate, Handle<NameDictionary> dictionary,
8373 : Handle<FixedArray> storage, KeyCollectionMode mode,
8374 : KeyAccumulator* accumulator);
8375 :
8376 : template Handle<FixedArray>
8377 : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::IterationIndices(
8378 : Isolate* isolate, Handle<GlobalDictionary> dictionary);
8379 : template void
8380 : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CollectKeysTo(
8381 : Handle<GlobalDictionary> dictionary, KeyAccumulator* keys);
8382 :
8383 : template Handle<FixedArray>
8384 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::IterationIndices(
8385 : Isolate* isolate, Handle<NameDictionary> dictionary);
8386 : template void
8387 : BaseNameDictionary<NameDictionary, NameDictionaryShape>::CollectKeysTo(
8388 : Handle<NameDictionary> dictionary, KeyAccumulator* keys);
8389 :
8390 252 : void JSFinalizationGroup::Cleanup(
8391 : Handle<JSFinalizationGroup> finalization_group, Isolate* isolate) {
8392 : // It's possible that the cleared_cells list is empty, since
8393 : // FinalizationGroup.unregister() removed all its elements before this task
8394 : // ran. In that case, don't call the cleanup function.
8395 504 : if (!finalization_group->cleared_cells()->IsUndefined(isolate)) {
8396 : // Construct the iterator.
8397 : Handle<JSFinalizationGroupCleanupIterator> iterator;
8398 : {
8399 : Handle<Map> cleanup_iterator_map(
8400 : isolate->native_context()
8401 567 : ->js_finalization_group_cleanup_iterator_map(),
8402 189 : isolate);
8403 : iterator = Handle<JSFinalizationGroupCleanupIterator>::cast(
8404 : isolate->factory()->NewJSObjectFromMap(
8405 : cleanup_iterator_map, NOT_TENURED,
8406 189 : Handle<AllocationSite>::null()));
8407 189 : iterator->set_finalization_group(*finalization_group);
8408 : }
8409 : Handle<Object> cleanup(finalization_group->cleanup(), isolate);
8410 :
8411 189 : v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
8412 : v8::Local<v8::Value> result;
8413 189 : MaybeHandle<Object> exception;
8414 : Handle<Object> args[] = {iterator};
8415 : bool has_pending_exception = !ToLocal<Value>(
8416 : Execution::TryCall(
8417 : isolate, cleanup,
8418 : handle(ReadOnlyRoots(isolate).undefined_value(), isolate), 1, args,
8419 : Execution::MessageHandling::kReport, &exception),
8420 378 : &result);
8421 : // TODO(marja): (spec): What if there's an exception?
8422 189 : USE(has_pending_exception);
8423 :
8424 : // TODO(marja): (spec): Should the iterator be invalidated after the
8425 : // function returns?
8426 : }
8427 252 : }
8428 :
8429 : } // namespace internal
8430 178779 : } // namespace v8
|