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