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