V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
objects.cc
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 <cmath>
8 #include <iomanip>
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/utils/random-number-generator.h"
25 #include "src/bootstrapper.h"
26 #include "src/builtins/builtins.h"
27 #include "src/code-stubs.h"
28 #include "src/compiler.h"
29 #include "src/counters-inl.h"
30 #include "src/counters.h"
31 #include "src/date.h"
32 #include "src/debug/debug.h"
33 #include "src/deoptimizer.h"
34 #include "src/elements.h"
35 #include "src/execution.h"
36 #include "src/field-index-inl.h"
37 #include "src/field-index.h"
38 #include "src/field-type.h"
39 #include "src/frames-inl.h"
40 #include "src/globals.h"
41 #include "src/ic/ic.h"
42 #include "src/identity-map.h"
43 #include "src/interpreter/bytecode-array-iterator.h"
44 #include "src/interpreter/bytecode-decoder.h"
45 #include "src/interpreter/interpreter.h"
46 #include "src/isolate-inl.h"
47 #include "src/keys.h"
48 #include "src/log.h"
49 #include "src/lookup-inl.h"
50 #include "src/macro-assembler.h"
51 #include "src/map-updater.h"
52 #include "src/message-template.h"
53 #include "src/objects-body-descriptors-inl.h"
54 #include "src/objects/api-callbacks.h"
55 #include "src/objects/arguments-inl.h"
56 #include "src/objects/bigint.h"
57 #include "src/objects/code-inl.h"
58 #include "src/objects/compilation-cache-inl.h"
59 #include "src/objects/debug-objects-inl.h"
60 #include "src/objects/frame-array-inl.h"
61 #include "src/objects/hash-table-inl.h"
62 #include "src/objects/js-array-inl.h"
63 #ifdef V8_INTL_SUPPORT
64 #include "src/objects/js-break-iterator.h"
65 #include "src/objects/js-collator.h"
66 #endif // V8_INTL_SUPPORT
67 #include "src/objects/js-collection-inl.h"
68 #ifdef V8_INTL_SUPPORT
69 #include "src/objects/js-date-time-format.h"
70 #endif // V8_INTL_SUPPORT
71 #include "src/objects/js-generator-inl.h"
72 #ifdef V8_INTL_SUPPORT
73 #include "src/objects/js-list-format.h"
74 #include "src/objects/js-locale.h"
75 #include "src/objects/js-number-format.h"
76 #include "src/objects/js-plural-rules.h"
77 #endif // V8_INTL_SUPPORT
78 #include "src/objects/js-regexp-inl.h"
79 #include "src/objects/js-regexp-string-iterator.h"
80 #ifdef V8_INTL_SUPPORT
81 #include "src/objects/js-relative-time-format.h"
82 #include "src/objects/js-segment-iterator.h"
83 #include "src/objects/js-segmenter.h"
84 #endif // V8_INTL_SUPPORT
85 #include "src/objects/js-weak-refs-inl.h"
86 #include "src/objects/literal-objects-inl.h"
87 #include "src/objects/map.h"
88 #include "src/objects/microtask-inl.h"
89 #include "src/objects/module-inl.h"
90 #include "src/objects/promise-inl.h"
91 #include "src/objects/slots-atomic-inl.h"
92 #include "src/objects/stack-frame-info-inl.h"
93 #include "src/parsing/preparsed-scope-data.h"
94 #include "src/property-descriptor.h"
95 #include "src/prototype.h"
96 #include "src/regexp/jsregexp.h"
97 #include "src/safepoint-table.h"
98 #include "src/snapshot/code-serializer.h"
99 #include "src/snapshot/snapshot.h"
100 #include "src/source-position-table.h"
101 #include "src/string-builder-inl.h"
102 #include "src/string-search.h"
103 #include "src/string-stream.h"
104 #include "src/unicode-decoder.h"
105 #include "src/unicode-inl.h"
106 #include "src/utils-inl.h"
107 #include "src/wasm/wasm-engine.h"
108 #include "src/wasm/wasm-objects.h"
109 #include "src/zone/zone.h"
110 
111 #ifdef ENABLE_DISASSEMBLER
112 #include "src/disasm.h"
113 #include "src/disassembler.h"
114 #include "src/eh-frame.h"
115 #endif
116 
117 namespace v8 {
118 namespace internal {
119 
120 bool ComparisonResultToBool(Operation op, ComparisonResult result) {
121  switch (op) {
122  case Operation::kLessThan:
123  return result == ComparisonResult::kLessThan;
124  case Operation::kLessThanOrEqual:
125  return result == ComparisonResult::kLessThan ||
126  result == ComparisonResult::kEqual;
127  case Operation::kGreaterThan:
128  return result == ComparisonResult::kGreaterThan;
129  case Operation::kGreaterThanOrEqual:
130  return result == ComparisonResult::kGreaterThan ||
131  result == ComparisonResult::kEqual;
132  default:
133  break;
134  }
135  UNREACHABLE();
136 }
137 
138 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
139  switch (instance_type) {
140 #define WRITE_TYPE(TYPE) \
141  case TYPE: \
142  return os << #TYPE;
143  INSTANCE_TYPE_LIST(WRITE_TYPE)
144 #undef WRITE_TYPE
145  }
146  UNREACHABLE();
147 }
148 
149 Handle<FieldType> Object::OptimalType(Isolate* isolate,
150  Representation representation) {
151  if (representation.IsNone()) return FieldType::None(isolate);
152  if (FLAG_track_field_types) {
153  if (representation.IsHeapObject() && IsHeapObject()) {
154  // We can track only JavaScript objects with stable maps.
155  Handle<Map> map(HeapObject::cast(this)->map(), isolate);
156  if (map->is_stable() && map->IsJSReceiverMap()) {
157  return FieldType::Class(map, isolate);
158  }
159  }
160  }
161  return FieldType::Any(isolate);
162 }
163 
164 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
165  Handle<Object> object,
166  Handle<Context> native_context,
167  const char* method_name) {
168  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
169  Handle<JSFunction> constructor;
170  if (object->IsSmi()) {
171  constructor = handle(native_context->number_function(), isolate);
172  } else {
173  int constructor_function_index =
174  Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
175  if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
176  if (method_name != nullptr) {
177  THROW_NEW_ERROR(
178  isolate,
179  NewTypeError(
180  MessageTemplate::kCalledOnNullOrUndefined,
181  isolate->factory()->NewStringFromAsciiChecked(method_name)),
182  JSReceiver);
183  }
184  THROW_NEW_ERROR(isolate,
185  NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
186  JSReceiver);
187  }
188  constructor = handle(
189  JSFunction::cast(native_context->get(constructor_function_index)),
190  isolate);
191  }
192  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
193  Handle<JSValue>::cast(result)->set_value(*object);
194  return result;
195 }
196 
197 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
198 // static
199 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
200  Handle<Object> object) {
201  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
202  if (object->IsNullOrUndefined(isolate)) {
203  return isolate->global_proxy();
204  }
205  return Object::ToObject(isolate, object);
206 }
207 
208 // static
209 MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
210  Handle<Object> input,
211  Conversion mode) {
212  while (true) {
213  if (input->IsNumber()) {
214  return input;
215  }
216  if (input->IsString()) {
217  return String::ToNumber(isolate, Handle<String>::cast(input));
218  }
219  if (input->IsOddball()) {
220  return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
221  }
222  if (input->IsSymbol()) {
223  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
224  Object);
225  }
226  if (input->IsBigInt()) {
227  if (mode == Conversion::kToNumeric) return input;
228  DCHECK_EQ(mode, Conversion::kToNumber);
229  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
230  Object);
231  }
232  ASSIGN_RETURN_ON_EXCEPTION(
233  isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
234  ToPrimitiveHint::kNumber),
235  Object);
236  }
237 }
238 
239 // static
240 MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
241  Handle<Object> input) {
242  ASSIGN_RETURN_ON_EXCEPTION(
243  isolate, input,
244  ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
245  if (input->IsSmi()) return input;
246  return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
247 }
248 
249 // static
250 MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
251  Handle<Object> input) {
252  ASSIGN_RETURN_ON_EXCEPTION(
253  isolate, input,
254  ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
255  if (input->IsSmi()) return input;
256  return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
257 }
258 
259 // static
260 MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
261  Handle<Object> input) {
262  ASSIGN_RETURN_ON_EXCEPTION(
263  isolate, input,
264  ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
265  if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
266  return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
267 }
268 
269 // static
270 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
271  Handle<Object> input) {
272  ASSIGN_RETURN_ON_EXCEPTION(
273  isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
274  Name);
275  if (input->IsName()) return Handle<Name>::cast(input);
276  return ToString(isolate, input);
277 }
278 
279 // ES6 7.1.14
280 // static
281 MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
282  Handle<Object> value) {
283  // 1. Let key be ToPrimitive(argument, hint String).
284  MaybeHandle<Object> maybe_key =
285  Object::ToPrimitive(value, ToPrimitiveHint::kString);
286  // 2. ReturnIfAbrupt(key).
287  Handle<Object> key;
288  if (!maybe_key.ToHandle(&key)) return key;
289  // 3. If Type(key) is Symbol, then return key.
290  if (key->IsSymbol()) return key;
291  // 4. Return ToString(key).
292  // Extending spec'ed behavior, we'd be happy to return an element index.
293  if (key->IsSmi()) return key;
294  if (key->IsHeapNumber()) {
295  uint32_t uint_value;
296  if (value->ToArrayLength(&uint_value) &&
297  uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
298  return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
299  }
300  }
301  return Object::ToString(isolate, key);
302 }
303 
304 // static
305 MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
306  Handle<Object> input) {
307  while (true) {
308  if (input->IsOddball()) {
309  return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
310  }
311  if (input->IsNumber()) {
312  return isolate->factory()->NumberToString(input);
313  }
314  if (input->IsSymbol()) {
315  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
316  String);
317  }
318  if (input->IsBigInt()) {
319  return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
320  }
321  ASSIGN_RETURN_ON_EXCEPTION(
322  isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
323  ToPrimitiveHint::kString),
324  String);
325  // The previous isString() check happened in Object::ToString and thus we
326  // put it at the end of the loop in this helper.
327  if (input->IsString()) {
328  return Handle<String>::cast(input);
329  }
330  }
331 }
332 
333 namespace {
334 
335 bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
336  if (!object->IsJSReceiver()) return false;
337  Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
338  return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
339  .FromMaybe(false);
340 }
341 
342 Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
343  return object->IsString() ? Handle<String>::cast(object)
344  : isolate->factory()->empty_string();
345 }
346 
347 Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
348  Handle<Object> input) {
349  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
350 
351  Handle<Name> name_key = isolate->factory()->name_string();
352  Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
353  Handle<String> name_str = AsStringOrEmpty(isolate, name);
354 
355  Handle<Name> msg_key = isolate->factory()->message_string();
356  Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
357  Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
358 
359  if (name_str->length() == 0) return msg_str;
360  if (msg_str->length() == 0) return name_str;
361 
362  IncrementalStringBuilder builder(isolate);
363  builder.AppendString(name_str);
364  builder.AppendCString(": ");
365  builder.AppendString(msg_str);
366 
367  return builder.Finish().ToHandleChecked();
368 }
369 
370 } // namespace
371 
372 // static
373 Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
374  Handle<Object> input) {
375  DisallowJavascriptExecution no_js(isolate);
376 
377  if (input->IsString() || input->IsNumber() || input->IsOddball()) {
378  return Object::ToString(isolate, input).ToHandleChecked();
379  } else if (input->IsBigInt()) {
380  MaybeHandle<String> maybe_string =
381  BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
382  Handle<String> result;
383  if (maybe_string.ToHandle(&result)) return result;
384  // BigInt-to-String conversion can fail on 32-bit platforms where
385  // String::kMaxLength is too small to fit this BigInt.
386  return isolate->factory()->NewStringFromStaticChars(
387  "<a very large BigInt>");
388  } else if (input->IsFunction()) {
389  // -- F u n c t i o n
390  Handle<String> fun_str;
391  if (input->IsJSBoundFunction()) {
392  fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
393  } else {
394  DCHECK(input->IsJSFunction());
395  fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
396  }
397 
398  if (fun_str->length() > 128) {
399  IncrementalStringBuilder builder(isolate);
400  builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
401  builder.AppendCString("...<omitted>...");
402  builder.AppendString(isolate->factory()->NewSubString(
403  fun_str, fun_str->length() - 2, fun_str->length()));
404 
405  return builder.Finish().ToHandleChecked();
406  }
407  return fun_str;
408  } else if (input->IsSymbol()) {
409  // -- S y m b o l
410  Handle<Symbol> symbol = Handle<Symbol>::cast(input);
411 
412  IncrementalStringBuilder builder(isolate);
413  builder.AppendCString("Symbol(");
414  if (symbol->name()->IsString()) {
415  builder.AppendString(handle(String::cast(symbol->name()), isolate));
416  }
417  builder.AppendCharacter(')');
418 
419  return builder.Finish().ToHandleChecked();
420  } else if (input->IsJSReceiver()) {
421  // -- J S R e c e i v e r
422  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
423  Handle<Object> to_string = JSReceiver::GetDataProperty(
424  receiver, isolate->factory()->toString_string());
425 
426  if (IsErrorObject(isolate, input) ||
427  *to_string == *isolate->error_to_string()) {
428  // When internally formatting error objects, use a side-effects-free
429  // version of Error.prototype.toString independent of the actually
430  // installed toString method.
431  return NoSideEffectsErrorToString(isolate, input);
432  } else if (*to_string == *isolate->object_to_string()) {
433  Handle<Object> ctor = JSReceiver::GetDataProperty(
434  receiver, isolate->factory()->constructor_string());
435  if (ctor->IsFunction()) {
436  Handle<String> ctor_name;
437  if (ctor->IsJSBoundFunction()) {
438  ctor_name = JSBoundFunction::GetName(
439  isolate, Handle<JSBoundFunction>::cast(ctor))
440  .ToHandleChecked();
441  } else if (ctor->IsJSFunction()) {
442  Handle<Object> ctor_name_obj =
443  JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
444  ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
445  }
446 
447  if (ctor_name->length() != 0) {
448  IncrementalStringBuilder builder(isolate);
449  builder.AppendCString("#<");
450  builder.AppendString(ctor_name);
451  builder.AppendCString(">");
452 
453  return builder.Finish().ToHandleChecked();
454  }
455  }
456  }
457  }
458 
459  // At this point, input is either none of the above or a JSReceiver.
460 
461  Handle<JSReceiver> receiver;
462  if (input->IsJSReceiver()) {
463  receiver = Handle<JSReceiver>::cast(input);
464  } else {
465  // This is the only case where Object::ToObject throws.
466  DCHECK(!input->IsSmi());
467  int constructor_function_index =
468  Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
469  if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
470  return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
471  }
472 
473  receiver = Object::ToObject(isolate, input, isolate->native_context())
474  .ToHandleChecked();
475  }
476 
477  Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
478  Handle<Object> tag_obj = JSReceiver::GetDataProperty(
479  receiver, isolate->factory()->to_string_tag_symbol());
480  Handle<String> tag =
481  tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
482 
483  IncrementalStringBuilder builder(isolate);
484  builder.AppendCString("[object ");
485  builder.AppendString(tag);
486  builder.AppendCString("]");
487 
488  return builder.Finish().ToHandleChecked();
489 }
490 
491 // static
492 MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
493  Handle<Object> input) {
494  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
495  if (input->IsSmi()) {
496  int value = std::max(Smi::ToInt(*input), 0);
497  return handle(Smi::FromInt(value), isolate);
498  }
499  double len = DoubleToInteger(input->Number());
500  if (len <= 0.0) {
501  return handle(Smi::kZero, isolate);
502  } else if (len >= kMaxSafeInteger) {
503  len = kMaxSafeInteger;
504  }
505  return isolate->factory()->NewNumber(len);
506 }
507 
508 // static
509 MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
510  Handle<Object> input,
511  MessageTemplate error_index) {
512  if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
513  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
514  if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
515  double len = DoubleToInteger(input->Number()) + 0.0;
516  auto js_len = isolate->factory()->NewNumber(len);
517  if (len < 0.0 || len > kMaxSafeInteger) {
518  THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
519  }
520  return js_len;
521 }
522 
523 bool Object::BooleanValue(Isolate* isolate) {
524  if (IsSmi()) return Smi::ToInt(this) != 0;
525  DCHECK(IsHeapObject());
526  if (IsBoolean()) return IsTrue(isolate);
527  if (IsNullOrUndefined(isolate)) return false;
528  if (IsUndetectable()) return false; // Undetectable object is false.
529  if (IsString()) return String::cast(this)->length() != 0;
530  if (IsHeapNumber()) return DoubleToBoolean(HeapNumber::cast(this)->value());
531  if (IsBigInt()) return BigInt::cast(this)->ToBoolean();
532  return true;
533 }
534 
535 bool ObjectPtr::BooleanValue(Isolate* isolate) {
536  return reinterpret_cast<Object*>(ptr())->BooleanValue(isolate);
537 }
538 
539 namespace {
540 
541 // TODO(bmeurer): Maybe we should introduce a marker interface Number,
542 // where we put all these methods at some point?
543 ComparisonResult NumberCompare(double x, double y) {
544  if (std::isnan(x) || std::isnan(y)) {
545  return ComparisonResult::kUndefined;
546  } else if (x < y) {
547  return ComparisonResult::kLessThan;
548  } else if (x > y) {
549  return ComparisonResult::kGreaterThan;
550  } else {
551  return ComparisonResult::kEqual;
552  }
553 }
554 
555 bool NumberEquals(double x, double y) {
556  // Must check explicitly for NaN's on Windows, but -0 works fine.
557  if (std::isnan(x)) return false;
558  if (std::isnan(y)) return false;
559  return x == y;
560 }
561 
562 bool NumberEquals(const Object* x, const Object* y) {
563  return NumberEquals(x->Number(), y->Number());
564 }
565 
566 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
567  return NumberEquals(*x, *y);
568 }
569 
570 ComparisonResult Reverse(ComparisonResult result) {
571  if (result == ComparisonResult::kLessThan) {
572  return ComparisonResult::kGreaterThan;
573  }
574  if (result == ComparisonResult::kGreaterThan) {
575  return ComparisonResult::kLessThan;
576  }
577  return result;
578 }
579 
580 } // anonymous namespace
581 
582 // static
583 Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
584  Handle<Object> y) {
585  // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
586  if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
587  !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
588  return Nothing<ComparisonResult>();
589  }
590  if (x->IsString() && y->IsString()) {
591  // ES6 section 7.2.11 Abstract Relational Comparison step 5.
592  return Just(String::Compare(isolate, Handle<String>::cast(x),
593  Handle<String>::cast(y)));
594  }
595  if (x->IsBigInt() && y->IsString()) {
596  return Just(BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
597  Handle<String>::cast(y)));
598  }
599  if (x->IsString() && y->IsBigInt()) {
600  return Just(Reverse(BigInt::CompareToString(
601  isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x))));
602  }
603  // ES6 section 7.2.11 Abstract Relational Comparison step 6.
604  if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
605  !Object::ToNumeric(isolate, y).ToHandle(&y)) {
606  return Nothing<ComparisonResult>();
607  }
608 
609  bool x_is_number = x->IsNumber();
610  bool y_is_number = y->IsNumber();
611  if (x_is_number && y_is_number) {
612  return Just(NumberCompare(x->Number(), y->Number()));
613  } else if (!x_is_number && !y_is_number) {
614  return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
615  Handle<BigInt>::cast(y)));
616  } else if (x_is_number) {
617  return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
618  } else {
619  return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
620  }
621 }
622 
623 
624 // static
625 Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
626  Handle<Object> y) {
627  // This is the generic version of Abstract Equality Comparison. Must be in
628  // sync with CodeStubAssembler::Equal.
629  while (true) {
630  if (x->IsNumber()) {
631  if (y->IsNumber()) {
632  return Just(NumberEquals(x, y));
633  } else if (y->IsBoolean()) {
634  return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
635  } else if (y->IsString()) {
636  return Just(NumberEquals(
637  x, String::ToNumber(isolate, Handle<String>::cast(y))));
638  } else if (y->IsBigInt()) {
639  return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
640  } else if (y->IsJSReceiver()) {
641  if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
642  .ToHandle(&y)) {
643  return Nothing<bool>();
644  }
645  } else {
646  return Just(false);
647  }
648  } else if (x->IsString()) {
649  if (y->IsString()) {
650  return Just(String::Equals(isolate, Handle<String>::cast(x),
651  Handle<String>::cast(y)));
652  } else if (y->IsNumber()) {
653  x = String::ToNumber(isolate, Handle<String>::cast(x));
654  return Just(NumberEquals(x, y));
655  } else if (y->IsBoolean()) {
656  x = String::ToNumber(isolate, Handle<String>::cast(x));
657  return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
658  } else if (y->IsBigInt()) {
659  return Just(BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
660  Handle<String>::cast(x)));
661  } else if (y->IsJSReceiver()) {
662  if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
663  .ToHandle(&y)) {
664  return Nothing<bool>();
665  }
666  } else {
667  return Just(false);
668  }
669  } else if (x->IsBoolean()) {
670  if (y->IsOddball()) {
671  return Just(x.is_identical_to(y));
672  } else if (y->IsNumber()) {
673  return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
674  } else if (y->IsString()) {
675  y = String::ToNumber(isolate, Handle<String>::cast(y));
676  return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
677  } else if (y->IsBigInt()) {
678  x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
679  return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
680  } else if (y->IsJSReceiver()) {
681  if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
682  .ToHandle(&y)) {
683  return Nothing<bool>();
684  }
685  x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
686  } else {
687  return Just(false);
688  }
689  } else if (x->IsSymbol()) {
690  if (y->IsSymbol()) {
691  return Just(x.is_identical_to(y));
692  } else if (y->IsJSReceiver()) {
693  if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
694  .ToHandle(&y)) {
695  return Nothing<bool>();
696  }
697  } else {
698  return Just(false);
699  }
700  } else if (x->IsBigInt()) {
701  if (y->IsBigInt()) {
702  return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
703  }
704  return Equals(isolate, y, x);
705  } else if (x->IsJSReceiver()) {
706  if (y->IsJSReceiver()) {
707  return Just(x.is_identical_to(y));
708  } else if (y->IsUndetectable()) {
709  return Just(x->IsUndetectable());
710  } else if (y->IsBoolean()) {
711  y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
712  } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
713  .ToHandle(&x)) {
714  return Nothing<bool>();
715  }
716  } else {
717  return Just(x->IsUndetectable() && y->IsUndetectable());
718  }
719  }
720 }
721 
722 
723 bool Object::StrictEquals(Object* that) {
724  if (this->IsNumber()) {
725  if (!that->IsNumber()) return false;
726  return NumberEquals(this, that);
727  } else if (this->IsString()) {
728  if (!that->IsString()) return false;
729  return String::cast(this)->Equals(String::cast(that));
730  } else if (this->IsBigInt()) {
731  if (!that->IsBigInt()) return false;
732  return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(that));
733  }
734  return this == that;
735 }
736 
737 
738 // static
739 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
740  if (object->IsNumber()) return isolate->factory()->number_string();
741  if (object->IsOddball())
742  return handle(Oddball::cast(*object)->type_of(), isolate);
743  if (object->IsUndetectable()) {
744  return isolate->factory()->undefined_string();
745  }
746  if (object->IsString()) return isolate->factory()->string_string();
747  if (object->IsSymbol()) return isolate->factory()->symbol_string();
748  if (object->IsBigInt()) return isolate->factory()->bigint_string();
749  if (object->IsCallable()) return isolate->factory()->function_string();
750  return isolate->factory()->object_string();
751 }
752 
753 
754 // static
755 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
756  Handle<Object> rhs) {
757  if (lhs->IsNumber() && rhs->IsNumber()) {
758  return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
759  } else if (lhs->IsString() && rhs->IsString()) {
760  return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
761  Handle<String>::cast(rhs));
762  }
763  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
764  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
765  if (lhs->IsString() || rhs->IsString()) {
766  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
767  Object);
768  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
769  Object);
770  return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
771  Handle<String>::cast(rhs));
772  }
773  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
774  Object);
775  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
776  Object);
777  return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
778 }
779 
780 
781 // static
782 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
783  Handle<Object> callable,
784  Handle<Object> object) {
785  // The {callable} must have a [[Call]] internal method.
786  if (!callable->IsCallable()) return isolate->factory()->false_value();
787 
788  // Check if {callable} is a bound function, and if so retrieve its
789  // [[BoundTargetFunction]] and use that instead of {callable}.
790  if (callable->IsJSBoundFunction()) {
791  Handle<Object> bound_callable(
792  Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
793  isolate);
794  return Object::InstanceOf(isolate, object, bound_callable);
795  }
796 
797  // If {object} is not a receiver, return false.
798  if (!object->IsJSReceiver()) return isolate->factory()->false_value();
799 
800  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
801  Handle<Object> prototype;
802  ASSIGN_RETURN_ON_EXCEPTION(
803  isolate, prototype,
804  Object::GetProperty(isolate, callable,
805  isolate->factory()->prototype_string()),
806  Object);
807  if (!prototype->IsJSReceiver()) {
808  THROW_NEW_ERROR(
809  isolate,
810  NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
811  Object);
812  }
813 
814  // Return whether or not {prototype} is in the prototype chain of {object}.
815  Maybe<bool> result = JSReceiver::HasInPrototypeChain(
816  isolate, Handle<JSReceiver>::cast(object), prototype);
817  if (result.IsNothing()) return MaybeHandle<Object>();
818  return isolate->factory()->ToBoolean(result.FromJust());
819 }
820 
821 // static
822 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
823  Handle<Object> callable) {
824  // The {callable} must be a receiver.
825  if (!callable->IsJSReceiver()) {
826  THROW_NEW_ERROR(isolate,
827  NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
828  Object);
829  }
830 
831  // Lookup the @@hasInstance method on {callable}.
832  Handle<Object> inst_of_handler;
833  ASSIGN_RETURN_ON_EXCEPTION(
834  isolate, inst_of_handler,
835  JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
836  isolate->factory()->has_instance_symbol()),
837  Object);
838  if (!inst_of_handler->IsUndefined(isolate)) {
839  // Call the {inst_of_handler} on the {callable}.
840  Handle<Object> result;
841  ASSIGN_RETURN_ON_EXCEPTION(
842  isolate, result,
843  Execution::Call(isolate, inst_of_handler, callable, 1, &object),
844  Object);
845  return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
846  }
847 
848  // The {callable} must have a [[Call]] internal method.
849  if (!callable->IsCallable()) {
850  THROW_NEW_ERROR(
851  isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
852  Object);
853  }
854 
855  // Fall back to OrdinaryHasInstance with {callable} and {object}.
856  Handle<Object> result;
857  ASSIGN_RETURN_ON_EXCEPTION(
858  isolate, result,
859  JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
860  return result;
861 }
862 
863 // static
864 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
865  Handle<Name> name) {
866  Handle<Object> func;
867  Isolate* isolate = receiver->GetIsolate();
868  ASSIGN_RETURN_ON_EXCEPTION(
869  isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
870  if (func->IsNullOrUndefined(isolate)) {
871  return isolate->factory()->undefined_value();
872  }
873  if (!func->IsCallable()) {
874  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
875  func, name, receiver),
876  Object);
877  }
878  return func;
879 }
880 
881 namespace {
882 
883 MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
884  Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
885  if (element_types == ElementTypes::kAll) {
886  if (object->IsJSArray()) {
887  Handle<JSArray> array = Handle<JSArray>::cast(object);
888  uint32_t length;
889  if (!array->HasArrayPrototype(isolate) ||
890  !array->length()->ToUint32(&length) || !array->HasFastElements() ||
891  !JSObject::PrototypeHasNoElements(isolate, *array)) {
892  return MaybeHandle<FixedArray>();
893  }
894  return array->GetElementsAccessor()->CreateListFromArrayLike(
895  isolate, array, length);
896  } else if (object->IsJSTypedArray()) {
897  Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
898  size_t length = array->length_value();
899  if (array->WasNeutered() ||
900  length > static_cast<size_t>(FixedArray::kMaxLength)) {
901  return MaybeHandle<FixedArray>();
902  }
903  return array->GetElementsAccessor()->CreateListFromArrayLike(
904  isolate, array, static_cast<uint32_t>(length));
905  }
906  }
907  return MaybeHandle<FixedArray>();
908 }
909 
910 } // namespace
911 
912 // static
913 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
914  Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
915  // Fast-path for JSArray and JSTypedArray.
916  MaybeHandle<FixedArray> fast_result =
917  CreateListFromArrayLikeFastPath(isolate, object, element_types);
918  if (!fast_result.is_null()) return fast_result;
919  // 1. ReturnIfAbrupt(object).
920  // 2. (default elementTypes -- not applicable.)
921  // 3. If Type(obj) is not Object, throw a TypeError exception.
922  if (!object->IsJSReceiver()) {
923  THROW_NEW_ERROR(isolate,
924  NewTypeError(MessageTemplate::kCalledOnNonObject,
925  isolate->factory()->NewStringFromAsciiChecked(
926  "CreateListFromArrayLike")),
927  FixedArray);
928  }
929 
930  // 4. Let len be ? ToLength(? Get(obj, "length")).
931  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
932  Handle<Object> raw_length_number;
933  ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
934  Object::GetLengthFromArrayLike(isolate, receiver),
935  FixedArray);
936  uint32_t len;
937  if (!raw_length_number->ToUint32(&len) ||
938  len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
939  THROW_NEW_ERROR(isolate,
940  NewRangeError(MessageTemplate::kInvalidArrayLength),
941  FixedArray);
942  }
943  // 5. Let list be an empty List.
944  Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
945  // 6. Let index be 0.
946  // 7. Repeat while index < len:
947  for (uint32_t index = 0; index < len; ++index) {
948  // 7a. Let indexName be ToString(index).
949  // 7b. Let next be ? Get(obj, indexName).
950  Handle<Object> next;
951  ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
952  JSReceiver::GetElement(isolate, receiver, index),
953  FixedArray);
954  switch (element_types) {
955  case ElementTypes::kAll:
956  // Nothing to do.
957  break;
958  case ElementTypes::kStringAndSymbol: {
959  // 7c. If Type(next) is not an element of elementTypes, throw a
960  // TypeError exception.
961  if (!next->IsName()) {
962  THROW_NEW_ERROR(isolate,
963  NewTypeError(MessageTemplate::kNotPropertyName, next),
964  FixedArray);
965  }
966  // 7d. Append next as the last element of list.
967  // Internalize on the fly so we can use pointer identity later.
968  next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
969  break;
970  }
971  }
972  list->set(index, *next);
973  // 7e. Set index to index + 1. (See loop header.)
974  }
975  // 8. Return list.
976  return list;
977 }
978 
979 
980 // static
981 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
982  Handle<JSReceiver> object) {
983  Handle<Object> val;
984  Handle<Name> key = isolate->factory()->length_string();
985  ASSIGN_RETURN_ON_EXCEPTION(
986  isolate, val, JSReceiver::GetProperty(isolate, object, key), Object);
987  return Object::ToLength(isolate, val);
988 }
989 
990 // static
991 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
992  for (; it->IsFound(); it->Next()) {
993  switch (it->state()) {
994  case LookupIterator::NOT_FOUND:
995  case LookupIterator::TRANSITION:
996  UNREACHABLE();
997  case LookupIterator::JSPROXY:
998  return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
999  it->GetName());
1000  case LookupIterator::INTERCEPTOR: {
1001  Maybe<PropertyAttributes> result =
1002  JSObject::GetPropertyAttributesWithInterceptor(it);
1003  if (result.IsNothing()) return Nothing<bool>();
1004  if (result.FromJust() != ABSENT) return Just(true);
1005  break;
1006  }
1007  case LookupIterator::ACCESS_CHECK: {
1008  if (it->HasAccess()) break;
1009  Maybe<PropertyAttributes> result =
1010  JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
1011  if (result.IsNothing()) return Nothing<bool>();
1012  return Just(result.FromJust() != ABSENT);
1013  }
1014  case LookupIterator::INTEGER_INDEXED_EXOTIC:
1015  // TypedArray out-of-bounds access.
1016  return Just(false);
1017  case LookupIterator::ACCESSOR:
1018  case LookupIterator::DATA:
1019  return Just(true);
1020  }
1021  }
1022  return Just(false);
1023 }
1024 
1025 // static
1026 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
1027  Handle<Name> name) {
1028  if (object->IsJSModuleNamespace()) {
1029  PropertyDescriptor desc;
1030  return JSReceiver::GetOwnPropertyDescriptor(object->GetIsolate(), object,
1031  name, &desc);
1032  }
1033 
1034  if (object->IsJSObject()) { // Shortcut.
1035  LookupIterator it = LookupIterator::PropertyOrElement(
1036  object->GetIsolate(), object, name, object, LookupIterator::OWN);
1037  return HasProperty(&it);
1038  }
1039 
1040  Maybe<PropertyAttributes> attributes =
1041  JSReceiver::GetOwnPropertyAttributes(object, name);
1042  MAYBE_RETURN(attributes, Nothing<bool>());
1043  return Just(attributes.FromJust() != ABSENT);
1044 }
1045 
1046 // static
1047 MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
1048  OnNonExistent on_non_existent) {
1049  for (; it->IsFound(); it->Next()) {
1050  switch (it->state()) {
1051  case LookupIterator::NOT_FOUND:
1052  case LookupIterator::TRANSITION:
1053  UNREACHABLE();
1054  case LookupIterator::JSPROXY: {
1055  bool was_found;
1056  MaybeHandle<Object> result =
1057  JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
1058  it->GetName(), it->GetReceiver(), &was_found);
1059  if (!was_found) it->NotFound();
1060  return result;
1061  }
1062  case LookupIterator::INTERCEPTOR: {
1063  bool done;
1064  Handle<Object> result;
1065  ASSIGN_RETURN_ON_EXCEPTION(
1066  it->isolate(), result,
1067  JSObject::GetPropertyWithInterceptor(it, &done), Object);
1068  if (done) return result;
1069  break;
1070  }
1071  case LookupIterator::ACCESS_CHECK:
1072  if (it->HasAccess()) break;
1073  return JSObject::GetPropertyWithFailedAccessCheck(it);
1074  case LookupIterator::ACCESSOR:
1075  return GetPropertyWithAccessor(it);
1076  case LookupIterator::INTEGER_INDEXED_EXOTIC:
1077  return it->isolate()->factory()->undefined_value();
1078  case LookupIterator::DATA:
1079  return it->GetDataValue();
1080  }
1081  }
1082 
1083  if (on_non_existent == OnNonExistent::kThrowReferenceError) {
1084  THROW_NEW_ERROR(it->isolate(),
1085  NewReferenceError(MessageTemplate::kNotDefined, it->name()),
1086  Object);
1087  }
1088  return it->isolate()->factory()->undefined_value();
1089 }
1090 
1091 
1092 // static
1093 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
1094  Handle<JSProxy> proxy,
1095  Handle<Name> name,
1096  Handle<Object> receiver,
1097  bool* was_found) {
1098  *was_found = true;
1099 
1100  DCHECK(!name->IsPrivate());
1101  STACK_CHECK(isolate, MaybeHandle<Object>());
1102  Handle<Name> trap_name = isolate->factory()->get_string();
1103  // 1. Assert: IsPropertyKey(P) is true.
1104  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1105  Handle<Object> handler(proxy->handler(), isolate);
1106  // 3. If handler is null, throw a TypeError exception.
1107  // 4. Assert: Type(handler) is Object.
1108  if (proxy->IsRevoked()) {
1109  THROW_NEW_ERROR(isolate,
1110  NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1111  Object);
1112  }
1113  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
1114  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1115  // 6. Let trap be ? GetMethod(handler, "get").
1116  Handle<Object> trap;
1117  ASSIGN_RETURN_ON_EXCEPTION(
1118  isolate, trap,
1119  Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
1120  // 7. If trap is undefined, then
1121  if (trap->IsUndefined(isolate)) {
1122  // 7.a Return target.[[Get]](P, Receiver).
1123  LookupIterator it =
1124  LookupIterator::PropertyOrElement(isolate, receiver, name, target);
1125  MaybeHandle<Object> result = Object::GetProperty(&it);
1126  *was_found = it.IsFound();
1127  return result;
1128  }
1129  // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
1130  Handle<Object> trap_result;
1131  Handle<Object> args[] = {target, name, receiver};
1132  ASSIGN_RETURN_ON_EXCEPTION(
1133  isolate, trap_result,
1134  Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
1135 
1136  MaybeHandle<Object> result =
1137  JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
1138  if (result.is_null()) {
1139  return result;
1140  }
1141 
1142  // 11. Return trap_result
1143  return trap_result;
1144 }
1145 
1146 // static
1147 MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
1148  Handle<Name> name,
1149  Handle<JSReceiver> target,
1150  Handle<Object> trap_result,
1151  AccessKind access_kind) {
1152  // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
1153  PropertyDescriptor target_desc;
1154  Maybe<bool> target_found =
1155  JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
1156  MAYBE_RETURN_NULL(target_found);
1157  // 10. If targetDesc is not undefined, then
1158  if (target_found.FromJust()) {
1159  // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
1160  // false and targetDesc.[[Writable]] is false, then
1161  // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
1162  // throw a TypeError exception.
1163  bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
1164  !target_desc.configurable() &&
1165  !target_desc.writable() &&
1166  !trap_result->SameValue(*target_desc.value());
1167  if (inconsistent) {
1168  if (access_kind == kGet) {
1169  THROW_NEW_ERROR(
1170  isolate,
1171  NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
1172  target_desc.value(), trap_result),
1173  Object);
1174  } else {
1175  isolate->Throw(*isolate->factory()->NewTypeError(
1176  MessageTemplate::kProxySetFrozenData, name));
1177  return MaybeHandle<Object>();
1178  }
1179  }
1180  // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
1181  // is false and targetDesc.[[Get]] is undefined, then
1182  // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
1183  if (access_kind == kGet) {
1184  inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1185  !target_desc.configurable() &&
1186  target_desc.get()->IsUndefined(isolate) &&
1187  !trap_result->IsUndefined(isolate);
1188  } else {
1189  inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1190  !target_desc.configurable() &&
1191  target_desc.set()->IsUndefined(isolate);
1192  }
1193  if (inconsistent) {
1194  if (access_kind == kGet) {
1195  THROW_NEW_ERROR(
1196  isolate,
1197  NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
1198  name, trap_result),
1199  Object);
1200  } else {
1201  isolate->Throw(*isolate->factory()->NewTypeError(
1202  MessageTemplate::kProxySetFrozenAccessor, name));
1203  return MaybeHandle<Object>();
1204  }
1205  }
1206  }
1207  return isolate->factory()->undefined_value();
1208 }
1209 
1210 
1211 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
1212  for (; it->IsFound(); it->Next()) {
1213  switch (it->state()) {
1214  case LookupIterator::INTERCEPTOR:
1215  case LookupIterator::NOT_FOUND:
1216  case LookupIterator::TRANSITION:
1217  UNREACHABLE();
1218  case LookupIterator::ACCESS_CHECK:
1219  // Support calling this method without an active context, but refuse
1220  // access to access-checked objects in that case.
1221  if (!it->isolate()->context().is_null() && it->HasAccess()) continue;
1222  V8_FALLTHROUGH;
1223  case LookupIterator::JSPROXY:
1224  it->NotFound();
1225  return it->isolate()->factory()->undefined_value();
1226  case LookupIterator::ACCESSOR:
1227  // TODO(verwaest): For now this doesn't call into AccessorInfo, since
1228  // clients don't need it. Update once relevant.
1229  it->NotFound();
1230  return it->isolate()->factory()->undefined_value();
1231  case LookupIterator::INTEGER_INDEXED_EXOTIC:
1232  return it->isolate()->factory()->undefined_value();
1233  case LookupIterator::DATA:
1234  return it->GetDataValue();
1235  }
1236  }
1237  return it->isolate()->factory()->undefined_value();
1238 }
1239 
1240 
1241 bool Object::ToInt32(int32_t* value) {
1242  if (IsSmi()) {
1243  *value = Smi::ToInt(this);
1244  return true;
1245  }
1246  if (IsHeapNumber()) {
1247  double num = HeapNumber::cast(this)->value();
1248  // Check range before conversion to avoid undefined behavior.
1249  if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1250  *value = FastD2I(num);
1251  return true;
1252  }
1253  }
1254  return false;
1255 }
1256 
1257 // static constexpr object declarations need a definition to make the
1258 // compiler happy.
1259 constexpr ObjectPtr Smi::kZero;
1260 constexpr ObjectPtr SharedFunctionInfo::kNoSharedNameSentinel;
1261 
1262 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
1263  Isolate* isolate, Handle<FunctionTemplateInfo> info,
1264  MaybeHandle<Name> maybe_name) {
1265  Object* current_info = info->shared_function_info();
1266  if (current_info->IsSharedFunctionInfo()) {
1267  return handle(SharedFunctionInfo::cast(current_info), isolate);
1268  }
1269  Handle<Name> name;
1270  Handle<String> name_string;
1271  if (maybe_name.ToHandle(&name) && name->IsString()) {
1272  name_string = Handle<String>::cast(name);
1273  } else if (info->class_name()->IsString()) {
1274  name_string = handle(String::cast(info->class_name()), isolate);
1275  } else {
1276  name_string = isolate->factory()->empty_string();
1277  }
1278  FunctionKind function_kind;
1279  if (info->remove_prototype()) {
1280  function_kind = kConciseMethod;
1281  } else {
1282  function_kind = kNormalFunction;
1283  }
1284  Handle<SharedFunctionInfo> result =
1285  isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info,
1286  function_kind);
1287 
1288  result->set_length(info->length());
1289  result->DontAdaptArguments();
1290  DCHECK(result->IsApiFunction());
1291 
1292  info->set_shared_function_info(*result);
1293  return result;
1294 }
1295 
1296 bool FunctionTemplateInfo::IsTemplateFor(Map map) {
1297  // There is a constraint on the object; check.
1298  if (!map->IsJSObjectMap()) return false;
1299  // Fetch the constructor function of the object.
1300  Object* cons_obj = map->GetConstructor();
1301  Object* type;
1302  if (cons_obj->IsJSFunction()) {
1303  JSFunction* fun = JSFunction::cast(cons_obj);
1304  type = fun->shared()->function_data();
1305  } else if (cons_obj->IsFunctionTemplateInfo()) {
1306  type = FunctionTemplateInfo::cast(cons_obj);
1307  } else {
1308  return false;
1309  }
1310  // Iterate through the chain of inheriting function templates to
1311  // see if the required one occurs.
1312  while (type->IsFunctionTemplateInfo()) {
1313  if (type == this) return true;
1314  type = FunctionTemplateInfo::cast(type)->GetParentTemplate();
1315  }
1316  // Didn't find the required type in the inheritance chain.
1317  return false;
1318 }
1319 
1320 // static
1321 FunctionTemplateRareData*
1322 FunctionTemplateInfo::AllocateFunctionTemplateRareData(
1323  Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
1324  DCHECK(function_template_info->rare_data()->IsUndefined(isolate));
1325  Handle<Struct> struct_obj =
1326  isolate->factory()->NewStruct(FUNCTION_TEMPLATE_RARE_DATA_TYPE, TENURED);
1327  Handle<FunctionTemplateRareData> rare_data =
1329  function_template_info->set_rare_data(*rare_data);
1330  return *rare_data;
1331 }
1332 
1333 // static
1334 Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
1335  Handle<FixedArray> list =
1336  isolate->factory()->NewFixedArray(kLengthIndex + size);
1337  list->set(kLengthIndex, Smi::kZero);
1338  return Handle<TemplateList>::cast(list);
1339 }
1340 
1341 // static
1342 Handle<TemplateList> TemplateList::Add(Isolate* isolate,
1343  Handle<TemplateList> list,
1344  Handle<i::Object> value) {
1345  STATIC_ASSERT(kFirstElementIndex == 1);
1346  int index = list->length() + 1;
1347  Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
1348  fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
1349  fixed_array->set(kLengthIndex, Smi::FromInt(index));
1350  return Handle<TemplateList>::cast(fixed_array);
1351 }
1352 
1353 // static
1354 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
1355  Handle<JSReceiver> new_target,
1356  Handle<AllocationSite> site) {
1357  // If called through new, new.target can be:
1358  // - a subclass of constructor,
1359  // - a proxy wrapper around constructor, or
1360  // - the constructor itself.
1361  // If called through Reflect.construct, it's guaranteed to be a constructor.
1362  Isolate* const isolate = constructor->GetIsolate();
1363  DCHECK(constructor->IsConstructor());
1364  DCHECK(new_target->IsConstructor());
1365  DCHECK(!constructor->has_initial_map() ||
1366  constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
1367 
1368  Handle<Map> initial_map;
1369  ASSIGN_RETURN_ON_EXCEPTION(
1370  isolate, initial_map,
1371  JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
1372  Handle<JSObject> result =
1373  isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
1374  if (initial_map->is_dictionary_map()) {
1375  Handle<NameDictionary> dictionary =
1376  NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
1377  result->SetProperties(*dictionary);
1378  }
1379  isolate->counters()->constructed_objects()->Increment();
1380  isolate->counters()->constructed_objects_runtime()->Increment();
1381  return result;
1382 }
1383 
1384 // 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
1385 // Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
1386 MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,
1387  Handle<Object> prototype) {
1388  // Generate the map with the specified {prototype} based on the Object
1389  // function's initial map from the current native context.
1390  // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1391  // slack tracking for Object.create.
1392  Handle<Map> map =
1393  Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
1394 
1395  // Actually allocate the object.
1396  Handle<JSObject> object;
1397  if (map->is_dictionary_map()) {
1398  object = isolate->factory()->NewSlowJSObjectFromMap(map);
1399  } else {
1400  object = isolate->factory()->NewJSObjectFromMap(map);
1401  }
1402  return object;
1403 }
1404 
1405 void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
1406  DCHECK(object->HasSmiOrObjectElements() ||
1407  object->HasFastStringWrapperElements());
1408  FixedArray raw_elems = FixedArray::cast(object->elements());
1409  Heap* heap = object->GetHeap();
1410  if (raw_elems->map() != ReadOnlyRoots(heap).fixed_cow_array_map()) return;
1411  Isolate* isolate = heap->isolate();
1412  Handle<FixedArray> elems(raw_elems, isolate);
1413  Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
1414  elems, isolate->factory()->fixed_array_map());
1415  object->set_elements(*writable_elems);
1416  isolate->counters()->cow_arrays_converted()->Increment();
1417 }
1418 
1419 int JSObject::GetHeaderSize(InstanceType type,
1420  bool function_has_prototype_slot) {
1421  switch (type) {
1422  case JS_OBJECT_TYPE:
1423  case JS_API_OBJECT_TYPE:
1424  case JS_SPECIAL_API_OBJECT_TYPE:
1425  return JSObject::kHeaderSize;
1426  case JS_GENERATOR_OBJECT_TYPE:
1427  return JSGeneratorObject::kSize;
1428  case JS_ASYNC_FUNCTION_OBJECT_TYPE:
1429  return JSAsyncFunctionObject::kSize;
1430  case JS_ASYNC_GENERATOR_OBJECT_TYPE:
1431  return JSAsyncGeneratorObject::kSize;
1432  case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
1433  return JSAsyncFromSyncIterator::kSize;
1434  case JS_GLOBAL_PROXY_TYPE:
1435  return JSGlobalProxy::kSize;
1436  case JS_GLOBAL_OBJECT_TYPE:
1437  return JSGlobalObject::kSize;
1438  case JS_BOUND_FUNCTION_TYPE:
1439  return JSBoundFunction::kSize;
1440  case JS_FUNCTION_TYPE:
1441  return JSFunction::GetHeaderSize(function_has_prototype_slot);
1442  case JS_VALUE_TYPE:
1443  return JSValue::kSize;
1444  case JS_DATE_TYPE:
1445  return JSDate::kSize;
1446  case JS_ARRAY_TYPE:
1447  return JSArray::kSize;
1448  case JS_ARRAY_BUFFER_TYPE:
1449  return JSArrayBuffer::kHeaderSize;
1450  case JS_ARRAY_ITERATOR_TYPE:
1451  return JSArrayIterator::kSize;
1452  case JS_TYPED_ARRAY_TYPE:
1453  return JSTypedArray::kHeaderSize;
1454  case JS_DATA_VIEW_TYPE:
1455  return JSDataView::kHeaderSize;
1456  case JS_SET_TYPE:
1457  return JSSet::kSize;
1458  case JS_MAP_TYPE:
1459  return JSMap::kSize;
1460  case JS_SET_KEY_VALUE_ITERATOR_TYPE:
1461  case JS_SET_VALUE_ITERATOR_TYPE:
1462  return JSSetIterator::kSize;
1463  case JS_MAP_KEY_ITERATOR_TYPE:
1464  case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
1465  case JS_MAP_VALUE_ITERATOR_TYPE:
1466  return JSMapIterator::kSize;
1467  case JS_WEAK_CELL_TYPE:
1468  return JSWeakCell::kSize;
1469  case JS_WEAK_FACTORY_TYPE:
1470  return JSWeakFactory::kSize;
1471  case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
1472  return JSWeakFactoryCleanupIterator::kSize;
1473  case JS_WEAK_MAP_TYPE:
1474  return JSWeakMap::kSize;
1475  case JS_WEAK_SET_TYPE:
1476  return JSWeakSet::kSize;
1477  case JS_PROMISE_TYPE:
1478  return JSPromise::kSize;
1479  case JS_REGEXP_TYPE:
1480  return JSRegExp::kSize;
1481  case JS_REGEXP_STRING_ITERATOR_TYPE:
1482  return JSRegExpStringIterator::kSize;
1483  case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1484  return JSObject::kHeaderSize;
1485  case JS_MESSAGE_OBJECT_TYPE:
1486  return JSMessageObject::kSize;
1487  case JS_ARGUMENTS_TYPE:
1488  return JSObject::kHeaderSize;
1489  case JS_ERROR_TYPE:
1490  return JSObject::kHeaderSize;
1491  case JS_STRING_ITERATOR_TYPE:
1492  return JSStringIterator::kSize;
1493  case JS_MODULE_NAMESPACE_TYPE:
1494  return JSModuleNamespace::kHeaderSize;
1495 #ifdef V8_INTL_SUPPORT
1496  case JS_INTL_V8_BREAK_ITERATOR_TYPE:
1497  return JSV8BreakIterator::kSize;
1498  case JS_INTL_COLLATOR_TYPE:
1499  return JSCollator::kSize;
1500  case JS_INTL_DATE_TIME_FORMAT_TYPE:
1501  return JSDateTimeFormat::kSize;
1502  case JS_INTL_LIST_FORMAT_TYPE:
1503  return JSListFormat::kSize;
1504  case JS_INTL_LOCALE_TYPE:
1505  return JSLocale::kSize;
1506  case JS_INTL_NUMBER_FORMAT_TYPE:
1507  return JSNumberFormat::kSize;
1508  case JS_INTL_PLURAL_RULES_TYPE:
1509  return JSPluralRules::kSize;
1510  case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
1511  return JSRelativeTimeFormat::kSize;
1512  case JS_INTL_SEGMENT_ITERATOR_TYPE:
1513  return JSSegmentIterator::kSize;
1514  case JS_INTL_SEGMENTER_TYPE:
1515  return JSSegmenter::kSize;
1516 #endif // V8_INTL_SUPPORT
1517  case WASM_GLOBAL_TYPE:
1518  return WasmGlobalObject::kSize;
1519  case WASM_INSTANCE_TYPE:
1520  return WasmInstanceObject::kSize;
1521  case WASM_MEMORY_TYPE:
1522  return WasmMemoryObject::kSize;
1523  case WASM_MODULE_TYPE:
1524  return WasmModuleObject::kSize;
1525  case WASM_TABLE_TYPE:
1526  return WasmTableObject::kSize;
1527  case WASM_EXCEPTION_TYPE:
1528  return WasmExceptionObject::kSize;
1529  default:
1530  UNREACHABLE();
1531  }
1532 }
1533 
1534 // ES6 9.5.1
1535 // static
1536 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1537  Isolate* isolate = proxy->GetIsolate();
1538  Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1539 
1540  STACK_CHECK(isolate, MaybeHandle<Object>());
1541 
1542  // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1543  // 2. If handler is null, throw a TypeError exception.
1544  // 3. Assert: Type(handler) is Object.
1545  // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1546  if (proxy->IsRevoked()) {
1547  THROW_NEW_ERROR(isolate,
1548  NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1549  Object);
1550  }
1551  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1552  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1553 
1554  // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1555  Handle<Object> trap;
1556  ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
1557  Object);
1558  // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1559  if (trap->IsUndefined(isolate)) {
1560  return JSReceiver::GetPrototype(isolate, target);
1561  }
1562  // 7. Let handlerProto be ? Call(trap, handler, «target»).
1563  Handle<Object> argv[] = {target};
1564  Handle<Object> handler_proto;
1565  ASSIGN_RETURN_ON_EXCEPTION(
1566  isolate, handler_proto,
1567  Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
1568  // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1569  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1570  THROW_NEW_ERROR(isolate,
1571  NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1572  Object);
1573  }
1574  // 9. Let extensibleTarget be ? IsExtensible(target).
1575  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1576  MAYBE_RETURN_NULL(is_extensible);
1577  // 10. If extensibleTarget is true, return handlerProto.
1578  if (is_extensible.FromJust()) return handler_proto;
1579  // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1580  Handle<Object> target_proto;
1581  ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1582  JSReceiver::GetPrototype(isolate, target), Object);
1583  // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1584  if (!handler_proto->SameValue(*target_proto)) {
1585  THROW_NEW_ERROR(
1586  isolate,
1587  NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1588  Object);
1589  }
1590  // 13. Return handlerProto.
1591  return handler_proto;
1592 }
1593 
1594 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1595  Isolate* isolate = it->isolate();
1596  Handle<Object> structure = it->GetAccessors();
1597  Handle<Object> receiver = it->GetReceiver();
1598  // In case of global IC, the receiver is the global object. Replace by the
1599  // global proxy.
1600  if (receiver->IsJSGlobalObject()) {
1601  receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1602  }
1603 
1604  // We should never get here to initialize a const with the hole value since a
1605  // const declaration would conflict with the getter.
1606  DCHECK(!structure->IsForeign());
1607 
1608  // API style callbacks.
1609  Handle<JSObject> holder = it->GetHolder<JSObject>();
1610  if (structure->IsAccessorInfo()) {
1611  Handle<Name> name = it->GetName();
1612  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1613  if (!info->IsCompatibleReceiver(*receiver)) {
1614  THROW_NEW_ERROR(isolate,
1615  NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1616  name, receiver),
1617  Object);
1618  }
1619 
1620  if (!info->has_getter()) return isolate->factory()->undefined_value();
1621 
1622  if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1623  ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1624  Object::ConvertReceiver(isolate, receiver),
1625  Object);
1626  }
1627 
1628  PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1629  kDontThrow);
1630  Handle<Object> result = args.CallAccessorGetter(info, name);
1631  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1632  if (result.is_null()) return isolate->factory()->undefined_value();
1633  Handle<Object> reboxed_result = handle(*result, isolate);
1634  if (info->replace_on_access() && receiver->IsJSReceiver()) {
1635  RETURN_ON_EXCEPTION(isolate,
1636  Accessors::ReplaceAccessorWithDataProperty(
1637  receiver, holder, name, result),
1638  Object);
1639  }
1640  return reboxed_result;
1641  }
1642 
1643  // AccessorPair with 'cached' private property.
1644  if (it->TryLookupCachedProperty()) {
1645  return Object::GetProperty(it);
1646  }
1647 
1648  // Regular accessor.
1649  Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1650  if (getter->IsFunctionTemplateInfo()) {
1651  SaveContext save(isolate);
1652  isolate->set_context(*holder->GetCreationContext());
1653  return Builtins::InvokeApiFunction(
1654  isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1655  nullptr, isolate->factory()->undefined_value());
1656  } else if (getter->IsCallable()) {
1657  // TODO(rossberg): nicer would be to cast to some JSCallable here...
1658  return Object::GetPropertyWithDefinedGetter(
1659  receiver, Handle<JSReceiver>::cast(getter));
1660  }
1661  // Getter is not a function.
1662  return isolate->factory()->undefined_value();
1663 }
1664 
1665 // static
1666 Address AccessorInfo::redirect(Address address, AccessorComponent component) {
1667  ApiFunction fun(address);
1668  DCHECK_EQ(ACCESSOR_GETTER, component);
1669  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1670  return ExternalReference::Create(&fun, type).address();
1671 }
1672 
1673 Address AccessorInfo::redirected_getter() const {
1674  Address accessor = v8::ToCData<Address>(getter());
1675  if (accessor == kNullAddress) return kNullAddress;
1676  return redirect(accessor, ACCESSOR_GETTER);
1677 }
1678 
1679 Address CallHandlerInfo::redirected_callback() const {
1680  Address address = v8::ToCData<Address>(callback());
1681  ApiFunction fun(address);
1682  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
1683  return ExternalReference::Create(&fun, type).address();
1684 }
1685 
1686 bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
1687  Handle<Map> map) {
1688  if (!info->HasExpectedReceiverType()) return true;
1689  if (!map->IsJSObjectMap()) return false;
1690  return FunctionTemplateInfo::cast(info->expected_receiver_type())
1691  ->IsTemplateFor(*map);
1692 }
1693 
1694 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
1695  Handle<Object> value,
1696  ShouldThrow should_throw) {
1697  Isolate* isolate = it->isolate();
1698  Handle<Object> structure = it->GetAccessors();
1699  Handle<Object> receiver = it->GetReceiver();
1700  // In case of global IC, the receiver is the global object. Replace by the
1701  // global proxy.
1702  if (receiver->IsJSGlobalObject()) {
1703  receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1704  }
1705 
1706  // We should never get here to initialize a const with the hole value since a
1707  // const declaration would conflict with the setter.
1708  DCHECK(!structure->IsForeign());
1709 
1710  // API style callbacks.
1711  Handle<JSObject> holder = it->GetHolder<JSObject>();
1712  if (structure->IsAccessorInfo()) {
1713  Handle<Name> name = it->GetName();
1714  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1715  if (!info->IsCompatibleReceiver(*receiver)) {
1716  isolate->Throw(*isolate->factory()->NewTypeError(
1717  MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1718  return Nothing<bool>();
1719  }
1720 
1721  if (!info->has_setter()) {
1722  // TODO(verwaest): We should not get here anymore once all AccessorInfos
1723  // are marked as special_data_property. They cannot both be writable and
1724  // not have a setter.
1725  return Just(true);
1726  }
1727 
1728  if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1729  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1730  isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1731  Nothing<bool>());
1732  }
1733 
1734  // The actual type of setter callback is either
1735  // v8::AccessorNameSetterCallback or
1736  // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
1737  // AccessorInfo was created by the API or internally (see accessors.cc).
1738  // Here we handle both cases using GenericNamedPropertySetterCallback and
1739  // its Call method.
1740  PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1741  should_throw);
1742  Handle<Object> result = args.CallAccessorSetter(info, name, value);
1743  // In the case of AccessorNameSetterCallback, we know that the result value
1744  // cannot have been set, so the result of Call will be null. In the case of
1745  // AccessorNameBooleanSetterCallback, the result will either be null
1746  // (signalling an exception) or a boolean Oddball.
1747  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1748  if (result.is_null()) return Just(true);
1749  DCHECK(result->BooleanValue(isolate) || should_throw == kDontThrow);
1750  return Just(result->BooleanValue(isolate));
1751  }
1752 
1753  // Regular accessor.
1754  Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1755  if (setter->IsFunctionTemplateInfo()) {
1756  SaveContext save(isolate);
1757  isolate->set_context(*holder->GetCreationContext());
1758  Handle<Object> argv[] = {value};
1759  RETURN_ON_EXCEPTION_VALUE(
1760  isolate, Builtins::InvokeApiFunction(
1761  isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
1762  receiver, arraysize(argv), argv,
1763  isolate->factory()->undefined_value()),
1764  Nothing<bool>());
1765  return Just(true);
1766  } else if (setter->IsCallable()) {
1767  // TODO(rossberg): nicer would be to cast to some JSCallable here...
1768  return SetPropertyWithDefinedSetter(
1769  receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
1770  }
1771 
1772  RETURN_FAILURE(isolate, should_throw,
1773  NewTypeError(MessageTemplate::kNoSetterInCallback,
1774  it->GetName(), it->GetHolder<JSObject>()));
1775 }
1776 
1777 
1778 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1779  Handle<Object> receiver,
1780  Handle<JSReceiver> getter) {
1781  Isolate* isolate = getter->GetIsolate();
1782 
1783  // Platforms with simulators like arm/arm64 expose a funny issue. If the
1784  // simulator has a separate JS stack pointer from the C++ stack pointer, it
1785  // can miss C++ stack overflows in the stack guard at the start of JavaScript
1786  // functions. It would be very expensive to check the C++ stack pointer at
1787  // that location. The best solution seems to be to break the impasse by
1788  // adding checks at possible recursion points. What's more, we don't put
1789  // this stack check behind the USE_SIMULATOR define in order to keep
1790  // behavior the same between hardware and simulators.
1791  StackLimitCheck check(isolate);
1792  if (check.JsHasOverflowed()) {
1793  isolate->StackOverflow();
1794  return MaybeHandle<Object>();
1795  }
1796 
1797  return Execution::Call(isolate, getter, receiver, 0, nullptr);
1798 }
1799 
1800 
1801 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
1802  Handle<JSReceiver> setter,
1803  Handle<Object> value,
1804  ShouldThrow should_throw) {
1805  Isolate* isolate = setter->GetIsolate();
1806 
1807  Handle<Object> argv[] = { value };
1808  RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1809  arraysize(argv), argv),
1810  Nothing<bool>());
1811  return Just(true);
1812 }
1813 
1814 
1815 // static
1816 bool JSObject::AllCanRead(LookupIterator* it) {
1817  // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
1818  // which have already been checked.
1819  DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
1820  it->state() == LookupIterator::INTERCEPTOR);
1821  for (it->Next(); it->IsFound(); it->Next()) {
1822  if (it->state() == LookupIterator::ACCESSOR) {
1823  auto accessors = it->GetAccessors();
1824  if (accessors->IsAccessorInfo()) {
1825  if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
1826  }
1827  } else if (it->state() == LookupIterator::INTERCEPTOR) {
1828  if (it->GetInterceptor()->all_can_read()) return true;
1829  } else if (it->state() == LookupIterator::JSPROXY) {
1830  // Stop lookupiterating. And no, AllCanNotRead.
1831  return false;
1832  }
1833  }
1834  return false;
1835 }
1836 
1837 namespace {
1838 
1839 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
1840  LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
1841  *done = false;
1842  Isolate* isolate = it->isolate();
1843  // Make sure that the top context does not change when doing callbacks or
1844  // interceptor calls.
1845  AssertNoContextChange ncc(isolate);
1846 
1847  if (interceptor->getter()->IsUndefined(isolate)) {
1848  return isolate->factory()->undefined_value();
1849  }
1850 
1851  Handle<JSObject> holder = it->GetHolder<JSObject>();
1852  Handle<Object> result;
1853  Handle<Object> receiver = it->GetReceiver();
1854  if (!receiver->IsJSReceiver()) {
1855  ASSIGN_RETURN_ON_EXCEPTION(
1856  isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
1857  }
1858  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1859  *holder, kDontThrow);
1860 
1861  if (it->IsElement()) {
1862  result = args.CallIndexedGetter(interceptor, it->index());
1863  } else {
1864  result = args.CallNamedGetter(interceptor, it->name());
1865  }
1866 
1867  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1868  if (result.is_null()) return isolate->factory()->undefined_value();
1869  *done = true;
1870  // Rebox handle before return
1871  return handle(*result, isolate);
1872 }
1873 
1874 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
1875  LookupIterator* it, Handle<InterceptorInfo> interceptor) {
1876  Isolate* isolate = it->isolate();
1877  // Make sure that the top context does not change when doing
1878  // callbacks or interceptor calls.
1879  AssertNoContextChange ncc(isolate);
1880  HandleScope scope(isolate);
1881 
1882  Handle<JSObject> holder = it->GetHolder<JSObject>();
1883  DCHECK_IMPLIES(!it->IsElement() && it->name()->IsSymbol(),
1884  interceptor->can_intercept_symbols());
1885  Handle<Object> receiver = it->GetReceiver();
1886  if (!receiver->IsJSReceiver()) {
1887  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1888  Object::ConvertReceiver(isolate, receiver),
1889  Nothing<PropertyAttributes>());
1890  }
1891  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1892  *holder, kDontThrow);
1893  if (!interceptor->query()->IsUndefined(isolate)) {
1894  Handle<Object> result;
1895  if (it->IsElement()) {
1896  result = args.CallIndexedQuery(interceptor, it->index());
1897  } else {
1898  result = args.CallNamedQuery(interceptor, it->name());
1899  }
1900  if (!result.is_null()) {
1901  int32_t value;
1902  CHECK(result->ToInt32(&value));
1903  return Just(static_cast<PropertyAttributes>(value));
1904  }
1905  } else if (!interceptor->getter()->IsUndefined(isolate)) {
1906  // TODO(verwaest): Use GetPropertyWithInterceptor?
1907  Handle<Object> result;
1908  if (it->IsElement()) {
1909  result = args.CallIndexedGetter(interceptor, it->index());
1910  } else {
1911  result = args.CallNamedGetter(interceptor, it->name());
1912  }
1913  if (!result.is_null()) return Just(DONT_ENUM);
1914  }
1915 
1916  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
1917  return Just(ABSENT);
1918 }
1919 
1920 Maybe<bool> SetPropertyWithInterceptorInternal(
1921  LookupIterator* it, Handle<InterceptorInfo> interceptor,
1922  ShouldThrow should_throw, Handle<Object> value) {
1923  Isolate* isolate = it->isolate();
1924  // Make sure that the top context does not change when doing callbacks or
1925  // interceptor calls.
1926  AssertNoContextChange ncc(isolate);
1927 
1928  if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
1929 
1930  Handle<JSObject> holder = it->GetHolder<JSObject>();
1931  bool result;
1932  Handle<Object> receiver = it->GetReceiver();
1933  if (!receiver->IsJSReceiver()) {
1934  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1935  Object::ConvertReceiver(isolate, receiver),
1936  Nothing<bool>());
1937  }
1938  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1939  *holder, should_throw);
1940 
1941  if (it->IsElement()) {
1942  // TODO(neis): In the future, we may want to actually return the
1943  // interceptor's result, which then should be a boolean.
1944  result = !args.CallIndexedSetter(interceptor, it->index(), value).is_null();
1945  } else {
1946  result = !args.CallNamedSetter(interceptor, it->name(), value).is_null();
1947  }
1948 
1949  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
1950  return Just(result);
1951 }
1952 
1953 Maybe<bool> DefinePropertyWithInterceptorInternal(
1954  LookupIterator* it, Handle<InterceptorInfo> interceptor,
1955  ShouldThrow should_throw, PropertyDescriptor& desc) {
1956  Isolate* isolate = it->isolate();
1957  // Make sure that the top context does not change when doing callbacks or
1958  // interceptor calls.
1959  AssertNoContextChange ncc(isolate);
1960 
1961  if (interceptor->definer()->IsUndefined(isolate)) return Just(false);
1962 
1963  Handle<JSObject> holder = it->GetHolder<JSObject>();
1964  bool result;
1965  Handle<Object> receiver = it->GetReceiver();
1966  if (!receiver->IsJSReceiver()) {
1967  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1968  Object::ConvertReceiver(isolate, receiver),
1969  Nothing<bool>());
1970  }
1971  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1972  *holder, should_throw);
1973 
1974  std::unique_ptr<v8::PropertyDescriptor> descriptor(
1975  new v8::PropertyDescriptor());
1976  if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
1977  descriptor.reset(new v8::PropertyDescriptor(
1978  v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
1979  } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
1980  if (desc.has_writable()) {
1981  descriptor.reset(new v8::PropertyDescriptor(
1982  v8::Utils::ToLocal(desc.value()), desc.writable()));
1983  } else {
1984  descriptor.reset(
1985  new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
1986  }
1987  }
1988  if (desc.has_enumerable()) {
1989  descriptor->set_enumerable(desc.enumerable());
1990  }
1991  if (desc.has_configurable()) {
1992  descriptor->set_configurable(desc.configurable());
1993  }
1994 
1995  if (it->IsElement()) {
1996  result = !args.CallIndexedDefiner(interceptor, it->index(), *descriptor)
1997  .is_null();
1998  } else {
1999  result =
2000  !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null();
2001  }
2002 
2003  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
2004  return Just(result);
2005 }
2006 
2007 } // namespace
2008 
2009 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
2010  LookupIterator* it) {
2011  Isolate* isolate = it->isolate();
2012  Handle<JSObject> checked = it->GetHolder<JSObject>();
2013  Handle<InterceptorInfo> interceptor =
2014  it->GetInterceptorForFailedAccessCheck();
2015  if (interceptor.is_null()) {
2016  while (AllCanRead(it)) {
2017  if (it->state() == LookupIterator::ACCESSOR) {
2018  return GetPropertyWithAccessor(it);
2019  }
2020  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
2021  bool done;
2022  Handle<Object> result;
2023  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
2024  GetPropertyWithInterceptor(it, &done), Object);
2025  if (done) return result;
2026  }
2027 
2028  } else {
2029  Handle<Object> result;
2030  bool done;
2031  ASSIGN_RETURN_ON_EXCEPTION(
2032  isolate, result,
2033  GetPropertyWithInterceptorInternal(it, interceptor, &done), Object);
2034  if (done) return result;
2035  }
2036 
2037  // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
2038  // undefined.
2039  Handle<Name> name = it->GetName();
2040  if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
2041  return it->factory()->undefined_value();
2042  }
2043 
2044  isolate->ReportFailedAccessCheck(checked);
2045  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2046  return it->factory()->undefined_value();
2047 }
2048 
2049 
2050 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
2051  LookupIterator* it) {
2052  Isolate* isolate = it->isolate();
2053  Handle<JSObject> checked = it->GetHolder<JSObject>();
2054  Handle<InterceptorInfo> interceptor =
2055  it->GetInterceptorForFailedAccessCheck();
2056  if (interceptor.is_null()) {
2057  while (AllCanRead(it)) {
2058  if (it->state() == LookupIterator::ACCESSOR) {
2059  return Just(it->property_attributes());
2060  }
2061  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
2062  auto result = GetPropertyAttributesWithInterceptor(it);
2063  if (isolate->has_scheduled_exception()) break;
2064  if (result.IsJust() && result.FromJust() != ABSENT) return result;
2065  }
2066  } else {
2067  Maybe<PropertyAttributes> result =
2068  GetPropertyAttributesWithInterceptorInternal(it, interceptor);
2069  if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>();
2070  if (result.FromMaybe(ABSENT) != ABSENT) return result;
2071  }
2072  isolate->ReportFailedAccessCheck(checked);
2073  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
2074  return Just(ABSENT);
2075 }
2076 
2077 
2078 // static
2079 bool JSObject::AllCanWrite(LookupIterator* it) {
2080  for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
2081  if (it->state() == LookupIterator::ACCESSOR) {
2082  Handle<Object> accessors = it->GetAccessors();
2083  if (accessors->IsAccessorInfo()) {
2084  if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
2085  }
2086  }
2087  }
2088  return false;
2089 }
2090 
2091 
2092 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
2093  LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
2094  Isolate* isolate = it->isolate();
2095  Handle<JSObject> checked = it->GetHolder<JSObject>();
2096  Handle<InterceptorInfo> interceptor =
2097  it->GetInterceptorForFailedAccessCheck();
2098  if (interceptor.is_null()) {
2099  if (AllCanWrite(it)) {
2100  return SetPropertyWithAccessor(it, value, should_throw);
2101  }
2102  } else {
2103  Maybe<bool> result = SetPropertyWithInterceptorInternal(
2104  it, interceptor, should_throw, value);
2105  if (isolate->has_pending_exception()) return Nothing<bool>();
2106  if (result.IsJust()) return result;
2107  }
2108  isolate->ReportFailedAccessCheck(checked);
2109  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
2110  return Just(true);
2111 }
2112 
2113 
2114 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
2115  Handle<Name> name,
2116  Handle<Object> value,
2117  PropertyDetails details) {
2118  DCHECK(!object->HasFastProperties());
2119  DCHECK(name->IsUniqueName());
2120  Isolate* isolate = object->GetIsolate();
2121 
2122  uint32_t hash = name->Hash();
2123 
2124  if (object->IsJSGlobalObject()) {
2125  Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object);
2126  Handle<GlobalDictionary> dictionary(global_obj->global_dictionary(),
2127  isolate);
2128  int entry = dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
2129 
2130  if (entry == GlobalDictionary::kNotFound) {
2131  DCHECK_IMPLIES(global_obj->map()->is_prototype_map(),
2132  Map::IsPrototypeChainInvalidated(global_obj->map()));
2133  auto cell = isolate->factory()->NewPropertyCell(name);
2134  cell->set_value(*value);
2135  auto cell_type = value->IsUndefined(isolate)
2136  ? PropertyCellType::kUndefined
2137  : PropertyCellType::kConstant;
2138  details = details.set_cell_type(cell_type);
2139  value = cell;
2140  dictionary =
2141  GlobalDictionary::Add(isolate, dictionary, name, value, details);
2142  global_obj->set_global_dictionary(*dictionary);
2143  } else {
2144  Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
2145  isolate, dictionary, entry, value, details);
2146  cell->set_value(*value);
2147  }
2148  } else {
2149  Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
2150 
2151  int entry = dictionary->FindEntry(isolate, name);
2152  if (entry == NameDictionary::kNotFound) {
2153  DCHECK_IMPLIES(object->map()->is_prototype_map(),
2154  Map::IsPrototypeChainInvalidated(object->map()));
2155  dictionary =
2156  NameDictionary::Add(isolate, dictionary, name, value, details);
2157  object->SetProperties(*dictionary);
2158  } else {
2159  PropertyDetails original_details = dictionary->DetailsAt(entry);
2160  int enumeration_index = original_details.dictionary_index();
2161  DCHECK_GT(enumeration_index, 0);
2162  details = details.set_index(enumeration_index);
2163  dictionary->SetEntry(isolate, entry, *name, *value, details);
2164  }
2165  }
2166 }
2167 
2168 // static
2169 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
2170  Handle<JSReceiver> object,
2171  Handle<Object> proto) {
2172  PrototypeIterator iter(isolate, object, kStartAtReceiver);
2173  while (true) {
2174  if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
2175  if (iter.IsAtEnd()) return Just(false);
2176  if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
2177  return Just(true);
2178  }
2179  }
2180 }
2181 
2182 namespace {
2183 
2184 bool HasExcludedProperty(
2185  const ScopedVector<Handle<Object>>* excluded_properties,
2186  Handle<Object> search_element) {
2187  // TODO(gsathya): Change this to be a hashtable.
2188  for (int i = 0; i < excluded_properties->length(); i++) {
2189  if (search_element->SameValue(*excluded_properties->at(i))) {
2190  return true;
2191  }
2192  }
2193 
2194  return false;
2195 }
2196 
2197 V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
2198  Handle<JSReceiver> target, Handle<Object> source,
2199  const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
2200  // Non-empty strings are the only non-JSReceivers that need to be handled
2201  // explicitly by Object.assign.
2202  if (!source->IsJSReceiver()) {
2203  return Just(!source->IsString() || String::cast(*source)->length() == 0);
2204  }
2205 
2206  // If the target is deprecated, the object will be updated on first store. If
2207  // the source for that store equals the target, this will invalidate the
2208  // cached representation of the source. Preventively upgrade the target.
2209  // Do this on each iteration since any property load could cause deprecation.
2210  if (target->map()->is_deprecated()) {
2211  JSObject::MigrateInstance(Handle<JSObject>::cast(target));
2212  }
2213 
2214  Isolate* isolate = target->GetIsolate();
2215  Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
2216 
2217  if (!map->IsJSObjectMap()) return Just(false);
2218  if (!map->OnlyHasSimpleProperties()) return Just(false);
2219 
2220  Handle<JSObject> from = Handle<JSObject>::cast(source);
2221  if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
2222  return Just(false);
2223  }
2224 
2225  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
2226  int length = map->NumberOfOwnDescriptors();
2227 
2228  bool stable = true;
2229 
2230  for (int i = 0; i < length; i++) {
2231  Handle<Name> next_key(descriptors->GetKey(i), isolate);
2232  Handle<Object> prop_value;
2233  // Directly decode from the descriptor array if |from| did not change shape.
2234  if (stable) {
2235  PropertyDetails details = descriptors->GetDetails(i);
2236  if (!details.IsEnumerable()) continue;
2237  if (details.kind() == kData) {
2238  if (details.location() == kDescriptor) {
2239  prop_value = handle(descriptors->GetStrongValue(i), isolate);
2240  } else {
2241  Representation representation = details.representation();
2242  FieldIndex index = FieldIndex::ForDescriptor(*map, i);
2243  prop_value = JSObject::FastPropertyAt(from, representation, index);
2244  }
2245  } else {
2246  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2247  isolate, prop_value,
2248  JSReceiver::GetProperty(isolate, from, next_key), Nothing<bool>());
2249  stable = from->map() == *map;
2250  }
2251  } else {
2252  // If the map did change, do a slower lookup. We are still guaranteed that
2253  // the object has a simple shape, and that the key is a name.
2254  LookupIterator it(from, next_key, from,
2255  LookupIterator::OWN_SKIP_INTERCEPTOR);
2256  if (!it.IsFound()) continue;
2257  DCHECK(it.state() == LookupIterator::DATA ||
2258  it.state() == LookupIterator::ACCESSOR);
2259  if (!it.IsEnumerable()) continue;
2260  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2261  isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
2262  }
2263 
2264  if (use_set) {
2265  LookupIterator it(target, next_key, target);
2266  Maybe<bool> result = Object::SetProperty(
2267  &it, prop_value, LanguageMode::kStrict, StoreOrigin::kNamed);
2268  if (result.IsNothing()) return result;
2269  if (stable) stable = from->map() == *map;
2270  } else {
2271  if (excluded_properties != nullptr &&
2272  HasExcludedProperty(excluded_properties, next_key)) {
2273  continue;
2274  }
2275 
2276  // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
2277  bool success;
2278  LookupIterator it = LookupIterator::PropertyOrElement(
2279  isolate, target, next_key, &success, LookupIterator::OWN);
2280  CHECK(success);
2281  CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
2282  .FromJust());
2283  }
2284  }
2285 
2286  return Just(true);
2287 }
2288 } // namespace
2289 
2290 // static
2291 Maybe<bool> JSReceiver::SetOrCopyDataProperties(
2292  Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
2293  const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
2294  Maybe<bool> fast_assign =
2295  FastAssign(target, source, excluded_properties, use_set);
2296  if (fast_assign.IsNothing()) return Nothing<bool>();
2297  if (fast_assign.FromJust()) return Just(true);
2298 
2299  Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
2300  // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
2301  Handle<FixedArray> keys;
2302  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2303  isolate, keys,
2304  KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2305  GetKeysConversion::kKeepNumbers),
2306  Nothing<bool>());
2307 
2308  // 4. Repeat for each element nextKey of keys in List order,
2309  for (int j = 0; j < keys->length(); ++j) {
2310  Handle<Object> next_key(keys->get(j), isolate);
2311  // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
2312  PropertyDescriptor desc;
2313  Maybe<bool> found =
2314  JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
2315  if (found.IsNothing()) return Nothing<bool>();
2316  // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
2317  if (found.FromJust() && desc.enumerable()) {
2318  // 4a ii 1. Let propValue be ? Get(from, nextKey).
2319  Handle<Object> prop_value;
2320  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2321  isolate, prop_value,
2322  Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
2323 
2324  if (use_set) {
2325  // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
2326  Handle<Object> status;
2327  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2328  isolate, status,
2329  Runtime::SetObjectProperty(isolate, target, next_key, prop_value,
2330  LanguageMode::kStrict,
2331  StoreOrigin::kMaybeKeyed),
2332  Nothing<bool>());
2333  } else {
2334  if (excluded_properties != nullptr &&
2335  HasExcludedProperty(excluded_properties, next_key)) {
2336  continue;
2337  }
2338 
2339  // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue).
2340  bool success;
2341  LookupIterator it = LookupIterator::PropertyOrElement(
2342  isolate, target, next_key, &success, LookupIterator::OWN);
2343  CHECK(success);
2344  CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
2345  .FromJust());
2346  }
2347  }
2348  }
2349 
2350  return Just(true);
2351 }
2352 
2353 Map Object::GetPrototypeChainRootMap(Isolate* isolate) const {
2354  DisallowHeapAllocation no_alloc;
2355  if (IsSmi()) {
2356  Context native_context = isolate->context()->native_context();
2357  return native_context->number_function()->initial_map();
2358  }
2359 
2360  const HeapObject* heap_object = HeapObject::cast(this);
2361  return heap_object->map()->GetPrototypeChainRootMap(isolate);
2362 }
2363 
2364 Map Map::GetPrototypeChainRootMap(Isolate* isolate) const {
2365  DisallowHeapAllocation no_alloc;
2366  if (IsJSReceiverMap()) {
2367  return *this;
2368  }
2369  int constructor_function_index = GetConstructorFunctionIndex();
2370  if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
2371  Context native_context = isolate->context()->native_context();
2372  JSFunction* constructor_function =
2373  JSFunction::cast(native_context->get(constructor_function_index));
2374  return constructor_function->initial_map();
2375  }
2376  return ReadOnlyRoots(isolate).null_value()->map();
2377 }
2378 
2379 Smi Object::GetOrCreateHash(Isolate* isolate) {
2380  DisallowHeapAllocation no_gc;
2381  Object* hash = Object::GetSimpleHash(this);
2382  if (hash->IsSmi()) return Smi::cast(hash);
2383 
2384  DCHECK(IsJSReceiver());
2385  return JSReceiver::cast(this)->GetOrCreateIdentityHash(isolate);
2386 }
2387 
2388 Smi ObjectPtr::GetOrCreateHash(Isolate* isolate) {
2389  return reinterpret_cast<Object*>(ptr())->GetOrCreateHash(isolate);
2390 }
2391 
2392 bool Object::SameValue(Object* other) {
2393  if (other == this) return true;
2394 
2395  if (IsNumber() && other->IsNumber()) {
2396  double this_value = Number();
2397  double other_value = other->Number();
2398  // SameValue(NaN, NaN) is true.
2399  if (this_value != other_value) {
2400  return std::isnan(this_value) && std::isnan(other_value);
2401  }
2402  // SameValue(0.0, -0.0) is false.
2403  return (std::signbit(this_value) == std::signbit(other_value));
2404  }
2405  if (IsString() && other->IsString()) {
2406  return String::cast(this)->Equals(String::cast(other));
2407  }
2408  if (IsBigInt() && other->IsBigInt()) {
2409  return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(other));
2410  }
2411  return false;
2412 }
2413 
2414 bool ObjectPtr::SameValue(Object* other) {
2415  return reinterpret_cast<Object*>(ptr())->SameValue(other);
2416 }
2417 
2418 bool Object::SameValueZero(Object* other) {
2419  if (other == this) return true;
2420 
2421  if (IsNumber() && other->IsNumber()) {
2422  double this_value = Number();
2423  double other_value = other->Number();
2424  // +0 == -0 is true
2425  return this_value == other_value ||
2426  (std::isnan(this_value) && std::isnan(other_value));
2427  }
2428  if (IsString() && other->IsString()) {
2429  return String::cast(this)->Equals(String::cast(other));
2430  }
2431  if (IsBigInt() && other->IsBigInt()) {
2432  return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(other));
2433  }
2434  return false;
2435 }
2436 
2437 
2438 MaybeHandle<Object> Object::ArraySpeciesConstructor(
2439  Isolate* isolate, Handle<Object> original_array) {
2440  Handle<Object> default_species = isolate->array_function();
2441  if (original_array->IsJSArray() &&
2442  Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
2443  isolate->IsArraySpeciesLookupChainIntact()) {
2444  return default_species;
2445  }
2446  Handle<Object> constructor = isolate->factory()->undefined_value();
2447  Maybe<bool> is_array = Object::IsArray(original_array);
2448  MAYBE_RETURN_NULL(is_array);
2449  if (is_array.FromJust()) {
2450  ASSIGN_RETURN_ON_EXCEPTION(
2451  isolate, constructor,
2452  Object::GetProperty(isolate, original_array,
2453  isolate->factory()->constructor_string()),
2454  Object);
2455  if (constructor->IsConstructor()) {
2456  Handle<Context> constructor_context;
2457  ASSIGN_RETURN_ON_EXCEPTION(
2458  isolate, constructor_context,
2459  JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
2460  Object);
2461  if (*constructor_context != *isolate->native_context() &&
2462  *constructor == constructor_context->array_function()) {
2463  constructor = isolate->factory()->undefined_value();
2464  }
2465  }
2466  if (constructor->IsJSReceiver()) {
2467  ASSIGN_RETURN_ON_EXCEPTION(
2468  isolate, constructor,
2469  JSReceiver::GetProperty(isolate,
2470  Handle<JSReceiver>::cast(constructor),
2471  isolate->factory()->species_symbol()),
2472  Object);
2473  if (constructor->IsNull(isolate)) {
2474  constructor = isolate->factory()->undefined_value();
2475  }
2476  }
2477  }
2478  if (constructor->IsUndefined(isolate)) {
2479  return default_species;
2480  } else {
2481  if (!constructor->IsConstructor()) {
2482  THROW_NEW_ERROR(isolate,
2483  NewTypeError(MessageTemplate::kSpeciesNotConstructor),
2484  Object);
2485  }
2486  return constructor;
2487  }
2488 }
2489 
2490 // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
2491 V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
2492  Isolate* isolate, Handle<JSReceiver> recv,
2493  Handle<JSFunction> default_ctor) {
2494  Handle<Object> ctor_obj;
2495  ASSIGN_RETURN_ON_EXCEPTION(
2496  isolate, ctor_obj,
2497  JSObject::GetProperty(isolate, recv,
2498  isolate->factory()->constructor_string()),
2499  Object);
2500 
2501  if (ctor_obj->IsUndefined(isolate)) return default_ctor;
2502 
2503  if (!ctor_obj->IsJSReceiver()) {
2504  THROW_NEW_ERROR(isolate,
2505  NewTypeError(MessageTemplate::kConstructorNotReceiver),
2506  Object);
2507  }
2508 
2509  Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
2510 
2511  Handle<Object> species;
2512  ASSIGN_RETURN_ON_EXCEPTION(
2513  isolate, species,
2514  JSObject::GetProperty(isolate, ctor,
2515  isolate->factory()->species_symbol()),
2516  Object);
2517 
2518  if (species->IsNullOrUndefined(isolate)) {
2519  return default_ctor;
2520  }
2521 
2522  if (species->IsConstructor()) return species;
2523 
2524  THROW_NEW_ERROR(
2525  isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
2526 }
2527 
2528 bool Object::IterationHasObservableEffects() {
2529  // Check that this object is an array.
2530  if (!IsJSArray()) return true;
2531  JSArray* array = JSArray::cast(this);
2532  Isolate* isolate = array->GetIsolate();
2533 
2534 #ifdef V8_ENABLE_FORCE_SLOW_PATH
2535  if (isolate->force_slow_path()) return true;
2536 #endif
2537 
2538  // Check that we have the original ArrayPrototype.
2539  if (!array->map()->prototype()->IsJSObject()) return true;
2540  JSObject* array_proto = JSObject::cast(array->map()->prototype());
2541  if (!isolate->is_initial_array_prototype(array_proto)) return true;
2542 
2543  // Check that the ArrayPrototype hasn't been modified in a way that would
2544  // affect iteration.
2545  if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
2546 
2547  // For FastPacked kinds, iteration will have the same effect as simply
2548  // accessing each property in order.
2549  ElementsKind array_kind = array->GetElementsKind();
2550  if (IsFastPackedElementsKind(array_kind)) return false;
2551 
2552  // For FastHoley kinds, an element access on a hole would cause a lookup on
2553  // the prototype. This could have different results if the prototype has been
2554  // changed.
2555  if (IsHoleyElementsKind(array_kind) &&
2556  isolate->IsNoElementsProtectorIntact()) {
2557  return false;
2558  }
2559  return true;
2560 }
2561 
2562 void Object::ShortPrint(FILE* out) {
2563  OFStream os(out);
2564  os << Brief(this);
2565 }
2566 
2567 
2568 void Object::ShortPrint(StringStream* accumulator) {
2569  std::ostringstream os;
2570  os << Brief(this);
2571  accumulator->Add(os.str().c_str());
2572 }
2573 
2574 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
2575 
2576 void ObjectPtr::ShortPrint(std::ostream& os) { os << Brief(*this); }
2577 
2578 void MaybeObject::ShortPrint(FILE* out) {
2579  OFStream os(out);
2580  os << Brief(*this);
2581 }
2582 
2583 void MaybeObject::ShortPrint(StringStream* accumulator) {
2584  std::ostringstream os;
2585  os << Brief(*this);
2586  accumulator->Add(os.str().c_str());
2587 }
2588 
2589 void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(*this); }
2590 
2591 Brief::Brief(const Object* v) : value(v->ptr()) {}
2592 Brief::Brief(const MaybeObject v) : value(v.ptr()) {}
2593 
2594 std::ostream& operator<<(std::ostream& os, const Brief& v) {
2595  MaybeObject maybe_object(v.value);
2596  Smi smi;
2597  HeapObject* heap_object;
2598  if (maybe_object->ToSmi(&smi)) {
2599  smi->SmiPrint(os);
2600  } else if (maybe_object->IsCleared()) {
2601  os << "[cleared]";
2602  } else if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
2603  os << "[weak] ";
2604  heap_object->HeapObjectShortPrint(os);
2605  } else if (maybe_object->GetHeapObjectIfStrong(&heap_object)) {
2606  heap_object->HeapObjectShortPrint(os);
2607  } else {
2608  UNREACHABLE();
2609  }
2610  return os;
2611 }
2612 
2613 void Smi::SmiPrint(std::ostream& os) const { // NOLINT
2614  os << value();
2615 }
2616 
2617 Handle<String> String::SlowFlatten(Isolate* isolate, Handle<ConsString> cons,
2618  PretenureFlag pretenure) {
2619  DCHECK_NE(cons->second()->length(), 0);
2620 
2621  // TurboFan can create cons strings with empty first parts.
2622  while (cons->first()->length() == 0) {
2623  // We do not want to call this function recursively. Therefore we call
2624  // String::Flatten only in those cases where String::SlowFlatten is not
2625  // called again.
2626  if (cons->second()->IsConsString() && !cons->second()->IsFlat()) {
2627  cons = handle(ConsString::cast(cons->second()), isolate);
2628  } else {
2629  return String::Flatten(isolate, handle(cons->second(), isolate));
2630  }
2631  }
2632 
2633  DCHECK(AllowHeapAllocation::IsAllowed());
2634  int length = cons->length();
2635  PretenureFlag tenure = Heap::InNewSpace(*cons) ? pretenure : TENURED;
2636  Handle<SeqString> result;
2637  if (cons->IsOneByteRepresentation()) {
2638  Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
2639  length, tenure).ToHandleChecked();
2640  DisallowHeapAllocation no_gc;
2641  WriteToFlat(*cons, flat->GetChars(), 0, length);
2642  result = flat;
2643  } else {
2644  Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
2645  length, tenure).ToHandleChecked();
2646  DisallowHeapAllocation no_gc;
2647  WriteToFlat(*cons, flat->GetChars(), 0, length);
2648  result = flat;
2649  }
2650  cons->set_first(isolate, *result);
2651  cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
2652  DCHECK(result->IsFlat());
2653  return result;
2654 }
2655 
2656 
2657 
2658 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
2659  DisallowHeapAllocation no_allocation;
2660  // Externalizing twice leaks the external resource, so it's
2661  // prohibited by the API.
2662  DCHECK(this->SupportsExternalization());
2663  DCHECK(resource->IsCacheable());
2664 #ifdef ENABLE_SLOW_DCHECKS
2665  if (FLAG_enable_slow_asserts) {
2666  // Assert that the resource and the string are equivalent.
2667  DCHECK(static_cast<size_t>(this->length()) == resource->length());
2668  ScopedVector<uc16> smart_chars(this->length());
2669  String::WriteToFlat(*this, smart_chars.start(), 0, this->length());
2670  DCHECK_EQ(0, memcmp(smart_chars.start(), resource->data(),
2671  resource->length() * sizeof(smart_chars[0])));
2672  }
2673 #endif // DEBUG
2674  int size = this->Size(); // Byte size of the original string.
2675  // Abort if size does not allow in-place conversion.
2676  if (size < ExternalString::kUncachedSize) return false;
2677  Isolate* isolate;
2678  // Read-only strings cannot be made external, since that would mutate the
2679  // string.
2680  if (!Isolate::FromWritableHeapObject(*this, &isolate)) return false;
2681  Heap* heap = isolate->heap();
2682  bool is_one_byte = this->IsOneByteRepresentation();
2683  bool is_internalized = this->IsInternalizedString();
2684  bool has_pointers = StringShape(*this).IsIndirect();
2685  if (has_pointers) {
2686  heap->NotifyObjectLayoutChange(*this, size, no_allocation);
2687  }
2688  // Morph the string to an external string by replacing the map and
2689  // reinitializing the fields. This won't work if the space the existing
2690  // string occupies is too small for a regular external string. Instead, we
2691  // resort to an uncached external string instead, omitting the field caching
2692  // the address of the backing store. When we encounter uncached external
2693  // strings in generated code, we need to bailout to runtime.
2694  Map new_map;
2695  ReadOnlyRoots roots(heap);
2696  if (size < ExternalString::kSize) {
2697  if (is_internalized) {
2698  if (is_one_byte) {
2699  new_map =
2700  roots
2701  .uncached_external_internalized_string_with_one_byte_data_map();
2702  } else {
2703  new_map = roots.uncached_external_internalized_string_map();
2704  }
2705  } else {
2706  new_map = is_one_byte
2707  ? roots.uncached_external_string_with_one_byte_data_map()
2708  : roots.uncached_external_string_map();
2709  }
2710  } else {
2711  new_map =
2712  is_internalized
2713  ? (is_one_byte
2714  ? roots.external_internalized_string_with_one_byte_data_map()
2715  : roots.external_internalized_string_map())
2716  : (is_one_byte ? roots.external_string_with_one_byte_data_map()
2717  : roots.external_string_map());
2718  }
2719 
2720  // Byte size of the external String object.
2721  int new_size = this->SizeFromMap(new_map);
2722  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2723  ClearRecordedSlots::kNo);
2724  if (has_pointers) {
2725  heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
2726  }
2727 
2728  // We are storing the new map using release store after creating a filler for
2729  // the left-over space to avoid races with the sweeper thread.
2730  this->synchronized_set_map(new_map);
2731 
2732  ExternalTwoByteString self = ExternalTwoByteString::cast(*this);
2733  self->SetResource(isolate, resource);
2734  heap->RegisterExternalString(*this);
2735  if (is_internalized) self->Hash(); // Force regeneration of the hash value.
2736  return true;
2737 }
2738 
2739 
2740 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
2741  DisallowHeapAllocation no_allocation;
2742  // Externalizing twice leaks the external resource, so it's
2743  // prohibited by the API.
2744  DCHECK(this->SupportsExternalization());
2745  DCHECK(resource->IsCacheable());
2746 #ifdef ENABLE_SLOW_DCHECKS
2747  if (FLAG_enable_slow_asserts) {
2748  // Assert that the resource and the string are equivalent.
2749  DCHECK(static_cast<size_t>(this->length()) == resource->length());
2750  if (this->IsTwoByteRepresentation()) {
2751  ScopedVector<uint16_t> smart_chars(this->length());
2752  String::WriteToFlat(*this, smart_chars.start(), 0, this->length());
2753  DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
2754  }
2755  ScopedVector<char> smart_chars(this->length());
2756  String::WriteToFlat(*this, smart_chars.start(), 0, this->length());
2757  DCHECK_EQ(0, memcmp(smart_chars.start(), resource->data(),
2758  resource->length() * sizeof(smart_chars[0])));
2759  }
2760 #endif // DEBUG
2761  int size = this->Size(); // Byte size of the original string.
2762  // Abort if size does not allow in-place conversion.
2763  if (size < ExternalString::kUncachedSize) return false;
2764  Isolate* isolate;
2765  // Read-only strings cannot be made external, since that would mutate the
2766  // string.
2767  if (!Isolate::FromWritableHeapObject(*this, &isolate)) return false;
2768  Heap* heap = isolate->heap();
2769  bool is_internalized = this->IsInternalizedString();
2770  bool has_pointers = StringShape(*this).IsIndirect();
2771 
2772  if (has_pointers) {
2773  heap->NotifyObjectLayoutChange(*this, size, no_allocation);
2774  }
2775 
2776  // Morph the string to an external string by replacing the map and
2777  // reinitializing the fields. This won't work if the space the existing
2778  // string occupies is too small for a regular external string. Instead, we
2779  // resort to an uncached external string instead, omitting the field caching
2780  // the address of the backing store. When we encounter uncached external
2781  // strings in generated code, we need to bailout to runtime.
2782  Map new_map;
2783  ReadOnlyRoots roots(heap);
2784  if (size < ExternalString::kSize) {
2785  new_map = is_internalized
2786  ? roots.uncached_external_one_byte_internalized_string_map()
2787  : roots.uncached_external_one_byte_string_map();
2788  } else {
2789  new_map = is_internalized
2790  ? roots.external_one_byte_internalized_string_map()
2791  : roots.external_one_byte_string_map();
2792  }
2793 
2794  // Byte size of the external String object.
2795  int new_size = this->SizeFromMap(new_map);
2796  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2797  ClearRecordedSlots::kNo);
2798  if (has_pointers) {
2799  heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
2800  }
2801 
2802  // We are storing the new map using release store after creating a filler for
2803  // the left-over space to avoid races with the sweeper thread.
2804  this->synchronized_set_map(new_map);
2805 
2806  ExternalOneByteString self = ExternalOneByteString::cast(*this);
2807  self->SetResource(isolate, resource);
2808  heap->RegisterExternalString(*this);
2809  if (is_internalized) self->Hash(); // Force regeneration of the hash value.
2810  return true;
2811 }
2812 
2813 bool String::SupportsExternalization() {
2814  if (this->IsThinString()) {
2815  return i::ThinString::cast(*this)->actual()->SupportsExternalization();
2816  }
2817 
2818  Isolate* isolate;
2819  // RO_SPACE strings cannot be externalized.
2820  if (!Isolate::FromWritableHeapObject(*this, &isolate)) {
2821  return false;
2822  }
2823 
2824  // Already an external string.
2825  if (StringShape(*this).IsExternal()) {
2826  return false;
2827  }
2828 
2829  return !isolate->heap()->IsInGCPostProcessing();
2830 }
2831 
2832 void String::StringShortPrint(StringStream* accumulator, bool show_details) {
2833  int len = length();
2834  if (len > kMaxShortPrintLength) {
2835  accumulator->Add("<Very long string[%u]>", len);
2836  return;
2837  }
2838 
2839  if (!LooksValid()) {
2840  accumulator->Add("<Invalid String>");
2841  return;
2842  }
2843 
2844  StringCharacterStream stream(*this);
2845 
2846  bool truncated = false;
2847  if (len > kMaxShortPrintLength) {
2848  len = kMaxShortPrintLength;
2849  truncated = true;
2850  }
2851  bool one_byte = true;
2852  for (int i = 0; i < len; i++) {
2853  uint16_t c = stream.GetNext();
2854 
2855  if (c < 32 || c >= 127) {
2856  one_byte = false;
2857  }
2858  }
2859  stream.Reset(*this);
2860  if (one_byte) {
2861  if (show_details) accumulator->Add("<String[%u]: ", length());
2862  for (int i = 0; i < len; i++) {
2863  accumulator->Put(static_cast<char>(stream.GetNext()));
2864  }
2865  if (show_details) accumulator->Put('>');
2866  } else {
2867  // Backslash indicates that the string contains control
2868  // characters and that backslashes are therefore escaped.
2869  if (show_details) accumulator->Add("<String[%u]\\: ", length());
2870  for (int i = 0; i < len; i++) {
2871  uint16_t c = stream.GetNext();
2872  if (c == '\n') {
2873  accumulator->Add("\\n");
2874  } else if (c == '\r') {
2875  accumulator->Add("\\r");
2876  } else if (c == '\\') {
2877  accumulator->Add("\\\\");
2878  } else if (c < 32 || c > 126) {
2879  accumulator->Add("\\x%02x", c);
2880  } else {
2881  accumulator->Put(static_cast<char>(c));
2882  }
2883  }
2884  if (truncated) {
2885  accumulator->Put('.');
2886  accumulator->Put('.');
2887  accumulator->Put('.');
2888  }
2889  if (show_details) accumulator->Put('>');
2890  }
2891  return;
2892 }
2893 
2894 
2895 void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
2896  if (end < 0) end = length();
2897  StringCharacterStream stream(*this, start);
2898  for (int i = start; i < end && stream.HasMore(); i++) {
2899  os << AsUC16(stream.GetNext());
2900  }
2901 }
2902 
2903 
2904 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
2905  switch (map()->instance_type()) {
2906  case JS_ARRAY_TYPE: {
2907  double length = JSArray::cast(this)->length()->IsUndefined()
2908  ? 0
2909  : JSArray::cast(this)->length()->Number();
2910  accumulator->Add("<JSArray[%u]>", static_cast<uint32_t>(length));
2911  break;
2912  }
2913  case JS_BOUND_FUNCTION_TYPE: {
2914  JSBoundFunction* bound_function = JSBoundFunction::cast(this);
2915  accumulator->Add("<JSBoundFunction");
2916  accumulator->Add(
2917  " (BoundTargetFunction %p)>",
2918  reinterpret_cast<void*>(bound_function->bound_target_function()));
2919  break;
2920  }
2921  case JS_WEAK_MAP_TYPE: {
2922  accumulator->Add("<JSWeakMap>");
2923  break;
2924  }
2925  case JS_WEAK_SET_TYPE: {
2926  accumulator->Add("<JSWeakSet>");
2927  break;
2928  }
2929  case JS_REGEXP_TYPE: {
2930  accumulator->Add("<JSRegExp");
2931  JSRegExp* regexp = JSRegExp::cast(this);
2932  if (regexp->source()->IsString()) {
2933  accumulator->Add(" ");
2934  String::cast(regexp->source())->StringShortPrint(accumulator);
2935  }
2936  accumulator->Add(">");
2937 
2938  break;
2939  }
2940  case JS_FUNCTION_TYPE: {
2941  JSFunction* function = JSFunction::cast(this);
2942  Object* fun_name = function->shared()->DebugName();
2943  bool printed = false;
2944  if (fun_name->IsString()) {
2945  String str = String::cast(fun_name);
2946  if (str->length() > 0) {
2947  accumulator->Add("<JSFunction ");
2948  accumulator->Put(str);
2949  printed = true;
2950  }
2951  }
2952  if (!printed) {
2953  accumulator->Add("<JSFunction");
2954  }
2955  if (FLAG_trace_file_names) {
2956  Object* source_name =
2957  Script::cast(function->shared()->script())->name();
2958  if (source_name->IsString()) {
2959  String str = String::cast(source_name);
2960  if (str->length() > 0) {
2961  accumulator->Add(" <");
2962  accumulator->Put(str);
2963  accumulator->Add(">");
2964  }
2965  }
2966  }
2967  accumulator->Add(" (sfi = %p)",
2968  reinterpret_cast<void*>(function->shared()));
2969  accumulator->Put('>');
2970  break;
2971  }
2972  case JS_GENERATOR_OBJECT_TYPE: {
2973  accumulator->Add("<JSGenerator>");
2974  break;
2975  }
2976  case JS_ASYNC_FUNCTION_OBJECT_TYPE: {
2977  accumulator->Add("<JSAsyncFunctionObject>");
2978  break;
2979  }
2980  case JS_ASYNC_GENERATOR_OBJECT_TYPE: {
2981  accumulator->Add("<JS AsyncGenerator>");
2982  break;
2983  }
2984 
2985  // All other JSObjects are rather similar to each other (JSObject,
2986  // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
2987  default: {
2988  Map map_of_this = map();
2989  Heap* heap = GetHeap();
2990  Object* constructor = map_of_this->GetConstructor();
2991  bool printed = false;
2992  if (constructor->IsHeapObject() &&
2993  !heap->Contains(HeapObject::cast(constructor))) {
2994  accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
2995  } else {
2996  bool global_object = IsJSGlobalProxy();
2997  if (constructor->IsJSFunction()) {
2998  if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
2999  accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
3000  } else {
3001  String constructor_name =
3002  JSFunction::cast(constructor)->shared()->Name();
3003  if (constructor_name->length() > 0) {
3004  accumulator->Add(global_object ? "<GlobalObject " : "<");
3005  accumulator->Put(constructor_name);
3006  accumulator->Add(
3007  " %smap = %p",
3008  map_of_this->is_deprecated() ? "deprecated-" : "",
3009  map_of_this);
3010  printed = true;
3011  }
3012  }
3013  } else if (constructor->IsFunctionTemplateInfo()) {
3014  accumulator->Add(global_object ? "<RemoteObject>" : "<RemoteObject>");
3015  printed = true;
3016  }
3017  if (!printed) {
3018  accumulator->Add("<JS%sObject", global_object ? "Global " : "");
3019  }
3020  }
3021  if (IsJSValue()) {
3022  accumulator->Add(" value = ");
3023  JSValue::cast(this)->value()->ShortPrint(accumulator);
3024  }
3025  accumulator->Put('>');
3026  break;
3027  }
3028  }
3029 }
3030 
3031 
3032 void JSObject::PrintElementsTransition(
3033  FILE* file, Handle<JSObject> object,
3034  ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
3035  ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
3036  if (from_kind != to_kind) {
3037  OFStream os(file);
3038  os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
3039  << ElementsKindToString(to_kind) << "] in ";
3040  JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
3041  PrintF(file, " for ");
3042  object->ShortPrint(file);
3043  PrintF(file, " from ");
3044  from_elements->ShortPrint(file);
3045  PrintF(file, " to ");
3046  to_elements->ShortPrint(file);
3047  PrintF(file, "\n");
3048  }
3049 }
3050 
3051 
3052 // static
3053 MaybeHandle<JSFunction> Map::GetConstructorFunction(
3054  Handle<Map> map, Handle<Context> native_context) {
3055  if (map->IsPrimitiveMap()) {
3056  int const constructor_function_index = map->GetConstructorFunctionIndex();
3057  if (constructor_function_index != kNoConstructorFunctionIndex) {
3058  return handle(
3059  JSFunction::cast(native_context->get(constructor_function_index)),
3060  native_context->GetIsolate());
3061  }
3062  }
3063  return MaybeHandle<JSFunction>();
3064 }
3065 
3066 void Map::PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index,
3067  PropertyKind kind,
3068  PropertyAttributes attributes) {
3069  OFStream os(file);
3070  os << "[reconfiguring]";
3071  Name name = instance_descriptors()->GetKey(modify_index);
3072  if (name->IsString()) {
3073  String::cast(name)->PrintOn(file);
3074  } else {
3075  os << "{symbol " << reinterpret_cast<void*>(name.ptr()) << "}";
3076  }
3077  os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
3078  os << attributes << " [";
3079  JavaScriptFrame::PrintTop(isolate, file, false, true);
3080  os << "]\n";
3081 }
3082 
3083 VisitorId Map::GetVisitorId(Map map) {
3084  STATIC_ASSERT(kVisitorIdCount <= 256);
3085 
3086  const int instance_type = map->instance_type();
3087  const bool has_unboxed_fields =
3088  FLAG_unbox_double_fields && !map->HasFastPointerLayout();
3089  if (instance_type < FIRST_NONSTRING_TYPE) {
3090  switch (instance_type & kStringRepresentationMask) {
3091  case kSeqStringTag:
3092  if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
3093  return kVisitSeqOneByteString;
3094  } else {
3095  return kVisitSeqTwoByteString;
3096  }
3097 
3098  case kConsStringTag:
3099  if (IsShortcutCandidate(instance_type)) {
3100  return kVisitShortcutCandidate;
3101  } else {
3102  return kVisitConsString;
3103  }
3104 
3105  case kSlicedStringTag:
3106  return kVisitSlicedString;
3107 
3108  case kExternalStringTag:
3109  return kVisitDataObject;
3110 
3111  case kThinStringTag:
3112  return kVisitThinString;
3113  }
3114  UNREACHABLE();
3115  }
3116 
3117  switch (instance_type) {
3118  case BYTE_ARRAY_TYPE:
3119  return kVisitByteArray;
3120 
3121  case BYTECODE_ARRAY_TYPE:
3122  return kVisitBytecodeArray;
3123 
3124  case FREE_SPACE_TYPE:
3125  return kVisitFreeSpace;
3126 
3127  case EMBEDDER_DATA_ARRAY_TYPE:
3128  return kVisitEmbedderDataArray;
3129 
3130  case FIXED_ARRAY_TYPE:
3131  case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
3132  case HASH_TABLE_TYPE:
3133  case ORDERED_HASH_MAP_TYPE:
3134  case ORDERED_HASH_SET_TYPE:
3135  case ORDERED_NAME_DICTIONARY_TYPE:
3136  case NAME_DICTIONARY_TYPE:
3137  case GLOBAL_DICTIONARY_TYPE:
3138  case NUMBER_DICTIONARY_TYPE:
3139  case SIMPLE_NUMBER_DICTIONARY_TYPE:
3140  case STRING_TABLE_TYPE:
3141  case SCOPE_INFO_TYPE:
3142  case SCRIPT_CONTEXT_TABLE_TYPE:
3143  return kVisitFixedArray;
3144 
3145  case AWAIT_CONTEXT_TYPE:
3146  case BLOCK_CONTEXT_TYPE:
3147  case CATCH_CONTEXT_TYPE:
3148  case DEBUG_EVALUATE_CONTEXT_TYPE:
3149  case EVAL_CONTEXT_TYPE:
3150  case FUNCTION_CONTEXT_TYPE:
3151  case MODULE_CONTEXT_TYPE:
3152  case SCRIPT_CONTEXT_TYPE:
3153  case WITH_CONTEXT_TYPE:
3154  return kVisitContext;
3155 
3156  case NATIVE_CONTEXT_TYPE:
3157  return kVisitNativeContext;
3158 
3159  case EPHEMERON_HASH_TABLE_TYPE:
3160  return kVisitEphemeronHashTable;
3161 
3162  case WEAK_FIXED_ARRAY_TYPE:
3163  case WEAK_ARRAY_LIST_TYPE:
3164  return kVisitWeakArray;
3165 
3166  case FIXED_DOUBLE_ARRAY_TYPE:
3167  return kVisitFixedDoubleArray;
3168 
3169  case PROPERTY_ARRAY_TYPE:
3170  return kVisitPropertyArray;
3171 
3172  case FEEDBACK_CELL_TYPE:
3173  return kVisitFeedbackCell;
3174 
3175  case FEEDBACK_VECTOR_TYPE:
3176  return kVisitFeedbackVector;
3177 
3178  case ODDBALL_TYPE:
3179  return kVisitOddball;
3180 
3181  case MAP_TYPE:
3182  return kVisitMap;
3183 
3184  case CODE_TYPE:
3185  return kVisitCode;
3186 
3187  case CELL_TYPE:
3188  return kVisitCell;
3189 
3190  case PROPERTY_CELL_TYPE:
3191  return kVisitPropertyCell;
3192 
3193  case DESCRIPTOR_ARRAY_TYPE:
3194  return kVisitDescriptorArray;
3195 
3196  case TRANSITION_ARRAY_TYPE:
3197  return kVisitTransitionArray;
3198 
3199  case JS_WEAK_MAP_TYPE:
3200  case JS_WEAK_SET_TYPE:
3201  return kVisitJSWeakCollection;
3202 
3203  case CALL_HANDLER_INFO_TYPE:
3204  return kVisitStruct;
3205 
3206  case SHARED_FUNCTION_INFO_TYPE:
3207  return kVisitSharedFunctionInfo;
3208 
3209  case JS_PROXY_TYPE:
3210  return kVisitStruct;
3211 
3212  case SYMBOL_TYPE:
3213  return kVisitSymbol;
3214 
3215  case JS_ARRAY_BUFFER_TYPE:
3216  return kVisitJSArrayBuffer;
3217 
3218  case JS_DATA_VIEW_TYPE:
3219  return kVisitJSDataView;
3220 
3221  case JS_TYPED_ARRAY_TYPE:
3222  return kVisitJSTypedArray;
3223 
3224  case SMALL_ORDERED_HASH_MAP_TYPE:
3225  return kVisitSmallOrderedHashMap;
3226 
3227  case SMALL_ORDERED_HASH_SET_TYPE:
3228  return kVisitSmallOrderedHashSet;
3229 
3230  case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
3231  return kVisitSmallOrderedNameDictionary;
3232 
3233  case CODE_DATA_CONTAINER_TYPE:
3234  return kVisitCodeDataContainer;
3235 
3236  case WASM_INSTANCE_TYPE:
3237  return kVisitWasmInstanceObject;
3238 
3239  case PRE_PARSED_SCOPE_DATA_TYPE:
3240  return kVisitPreParsedScopeData;
3241 
3242  case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
3243  return kVisitUncompiledDataWithoutPreParsedScope;
3244 
3245  case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
3246  return kVisitUncompiledDataWithPreParsedScope;
3247 
3248  case JS_OBJECT_TYPE:
3249  case JS_ERROR_TYPE:
3250  case JS_ARGUMENTS_TYPE:
3251  case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
3252  case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
3253  case JS_GENERATOR_OBJECT_TYPE:
3254  case JS_ASYNC_FUNCTION_OBJECT_TYPE:
3255  case JS_ASYNC_GENERATOR_OBJECT_TYPE:
3256  case JS_MODULE_NAMESPACE_TYPE:
3257  case JS_VALUE_TYPE:
3258  case JS_DATE_TYPE:
3259  case JS_ARRAY_ITERATOR_TYPE:
3260  case JS_ARRAY_TYPE:
3261  case JS_FUNCTION_TYPE:
3262  case JS_GLOBAL_PROXY_TYPE:
3263  case JS_GLOBAL_OBJECT_TYPE:
3264  case JS_MESSAGE_OBJECT_TYPE:
3265  case JS_SET_TYPE:
3266  case JS_MAP_TYPE:
3267  case JS_SET_KEY_VALUE_ITERATOR_TYPE:
3268  case JS_SET_VALUE_ITERATOR_TYPE:
3269  case JS_MAP_KEY_ITERATOR_TYPE:
3270  case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
3271  case JS_MAP_VALUE_ITERATOR_TYPE:
3272  case JS_STRING_ITERATOR_TYPE:
3273  case JS_PROMISE_TYPE:
3274  case JS_REGEXP_TYPE:
3275  case JS_REGEXP_STRING_ITERATOR_TYPE:
3276  case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
3277  case JS_WEAK_FACTORY_TYPE:
3278 #ifdef V8_INTL_SUPPORT
3279  case JS_INTL_V8_BREAK_ITERATOR_TYPE:
3280  case JS_INTL_COLLATOR_TYPE:
3281  case JS_INTL_DATE_TIME_FORMAT_TYPE:
3282  case JS_INTL_LIST_FORMAT_TYPE:
3283  case JS_INTL_LOCALE_TYPE:
3284  case JS_INTL_NUMBER_FORMAT_TYPE:
3285  case JS_INTL_PLURAL_RULES_TYPE:
3286  case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
3287  case JS_INTL_SEGMENT_ITERATOR_TYPE:
3288  case JS_INTL_SEGMENTER_TYPE:
3289 #endif // V8_INTL_SUPPORT
3290  case WASM_EXCEPTION_TYPE:
3291  case WASM_GLOBAL_TYPE:
3292  case WASM_MEMORY_TYPE:
3293  case WASM_MODULE_TYPE:
3294  case WASM_TABLE_TYPE:
3295  case JS_BOUND_FUNCTION_TYPE:
3296  return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
3297  case JS_API_OBJECT_TYPE:
3298  case JS_SPECIAL_API_OBJECT_TYPE:
3299  return kVisitJSApiObject;
3300 
3301  case JS_WEAK_CELL_TYPE:
3302  case JS_WEAK_REF_TYPE:
3303  return kVisitJSWeakCell;
3304 
3305  case FILLER_TYPE:
3306  case FOREIGN_TYPE:
3307  case HEAP_NUMBER_TYPE:
3308  case MUTABLE_HEAP_NUMBER_TYPE:
3309  case FEEDBACK_METADATA_TYPE:
3310  return kVisitDataObject;
3311 
3312  case BIGINT_TYPE:
3313  return kVisitBigInt;
3314 
3315  case FIXED_UINT8_ARRAY_TYPE:
3316  case FIXED_INT8_ARRAY_TYPE:
3317  case FIXED_UINT16_ARRAY_TYPE:
3318  case FIXED_INT16_ARRAY_TYPE:
3319  case FIXED_UINT32_ARRAY_TYPE:
3320  case FIXED_INT32_ARRAY_TYPE:
3321  case FIXED_FLOAT32_ARRAY_TYPE:
3322  case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
3323  case FIXED_BIGUINT64_ARRAY_TYPE:
3324  case FIXED_BIGINT64_ARRAY_TYPE:
3325  return kVisitFixedTypedArrayBase;
3326 
3327  case FIXED_FLOAT64_ARRAY_TYPE:
3328  return kVisitFixedFloat64Array;
3329 
3330  case ALLOCATION_SITE_TYPE:
3331  return kVisitAllocationSite;
3332 
3333 #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
3334  STRUCT_LIST(MAKE_STRUCT_CASE)
3335 #undef MAKE_STRUCT_CASE
3336  if (instance_type == PROTOTYPE_INFO_TYPE) {
3337  return kVisitPrototypeInfo;
3338  }
3339  return kVisitStruct;
3340 
3341  case LOAD_HANDLER_TYPE:
3342  case STORE_HANDLER_TYPE:
3343  return kVisitDataHandler;
3344 
3345  default:
3346  UNREACHABLE();
3347  }
3348 }
3349 
3350 void Map::PrintGeneralization(
3351  Isolate* isolate, FILE* file, const char* reason, int modify_index,
3352  int split, int descriptors, bool descriptor_to_field,
3353  Representation old_representation, Representation new_representation,
3354  MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value,
3355  MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value) {
3356  OFStream os(file);
3357  os << "[generalizing]";
3358  Name name = instance_descriptors()->GetKey(modify_index);
3359  if (name->IsString()) {
3360  String::cast(name)->PrintOn(file);
3361  } else {
3362  os << "{symbol " << reinterpret_cast<void*>(name.ptr()) << "}";
3363  }
3364  os << ":";
3365  if (descriptor_to_field) {
3366  os << "c";
3367  } else {
3368  os << old_representation.Mnemonic() << "{";
3369  if (old_field_type.is_null()) {
3370  os << Brief(*(old_value.ToHandleChecked()));
3371  } else {
3372  old_field_type.ToHandleChecked()->PrintTo(os);
3373  }
3374  os << "}";
3375  }
3376  os << "->" << new_representation.Mnemonic() << "{";
3377  if (new_field_type.is_null()) {
3378  os << Brief(*(new_value.ToHandleChecked()));
3379  } else {
3380  new_field_type.ToHandleChecked()->PrintTo(os);
3381  }
3382  os << "} (";
3383  if (strlen(reason) > 0) {
3384  os << reason;
3385  } else {
3386  os << "+" << (descriptors - split) << " maps";
3387  }
3388  os << ") [";
3389  JavaScriptFrame::PrintTop(isolate, file, false, true);
3390  os << "]\n";
3391 }
3392 
3393 void JSObject::PrintInstanceMigration(FILE* file, Map original_map,
3394  Map new_map) {
3395  if (new_map->is_dictionary_map()) {
3396  PrintF(file, "[migrating to slow]\n");
3397  return;
3398  }
3399  PrintF(file, "[migrating]");
3400  DescriptorArray* o = original_map->instance_descriptors();
3401  DescriptorArray* n = new_map->instance_descriptors();
3402  for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
3403  Representation o_r = o->GetDetails(i).representation();
3404  Representation n_r = n->GetDetails(i).representation();
3405  if (!o_r.Equals(n_r)) {
3406  String::cast(o->GetKey(i))->PrintOn(file);
3407  PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
3408  } else if (o->GetDetails(i).location() == kDescriptor &&
3409  n->GetDetails(i).location() == kField) {
3410  Name name = o->GetKey(i);
3411  if (name->IsString()) {
3412  String::cast(name)->PrintOn(file);
3413  } else {
3414  PrintF(file, "{symbol %p}", reinterpret_cast<void*>(name.ptr()));
3415  }
3416  PrintF(file, " ");
3417  }
3418  }
3419  if (original_map->elements_kind() != new_map->elements_kind()) {
3420  PrintF(file, "elements_kind[%i->%i]", original_map->elements_kind(),
3421  new_map->elements_kind());
3422  }
3423  PrintF(file, "\n");
3424 }
3425 
3426 bool JSObject::IsUnmodifiedApiObject(ObjectSlot o) {
3427  Object* object = *o;
3428  if (object->IsSmi()) return false;
3429  HeapObject* heap_object = HeapObject::cast(object);
3430  if (!object->IsJSObject()) return false;
3431  JSObject* js_object = JSObject::cast(object);
3432  if (!js_object->IsDroppableApiWrapper()) return false;
3433  Object* maybe_constructor = js_object->map()->GetConstructor();
3434  if (!maybe_constructor->IsJSFunction()) return false;
3435  JSFunction* constructor = JSFunction::cast(maybe_constructor);
3436  if (js_object->elements()->length() != 0) return false;
3437 
3438  return constructor->initial_map() == heap_object->map();
3439 }
3440 
3441 void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
3442  os << AsHex(this->ptr(), kSystemPointerHexDigits, true) << " ";
3443 
3444  if (IsString()) {
3445  HeapStringAllocator allocator;
3446  StringStream accumulator(&allocator);
3447  String::cast(this)->StringShortPrint(&accumulator);
3448  os << accumulator.ToCString().get();
3449  return;
3450  }
3451  if (IsJSObject()) {
3452  HeapStringAllocator allocator;
3453  StringStream accumulator(&allocator);
3454  JSObject::cast(this)->JSObjectShortPrint(&accumulator);
3455  os << accumulator.ToCString().get();
3456  return;
3457  }
3458  switch (map()->instance_type()) {
3459  case MAP_TYPE: {
3460  os << "<Map";
3461  Map mapInstance = Map::cast(this);
3462  if (mapInstance->IsJSObjectMap()) {
3463  os << "(" << ElementsKindToString(mapInstance->elements_kind()) << ")";
3464  } else if (mapInstance->instance_size() != kVariableSizeSentinel) {
3465  os << "[" << mapInstance->instance_size() << "]";
3466  }
3467  os << ">";
3468  } break;
3469  case AWAIT_CONTEXT_TYPE: {
3470  os << "<AwaitContext generator= ";
3471  HeapStringAllocator allocator;
3472  StringStream accumulator(&allocator);
3473  Context::cast(this)->extension()->ShortPrint(&accumulator);
3474  os << accumulator.ToCString().get();
3475  os << '>';
3476  break;
3477  }
3478  case BLOCK_CONTEXT_TYPE:
3479  os << "<BlockContext[" << Context::cast(this)->length() << "]>";
3480  break;
3481  case CATCH_CONTEXT_TYPE:
3482  os << "<CatchContext[" << Context::cast(this)->length() << "]>";
3483  break;
3484  case DEBUG_EVALUATE_CONTEXT_TYPE:
3485  os << "<DebugEvaluateContext[" << Context::cast(this)->length() << "]>";
3486  break;
3487  case EVAL_CONTEXT_TYPE:
3488  os << "<EvalContext[" << Context::cast(this)->length() << "]>";
3489  break;
3490  case FUNCTION_CONTEXT_TYPE:
3491  os << "<FunctionContext[" << Context::cast(this)->length() << "]>";
3492  break;
3493  case MODULE_CONTEXT_TYPE:
3494  os << "<ModuleContext[" << Context::cast(this)->length() << "]>";
3495  break;
3496  case NATIVE_CONTEXT_TYPE:
3497  os << "<NativeContext[" << Context::cast(this)->length() << "]>";
3498  break;
3499  case SCRIPT_CONTEXT_TYPE:
3500  os << "<ScriptContext[" << Context::cast(this)->length() << "]>";
3501  break;
3502  case WITH_CONTEXT_TYPE:
3503  os << "<WithContext[" << Context::cast(this)->length() << "]>";
3504  break;
3505  case SCRIPT_CONTEXT_TABLE_TYPE:
3506  os << "<ScriptContextTable[" << FixedArray::cast(this)->length() << "]>";
3507  break;
3508  case HASH_TABLE_TYPE:
3509  os << "<HashTable[" << FixedArray::cast(this)->length() << "]>";
3510  break;
3511  case ORDERED_HASH_MAP_TYPE:
3512  os << "<OrderedHashMap[" << FixedArray::cast(this)->length() << "]>";
3513  break;
3514  case ORDERED_HASH_SET_TYPE:
3515  os << "<OrderedHashSet[" << FixedArray::cast(this)->length() << "]>";
3516  break;
3517  case ORDERED_NAME_DICTIONARY_TYPE:
3518  os << "<OrderedNameDictionary[" << FixedArray::cast(this)->length()
3519  << "]>";
3520  break;
3521  case NAME_DICTIONARY_TYPE:
3522  os << "<NameDictionary[" << FixedArray::cast(this)->length() << "]>";
3523  break;
3524  case GLOBAL_DICTIONARY_TYPE:
3525  os << "<GlobalDictionary[" << FixedArray::cast(this)->length() << "]>";
3526  break;
3527  case NUMBER_DICTIONARY_TYPE:
3528  os << "<NumberDictionary[" << FixedArray::cast(this)->length() << "]>";
3529  break;
3530  case SIMPLE_NUMBER_DICTIONARY_TYPE:
3531  os << "<SimpleNumberDictionary[" << FixedArray::cast(this)->length()
3532  << "]>";
3533  break;
3534  case STRING_TABLE_TYPE:
3535  os << "<StringTable[" << FixedArray::cast(this)->length() << "]>";
3536  break;
3537  case FIXED_ARRAY_TYPE:
3538  os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
3539  break;
3540  case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
3541  os << "<ObjectBoilerplateDescription[" << FixedArray::cast(this)->length()
3542  << "]>";
3543  break;
3544  case FIXED_DOUBLE_ARRAY_TYPE:
3545  os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
3546  << "]>";
3547  break;
3548  case BYTE_ARRAY_TYPE:
3549  os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
3550  break;
3551  case BYTECODE_ARRAY_TYPE:
3552  os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
3553  break;
3554  case DESCRIPTOR_ARRAY_TYPE:
3555  os << "<DescriptorArray["
3556  << DescriptorArray::cast(this)->number_of_descriptors() << "]>";
3557  break;
3558  case TRANSITION_ARRAY_TYPE:
3559  os << "<TransitionArray[" << TransitionArray::cast(this)->length()
3560  << "]>";
3561  break;
3562  case PROPERTY_ARRAY_TYPE:
3563  os << "<PropertyArray[" << PropertyArray::cast(this)->length() << "]>";
3564  break;
3565  case FEEDBACK_CELL_TYPE: {
3566  {
3567  ReadOnlyRoots roots = GetReadOnlyRoots();
3568  os << "<FeedbackCell[";
3569  if (map() == roots.no_closures_cell_map()) {
3570  os << "no feedback";
3571  } else if (map() == roots.no_closures_cell_map()) {
3572  os << "no closures";
3573  } else if (map() == roots.one_closure_cell_map()) {
3574  os << "one closure";
3575  } else if (map() == roots.many_closures_cell_map()) {
3576  os << "many closures";
3577  } else {
3578  os << "!!!INVALID MAP!!!";
3579  }
3580  os << "]>";
3581  }
3582  break;
3583  }
3584  case FEEDBACK_VECTOR_TYPE:
3585  os << "<FeedbackVector[" << FeedbackVector::cast(this)->length() << "]>";
3586  break;
3587  case FREE_SPACE_TYPE:
3588  os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
3589  break;
3590 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype) \
3591  case FIXED_##TYPE##_ARRAY_TYPE: \
3592  os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
3593  << "]>"; \
3594  break;
3595 
3596  TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
3597 #undef TYPED_ARRAY_SHORT_PRINT
3598 
3599  case PRE_PARSED_SCOPE_DATA_TYPE: {
3600  PreParsedScopeData* data = PreParsedScopeData::cast(this);
3601  os << "<PreParsedScopeData[" << data->length() << "]>";
3602  break;
3603  }
3604 
3605  case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE: {
3606  UncompiledDataWithoutPreParsedScope* data =
3607  UncompiledDataWithoutPreParsedScope::cast(this);
3608  os << "<UncompiledDataWithoutPreParsedScope (" << data->start_position()
3609  << ", " << data->end_position() << ")]>";
3610  break;
3611  }
3612 
3613  case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE: {
3614  UncompiledDataWithPreParsedScope* data =
3615  UncompiledDataWithPreParsedScope::cast(this);
3616  os << "<UncompiledDataWithPreParsedScope (" << data->start_position()
3617  << ", " << data->end_position()
3618  << ") preparsed=" << Brief(data->pre_parsed_scope_data()) << ">";
3619  break;
3620  }
3621 
3622  case SHARED_FUNCTION_INFO_TYPE: {
3623  SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
3624  std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
3625  if (debug_name[0] != 0) {
3626  os << "<SharedFunctionInfo " << debug_name.get() << ">";
3627  } else {
3628  os << "<SharedFunctionInfo>";
3629  }
3630  break;
3631  }
3632  case JS_MESSAGE_OBJECT_TYPE:
3633  os << "<JSMessageObject>";
3634  break;
3635 #define MAKE_STRUCT_CASE(TYPE, Name, name) \
3636  case TYPE: \
3637  os << "<" #Name; \
3638  Name::cast(this)->BriefPrintDetails(os); \
3639  os << ">"; \
3640  break;
3641  STRUCT_LIST(MAKE_STRUCT_CASE)
3642 #undef MAKE_STRUCT_CASE
3643  case ALLOCATION_SITE_TYPE: {
3644  os << "<AllocationSite";
3645  AllocationSite::cast(this)->BriefPrintDetails(os);
3646  os << ">";
3647  break;
3648  }
3649  case SCOPE_INFO_TYPE: {
3650  ScopeInfo scope = ScopeInfo::cast(this);
3651  os << "<ScopeInfo";
3652  if (scope->length()) os << " " << scope->scope_type() << " ";
3653  os << "[" << scope->length() << "]>";
3654  break;
3655  }
3656  case CODE_TYPE: {
3657  Code code = Code::cast(this);
3658  os << "<Code " << Code::Kind2String(code->kind());
3659  if (code->is_stub()) {
3660  os << " " << CodeStub::MajorName(CodeStub::GetMajorKey(code));
3661  } else if (code->is_builtin()) {
3662  os << " " << Builtins::name(code->builtin_index());
3663  }
3664  os << ">";
3665  break;
3666  }
3667  case ODDBALL_TYPE: {
3668  if (IsUndefined()) {
3669  os << "<undefined>";
3670  } else if (IsTheHole()) {
3671  os << "<the_hole>";
3672  } else if (IsNull()) {
3673  os << "<null>";
3674  } else if (IsTrue()) {
3675  os << "<true>";
3676  } else if (IsFalse()) {
3677  os << "<false>";
3678  } else {
3679  os << "<Odd Oddball: ";
3680  os << Oddball::cast(this)->to_string()->ToCString().get();
3681  os << ">";
3682  }
3683  break;
3684  }
3685  case SYMBOL_TYPE: {
3686  Symbol symbol = Symbol::cast(this);
3687  symbol->SymbolShortPrint(os);
3688  break;
3689  }
3690  case HEAP_NUMBER_TYPE: {
3691  os << "<HeapNumber ";
3692  HeapNumber::cast(this)->HeapNumberPrint(os);
3693  os << ">";
3694  break;
3695  }
3696  case MUTABLE_HEAP_NUMBER_TYPE: {
3697  os << "<MutableHeapNumber ";
3698  MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os);
3699  os << '>';
3700  break;
3701  }
3702  case BIGINT_TYPE: {
3703  os << "<BigInt ";
3704  BigInt::cast(this)->BigIntShortPrint(os);
3705  os << ">";
3706  break;
3707  }
3708  case JS_PROXY_TYPE:
3709  os << "<JSProxy>";
3710  break;
3711  case FOREIGN_TYPE:
3712  os << "<Foreign>";
3713  break;
3714  case CELL_TYPE: {
3715  os << "<Cell value= ";
3716  HeapStringAllocator allocator;
3717  StringStream accumulator(&allocator);
3718  Cell::cast(this)->value()->ShortPrint(&accumulator);
3719  os << accumulator.ToCString().get();
3720  os << '>';
3721  break;
3722  }
3723  case PROPERTY_CELL_TYPE: {
3724  PropertyCell* cell = PropertyCell::cast(this);
3725  os << "<PropertyCell name=";
3726  cell->name()->ShortPrint(os);
3727  os << " value=";
3728  HeapStringAllocator allocator;
3729  StringStream accumulator(&allocator);
3730  cell->value()->ShortPrint(&accumulator);
3731  os << accumulator.ToCString().get();
3732  os << '>';
3733  break;
3734  }
3735  case CALL_HANDLER_INFO_TYPE: {
3736  CallHandlerInfo* info = CallHandlerInfo::cast(this);
3737  os << "<CallHandlerInfo ";
3738  os << "callback= " << Brief(info->callback());
3739  os << ", js_callback= " << Brief(info->js_callback());
3740  os << ", data= " << Brief(info->data());
3741  if (info->IsSideEffectFreeCallHandlerInfo()) {
3742  os << ", side_effect_free= true>";
3743  } else {
3744  os << ", side_effect_free= false>";
3745  }
3746  break;
3747  }
3748  default:
3749  os << "<Other heap object (" << map()->instance_type() << ")>";
3750  break;
3751  }
3752 }
3753 
3754 void Struct::BriefPrintDetails(std::ostream& os) {}
3755 
3756 void Tuple2::BriefPrintDetails(std::ostream& os) {
3757  os << " " << Brief(value1()) << ", " << Brief(value2());
3758 }
3759 
3760 void Tuple3::BriefPrintDetails(std::ostream& os) {
3761  os << " " << Brief(value1()) << ", " << Brief(value2()) << ", "
3762  << Brief(value3());
3763 }
3764 
3765 void ArrayBoilerplateDescription::BriefPrintDetails(std::ostream& os) {
3766  os << " " << elements_kind() << ", " << Brief(constant_elements());
3767 }
3768 
3769 void CallableTask::BriefPrintDetails(std::ostream& os) {
3770  os << " callable=" << Brief(callable());
3771 }
3772 
3773 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
3774 
3775 
3776 void HeapObject::IterateBody(ObjectVisitor* v) {
3777  Map m = map();
3778  IterateBodyFast<ObjectVisitor>(m, SizeFromMap(m), v);
3779 }
3780 
3781 void HeapObject::IterateBody(Map map, int object_size, ObjectVisitor* v) {
3782  IterateBodyFast<ObjectVisitor>(map, object_size, v);
3783 }
3784 
3785 
3786 struct CallIsValidSlot {
3787  template <typename BodyDescriptor>
3788  static bool apply(Map map, HeapObject* obj, int offset, int) {
3789  return BodyDescriptor::IsValidSlot(map, obj, offset);
3790  }
3791 };
3792 
3793 bool HeapObject::IsValidSlot(Map map, int offset) {
3794  DCHECK_NE(0, offset);
3795  return BodyDescriptorApply<CallIsValidSlot, bool>(map->instance_type(), map,
3796  this, offset, 0);
3797 }
3798 
3799 String JSReceiver::class_name() {
3800  ReadOnlyRoots roots = GetReadOnlyRoots();
3801  if (IsFunction()) return roots.Function_string();
3802  if (IsJSArgumentsObject()) return roots.Arguments_string();
3803  if (IsJSArray()) return roots.Array_string();
3804  if (IsJSArrayBuffer()) {
3805  if (JSArrayBuffer::cast(this)->is_shared()) {
3806  return roots.SharedArrayBuffer_string();
3807  }
3808  return roots.ArrayBuffer_string();
3809  }
3810  if (IsJSArrayIterator()) return roots.ArrayIterator_string();
3811  if (IsJSDate()) return roots.Date_string();
3812  if (IsJSError()) return roots.Error_string();
3813  if (IsJSGeneratorObject()) return roots.Generator_string();
3814  if (IsJSMap()) return roots.Map_string();
3815  if (IsJSMapIterator()) return roots.MapIterator_string();
3816  if (IsJSProxy()) {
3817  return map()->is_callable() ? roots.Function_string()
3818  : roots.Object_string();
3819  }
3820  if (IsJSRegExp()) return roots.RegExp_string();
3821  if (IsJSSet()) return roots.Set_string();
3822  if (IsJSSetIterator()) return roots.SetIterator_string();
3823  if (IsJSTypedArray()) {
3824 #define SWITCH_KIND(Type, type, TYPE, ctype) \
3825  if (map()->elements_kind() == TYPE##_ELEMENTS) { \
3826  return roots.Type##Array_string(); \
3827  }
3828  TYPED_ARRAYS(SWITCH_KIND)
3829 #undef SWITCH_KIND
3830  }
3831  if (IsJSValue()) {
3832  Object* value = JSValue::cast(this)->value();
3833  if (value->IsBoolean()) return roots.Boolean_string();
3834  if (value->IsString()) return roots.String_string();
3835  if (value->IsNumber()) return roots.Number_string();
3836  if (value->IsBigInt()) return roots.BigInt_string();
3837  if (value->IsSymbol()) return roots.Symbol_string();
3838  if (value->IsScript()) return roots.Script_string();
3839  UNREACHABLE();
3840  }
3841  if (IsJSWeakMap()) return roots.WeakMap_string();
3842  if (IsJSWeakSet()) return roots.WeakSet_string();
3843  if (IsJSGlobalProxy()) return roots.global_string();
3844 
3845  Object* maybe_constructor = map()->GetConstructor();
3846  if (maybe_constructor->IsJSFunction()) {
3847  JSFunction* constructor = JSFunction::cast(maybe_constructor);
3848  if (constructor->shared()->IsApiFunction()) {
3849  maybe_constructor = constructor->shared()->get_api_func_data();
3850  }
3851  }
3852 
3853  if (maybe_constructor->IsFunctionTemplateInfo()) {
3854  FunctionTemplateInfo* info = FunctionTemplateInfo::cast(maybe_constructor);
3855  if (info->class_name()->IsString()) return String::cast(info->class_name());
3856  }
3857 
3858  return roots.Object_string();
3859 }
3860 
3861 bool HeapObject::CanBeRehashed() const {
3862  DCHECK(NeedsRehashing());
3863  switch (map()->instance_type()) {
3864  case ORDERED_HASH_MAP_TYPE:
3865  case ORDERED_HASH_SET_TYPE:
3866  case ORDERED_NAME_DICTIONARY_TYPE:
3867  // TODO(yangguo): actually support rehashing OrderedHash{Map,Set}.
3868  return false;
3869  case NAME_DICTIONARY_TYPE:
3870  case GLOBAL_DICTIONARY_TYPE:
3871  case NUMBER_DICTIONARY_TYPE:
3872  case SIMPLE_NUMBER_DICTIONARY_TYPE:
3873  case STRING_TABLE_TYPE:
3874  return true;
3875  case DESCRIPTOR_ARRAY_TYPE:
3876  return true;
3877  case TRANSITION_ARRAY_TYPE:
3878  return true;
3879  case SMALL_ORDERED_HASH_MAP_TYPE:
3880  return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
3881  case SMALL_ORDERED_HASH_SET_TYPE:
3882  return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
3883  case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
3884  return SmallOrderedNameDictionary::cast(this)->NumberOfElements() == 0;
3885  default:
3886  return false;
3887  }
3888  return false;
3889 }
3890 
3891 void HeapObject::RehashBasedOnMap(Isolate* isolate) {
3892  switch (map()->instance_type()) {
3893  case HASH_TABLE_TYPE:
3894  UNREACHABLE();
3895  break;
3896  case NAME_DICTIONARY_TYPE:
3897  NameDictionary::cast(this)->Rehash(isolate);
3898  break;
3899  case GLOBAL_DICTIONARY_TYPE:
3900  GlobalDictionary::cast(this)->Rehash(isolate);
3901  break;
3902  case NUMBER_DICTIONARY_TYPE:
3903  NumberDictionary::cast(this)->Rehash(isolate);
3904  break;
3905  case SIMPLE_NUMBER_DICTIONARY_TYPE:
3906  SimpleNumberDictionary::cast(this)->Rehash(isolate);
3907  break;
3908  case STRING_TABLE_TYPE:
3909  StringTable::cast(this)->Rehash(isolate);
3910  break;
3911  case DESCRIPTOR_ARRAY_TYPE:
3912  DCHECK_LE(1, DescriptorArray::cast(this)->number_of_descriptors());
3913  DescriptorArray::cast(this)->Sort();
3914  break;
3915  case TRANSITION_ARRAY_TYPE:
3916  TransitionArray::cast(this)->Sort();
3917  break;
3918  case SMALL_ORDERED_HASH_MAP_TYPE:
3919  DCHECK_EQ(0, SmallOrderedHashMap::cast(this)->NumberOfElements());
3920  break;
3921  case SMALL_ORDERED_HASH_SET_TYPE:
3922  DCHECK_EQ(0, SmallOrderedHashSet::cast(this)->NumberOfElements());
3923  break;
3924  case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
3925  DCHECK_EQ(0, SmallOrderedNameDictionary::cast(this)->NumberOfElements());
3926  break;
3927  default:
3928  break;
3929  }
3930 }
3931 
3932 namespace {
3933 std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper(
3934  Handle<JSReceiver> receiver) {
3935  Isolate* isolate = receiver->GetIsolate();
3936 
3937  // If the object was instantiated simply with base == new.target, the
3938  // constructor on the map provides the most accurate name.
3939  // Don't provide the info for prototypes, since their constructors are
3940  // reclaimed and replaced by Object in OptimizeAsPrototype.
3941  if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
3942  !receiver->map()->is_prototype_map()) {
3943  Object* maybe_constructor = receiver->map()->GetConstructor();
3944  if (maybe_constructor->IsJSFunction()) {
3945  JSFunction* constructor = JSFunction::cast(maybe_constructor);
3946  String name = constructor->shared()->DebugName();
3947  if (name->length() != 0 &&
3948  !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
3949  return std::make_pair(handle(constructor, isolate),
3950  handle(name, isolate));
3951  }
3952  } else if (maybe_constructor->IsFunctionTemplateInfo()) {
3953  FunctionTemplateInfo* info =
3954  FunctionTemplateInfo::cast(maybe_constructor);
3955  if (info->class_name()->IsString()) {
3956  return std::make_pair(
3958  handle(String::cast(info->class_name()), isolate));
3959  }
3960  }
3961  }
3962 
3963  Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
3964  receiver, isolate->factory()->to_string_tag_symbol());
3965  if (maybe_tag->IsString())
3966  return std::make_pair(MaybeHandle<JSFunction>(),
3967  Handle<String>::cast(maybe_tag));
3968 
3969  PrototypeIterator iter(isolate, receiver);
3970  if (iter.IsAtEnd()) {
3971  return std::make_pair(MaybeHandle<JSFunction>(),
3972  handle(receiver->class_name(), isolate));
3973  }
3974 
3975  Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
3976  LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
3977  LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
3978  Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
3979  if (maybe_constructor->IsJSFunction()) {
3980  JSFunction* constructor = JSFunction::cast(*maybe_constructor);
3981  String name = constructor->shared()->DebugName();
3982 
3983  if (name->length() != 0 &&
3984  !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
3985  return std::make_pair(handle(constructor, isolate),
3986  handle(name, isolate));
3987  }
3988  }
3989 
3990  return std::make_pair(MaybeHandle<JSFunction>(),
3991  handle(receiver->class_name(), isolate));
3992 }
3993 } // anonymous namespace
3994 
3995 // static
3996 MaybeHandle<JSFunction> JSReceiver::GetConstructor(
3997  Handle<JSReceiver> receiver) {
3998  return GetConstructorHelper(receiver).first;
3999 }
4000 
4001 // static
4002 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
4003  return GetConstructorHelper(receiver).second;
4004 }
4005 
4006 Handle<Context> JSReceiver::GetCreationContext() {
4007  JSReceiver* receiver = this;
4008  // Externals are JSObjects with null as a constructor.
4009  DCHECK(!receiver->IsExternal(GetIsolate()));
4010  Object* constructor = receiver->map()->GetConstructor();
4011  JSFunction* function;
4012  if (constructor->IsJSFunction()) {
4013  function = JSFunction::cast(constructor);
4014  } else if (constructor->IsFunctionTemplateInfo()) {
4015  // Remote objects don't have a creation context.
4016  return Handle<Context>::null();
4017  } else {
4018  // Functions have null as a constructor,
4019  // but any JSFunction knows its context immediately.
4020  CHECK(receiver->IsJSFunction());
4021  function = JSFunction::cast(receiver);
4022  }
4023 
4024  return function->has_context()
4025  ? Handle<Context>(function->context()->native_context(),
4026  receiver->GetIsolate())
4027  : Handle<Context>::null();
4028 }
4029 
4030 // static
4031 MaybeObjectHandle Map::WrapFieldType(Isolate* isolate, Handle<FieldType> type) {
4032  if (type->IsClass()) {
4033  return MaybeObjectHandle::Weak(type->AsClass(), isolate);
4034  }
4035  return MaybeObjectHandle(type);
4036 }
4037 
4038 // static
4039 FieldType Map::UnwrapFieldType(MaybeObject wrapped_type) {
4040  if (wrapped_type->IsCleared()) {
4041  return FieldType::None();
4042  }
4043  HeapObject* heap_object;
4044  if (wrapped_type->GetHeapObjectIfWeak(&heap_object)) {
4045  return FieldType::cast(heap_object);
4046  }
4047  return wrapped_type->cast<FieldType>();
4048 }
4049 
4050 MaybeHandle<Map> Map::CopyWithField(Isolate* isolate, Handle<Map> map,
4051  Handle<Name> name, Handle<FieldType> type,
4052  PropertyAttributes attributes,
4053  PropertyConstness constness,
4054  Representation representation,
4055  TransitionFlag flag) {
4056  DCHECK(DescriptorArray::kNotFound ==
4057  map->instance_descriptors()->Search(
4058  *name, map->NumberOfOwnDescriptors()));
4059 
4060  // Ensure the descriptor array does not get too big.
4061  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
4062  return MaybeHandle<Map>();
4063  }
4064 
4065  // Compute the new index for new field.
4066  int index = map->NextFreePropertyIndex();
4067 
4068  if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
4069  constness = PropertyConstness::kMutable;
4070  representation = Representation::Tagged();
4071  type = FieldType::Any(isolate);
4072  } else {
4073  Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
4074  isolate, map->instance_type(), &constness, &representation, &type);
4075  }
4076 
4077  MaybeObjectHandle wrapped_type = WrapFieldType(isolate, type);
4078 
4079  DCHECK_IMPLIES(!FLAG_track_constant_fields,
4080  constness == PropertyConstness::kMutable);
4081  Descriptor d = Descriptor::DataField(name, index, attributes, constness,
4082  representation, wrapped_type);
4083  Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
4084  new_map->AccountAddedPropertyField();
4085  return new_map;
4086 }
4087 
4088 MaybeHandle<Map> Map::CopyWithConstant(Isolate* isolate, Handle<Map> map,
4089  Handle<Name> name,
4090  Handle<Object> constant,
4091  PropertyAttributes attributes,
4092  TransitionFlag flag) {
4093  // Ensure the descriptor array does not get too big.
4094  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
4095  return MaybeHandle<Map>();
4096  }
4097 
4098  if (FLAG_track_constant_fields) {
4099  Representation representation = constant->OptimalRepresentation();
4100  Handle<FieldType> type = constant->OptimalType(isolate, representation);
4101  return CopyWithField(isolate, map, name, type, attributes,
4102  PropertyConstness::kConst, representation, flag);
4103  } else {
4104  // Allocate new instance descriptors with (name, constant) added.
4105  Descriptor d =
4106  Descriptor::DataConstant(isolate, name, 0, constant, attributes);
4107  Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
4108  return new_map;
4109  }
4110 }
4111 
4112 const char* Representation::Mnemonic() const {
4113  switch (kind_) {
4114  case kNone: return "v";
4115  case kTagged: return "t";
4116  case kSmi: return "s";
4117  case kDouble: return "d";
4118  case kInteger32: return "i";
4119  case kHeapObject: return "h";
4120  case kExternal: return "x";
4121  default:
4122  UNREACHABLE();
4123  }
4124 }
4125 
4126 bool Map::TransitionRemovesTaggedField(Map target) const {
4127  int inobject = NumberOfFields();
4128  int target_inobject = target->NumberOfFields();
4129  for (int i = target_inobject; i < inobject; i++) {
4130  FieldIndex index = FieldIndex::ForPropertyIndex(*this, i);
4131  if (!IsUnboxedDoubleField(index)) return true;
4132  }
4133  return false;
4134 }
4135 
4136 bool Map::TransitionChangesTaggedFieldToUntaggedField(Map target) const {
4137  int inobject = NumberOfFields();
4138  int target_inobject = target->NumberOfFields();
4139  int limit = Min(inobject, target_inobject);
4140  for (int i = 0; i < limit; i++) {
4141  FieldIndex index = FieldIndex::ForPropertyIndex(target, i);
4142  if (!IsUnboxedDoubleField(index) && target->IsUnboxedDoubleField(index)) {
4143  return true;
4144  }
4145  }
4146  return false;
4147 }
4148 
4149 bool Map::TransitionRequiresSynchronizationWithGC(Map target) const {
4150  return TransitionRemovesTaggedField(target) ||
4151  TransitionChangesTaggedFieldToUntaggedField(target);
4152 }
4153 
4154 bool Map::InstancesNeedRewriting(Map target) const {
4155  int target_number_of_fields = target->NumberOfFields();
4156  int target_inobject = target->GetInObjectProperties();
4157  int target_unused = target->UnusedPropertyFields();
4158  int old_number_of_fields;
4159 
4160  return InstancesNeedRewriting(target, target_number_of_fields,
4161  target_inobject, target_unused,
4162  &old_number_of_fields);
4163 }
4164 
4165 bool Map::InstancesNeedRewriting(Map target, int target_number_of_fields,
4166  int target_inobject, int target_unused,
4167  int* old_number_of_fields) const {
4168  // If fields were added (or removed), rewrite the instance.
4169  *old_number_of_fields = NumberOfFields();
4170  DCHECK(target_number_of_fields >= *old_number_of_fields);
4171  if (target_number_of_fields != *old_number_of_fields) return true;
4172 
4173  // If smi descriptors were replaced by double descriptors, rewrite.
4174  DescriptorArray* old_desc = instance_descriptors();
4175  DescriptorArray* new_desc = target->instance_descriptors();
4176  int limit = NumberOfOwnDescriptors();
4177  for (int i = 0; i < limit; i++) {
4178  if (new_desc->GetDetails(i).representation().IsDouble() !=
4179  old_desc->GetDetails(i).representation().IsDouble()) {
4180  return true;
4181  }
4182  }
4183 
4184  // If no fields were added, and no inobject properties were removed, setting
4185  // the map is sufficient.
4186  if (target_inobject == GetInObjectProperties()) return false;
4187  // In-object slack tracking may have reduced the object size of the new map.
4188  // In that case, succeed if all existing fields were inobject, and they still
4189  // fit within the new inobject size.
4190  DCHECK(target_inobject < GetInObjectProperties());
4191  if (target_number_of_fields <= target_inobject) {
4192  DCHECK(target_number_of_fields + target_unused == target_inobject);
4193  return false;
4194  }
4195  // Otherwise, properties will need to be moved to the backing store.
4196  return true;
4197 }
4198 
4199 
4200 // static
4201 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
4202  Handle<Map> new_map,
4203  Isolate* isolate) {
4204  DCHECK(old_map->is_prototype_map());
4205  DCHECK(new_map->is_prototype_map());
4206  bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
4207  new_map->set_prototype_info(old_map->prototype_info());
4208  old_map->set_prototype_info(Smi::kZero);
4209  if (FLAG_trace_prototype_users) {
4210  PrintF("Moving prototype_info %p from map %p to map %p.\n",
4211  reinterpret_cast<void*>(new_map->prototype_info()),
4212  reinterpret_cast<void*>(old_map->ptr()),
4213  reinterpret_cast<void*>(new_map->ptr()));
4214  }
4215  if (was_registered) {
4216  if (new_map->prototype_info()->IsPrototypeInfo()) {
4217  // The new map isn't registered with its prototype yet; reflect this fact
4218  // in the PrototypeInfo it just inherited from the old map.
4219  PrototypeInfo::cast(new_map->prototype_info())
4220  ->set_registry_slot(PrototypeInfo::UNREGISTERED);
4221  }
4222  JSObject::LazyRegisterPrototypeUser(new_map, isolate);
4223  }
4224 }
4225 
4226 namespace {
4227 // To migrate a fast instance to a fast map:
4228 // - First check whether the instance needs to be rewritten. If not, simply
4229 // change the map.
4230 // - Otherwise, allocate a fixed array large enough to hold all fields, in
4231 // addition to unused space.
4232 // - Copy all existing properties in, in the following order: backing store
4233 // properties, unused fields, inobject properties.
4234 // - If all allocation succeeded, commit the state atomically:
4235 // * Copy inobject properties from the backing store back into the object.
4236 // * Trim the difference in instance size of the object. This also cleanly
4237 // frees inobject properties that moved to the backing store.
4238 // * If there are properties left in the backing store, trim of the space used
4239 // to temporarily store the inobject properties.
4240 // * If there are properties left in the backing store, install the backing
4241 // store.
4242 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
4243  Isolate* isolate = object->GetIsolate();
4244  Handle<Map> old_map(object->map(), isolate);
4245  // In case of a regular transition.
4246  if (new_map->GetBackPointer() == *old_map) {
4247  // If the map does not add named properties, simply set the map.
4248  if (old_map->NumberOfOwnDescriptors() ==
4249  new_map->NumberOfOwnDescriptors()) {
4250  object->synchronized_set_map(*new_map);
4251  return;
4252  }
4253 
4254  PropertyDetails details = new_map->GetLastDescriptorDetails();
4255  int target_index = details.field_index() - new_map->GetInObjectProperties();
4256  int property_array_length = object->property_array()->length();
4257  bool have_space = old_map->UnusedPropertyFields() > 0 ||
4258  (details.location() == kField && target_index >= 0 &&
4259  property_array_length > target_index);
4260  // Either new_map adds an kDescriptor property, or a kField property for
4261  // which there is still space, and which does not require a mutable double
4262  // box (an out-of-object double).
4263  if (details.location() == kDescriptor ||
4264  (have_space && ((FLAG_unbox_double_fields && target_index < 0) ||
4265  !details.representation().IsDouble()))) {
4266  object->synchronized_set_map(*new_map);
4267  return;
4268  }
4269 
4270  // If there is still space in the object, we need to allocate a mutable
4271  // double box.
4272  if (have_space) {
4273  FieldIndex index =
4274  FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
4275  DCHECK(details.representation().IsDouble());
4276  DCHECK(!new_map->IsUnboxedDoubleField(index));
4277  auto value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4278  object->RawFastPropertyAtPut(index, *value);
4279  object->synchronized_set_map(*new_map);
4280  return;
4281  }
4282 
4283  // This migration is a transition from a map that has run out of property
4284  // space. Extend the backing store.
4285  int grow_by = new_map->UnusedPropertyFields() + 1;
4286  Handle<PropertyArray> old_storage(object->property_array(), isolate);
4287  Handle<PropertyArray> new_storage =
4288  isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by);
4289 
4290  // Properly initialize newly added property.
4291  Handle<Object> value;
4292  if (details.representation().IsDouble()) {
4293  value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4294  } else {
4295  value = isolate->factory()->uninitialized_value();
4296  }
4297  DCHECK_EQ(kField, details.location());
4298  DCHECK_EQ(kData, details.kind());
4299  DCHECK_GE(target_index, 0); // Must be a backing store index.
4300  new_storage->set(target_index, *value);
4301 
4302  // From here on we cannot fail and we shouldn't GC anymore.
4303  DisallowHeapAllocation no_allocation;
4304 
4305  // Set the new property value and do the map transition.
4306  object->SetProperties(*new_storage);
4307  object->synchronized_set_map(*new_map);
4308  return;
4309  }
4310 
4311  int old_number_of_fields;
4312  int number_of_fields = new_map->NumberOfFields();
4313  int inobject = new_map->GetInObjectProperties();
4314  int unused = new_map->UnusedPropertyFields();
4315 
4316  // Nothing to do if no functions were converted to fields and no smis were
4317  // converted to doubles.
4318  if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
4319  unused, &old_number_of_fields)) {
4320  object->synchronized_set_map(*new_map);
4321  return;
4322  }
4323 
4324  int total_size = number_of_fields + unused;
4325  int external = total_size - inobject;
4326  Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external);
4327 
4328  // We use this array to temporarily store the inobject properties.
4329  Handle<FixedArray> inobject_props =
4330  isolate->factory()->NewFixedArray(inobject);
4331 
4332  Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors(),
4333  isolate);
4334  Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors(),
4335  isolate);
4336  int old_nof = old_map->NumberOfOwnDescriptors();
4337  int new_nof = new_map->NumberOfOwnDescriptors();
4338 
4339  // This method only supports generalizing instances to at least the same
4340  // number of properties.
4341  DCHECK(old_nof <= new_nof);
4342 
4343  for (int i = 0; i < old_nof; i++) {
4344  PropertyDetails details = new_descriptors->GetDetails(i);
4345  if (details.location() != kField) continue;
4346  DCHECK_EQ(kData, details.kind());
4347  PropertyDetails old_details = old_descriptors->GetDetails(i);
4348  Representation old_representation = old_details.representation();
4349  Representation representation = details.representation();
4350  Handle<Object> value;
4351  if (old_details.location() == kDescriptor) {
4352  if (old_details.kind() == kAccessor) {
4353  // In case of kAccessor -> kData property reconfiguration, the property
4354  // must already be prepared for data of certain type.
4355  DCHECK(!details.representation().IsNone());
4356  if (details.representation().IsDouble()) {
4357  value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4358  } else {
4359  value = isolate->factory()->uninitialized_value();
4360  }
4361  } else {
4362  DCHECK_EQ(kData, old_details.kind());
4363  value = handle(old_descriptors->GetStrongValue(i), isolate);
4364  DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
4365  }
4366  } else {
4367  DCHECK_EQ(kField, old_details.location());
4368  FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
4369  if (object->IsUnboxedDoubleField(index)) {
4370  uint64_t old_bits = object->RawFastDoublePropertyAsBitsAt(index);
4371  if (representation.IsDouble()) {
4372  value = isolate->factory()->NewMutableHeapNumberFromBits(old_bits);
4373  } else {
4374  value = isolate->factory()->NewHeapNumberFromBits(old_bits);
4375  }
4376  } else {
4377  value = handle(object->RawFastPropertyAt(index), isolate);
4378  if (!old_representation.IsDouble() && representation.IsDouble()) {
4379  DCHECK_IMPLIES(old_representation.IsNone(),
4380  value->IsUninitialized(isolate));
4381  value = Object::NewStorageFor(isolate, value, representation);
4382  } else if (old_representation.IsDouble() &&
4383  !representation.IsDouble()) {
4384  value = Object::WrapForRead(isolate, value, old_representation);
4385  }
4386  }
4387  }
4388  DCHECK(!(representation.IsDouble() && value->IsSmi()));
4389  int target_index = new_descriptors->GetFieldIndex(i);
4390  if (target_index < inobject) {
4391  inobject_props->set(target_index, *value);
4392  } else {
4393  array->set(target_index - inobject, *value);
4394  }
4395  }
4396 
4397  for (int i = old_nof; i < new_nof; i++) {
4398  PropertyDetails details = new_descriptors->GetDetails(i);
4399  if (details.location() != kField) continue;
4400  DCHECK_EQ(kData, details.kind());
4401  Handle<Object> value;
4402  if (details.representation().IsDouble()) {
4403  value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
4404  } else {
4405  value = isolate->factory()->uninitialized_value();
4406  }
4407  int target_index = new_descriptors->GetFieldIndex(i);
4408  if (target_index < inobject) {
4409  inobject_props->set(target_index, *value);
4410  } else {
4411  array->set(target_index - inobject, *value);
4412  }
4413  }
4414 
4415  // From here on we cannot fail and we shouldn't GC anymore.
4416  DisallowHeapAllocation no_allocation;
4417 
4418  Heap* heap = isolate->heap();
4419 
4420  int old_instance_size = old_map->instance_size();
4421 
4422  heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
4423 
4424  // Copy (real) inobject properties. If necessary, stop at number_of_fields to
4425  // avoid overwriting |one_pointer_filler_map|.
4426  int limit = Min(inobject, number_of_fields);
4427  for (int i = 0; i < limit; i++) {
4428  FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4429  Object* value = inobject_props->get(i);
4430  // Can't use JSObject::FastPropertyAtPut() because proper map was not set
4431  // yet.
4432  if (new_map->IsUnboxedDoubleField(index)) {
4433  DCHECK(value->IsMutableHeapNumber());
4434  // Ensure that all bits of the double value are preserved.
4435  object->RawFastDoublePropertyAsBitsAtPut(
4436  index, MutableHeapNumber::cast(value)->value_as_bits());
4437  if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
4438  // Transition from tagged to untagged slot.
4439  heap->ClearRecordedSlot(*object,
4440  HeapObject::RawField(*object, index.offset()));
4441  } else {
4442 #ifdef DEBUG
4443  heap->VerifyClearedSlot(*object,
4444  HeapObject::RawField(*object, index.offset()));
4445 #endif
4446  }
4447  } else {
4448  object->RawFastPropertyAtPut(index, value);
4449  }
4450  }
4451 
4452  object->SetProperties(*array);
4453 
4454  // Create filler object past the new instance size.
4455  int new_instance_size = new_map->instance_size();
4456  int instance_size_delta = old_instance_size - new_instance_size;
4457  DCHECK_GE(instance_size_delta, 0);
4458 
4459  if (instance_size_delta > 0) {
4460  Address address = object->address();
4461  heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
4462  ClearRecordedSlots::kYes);
4463  }
4464 
4465  // We are storing the new map using release store after creating a filler for
4466  // the left-over space to avoid races with the sweeper thread.
4467  object->synchronized_set_map(*new_map);
4468 }
4469 
4470 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
4471  int expected_additional_properties) {
4472  // The global object is always normalized.
4473  DCHECK(!object->IsJSGlobalObject());
4474  // JSGlobalProxy must never be normalized
4475  DCHECK(!object->IsJSGlobalProxy());
4476 
4477  DCHECK_IMPLIES(new_map->is_prototype_map(),
4478  Map::IsPrototypeChainInvalidated(*new_map));
4479 
4480  Isolate* isolate = object->GetIsolate();
4481  HandleScope scope(isolate);
4482  Handle<Map> map(object->map(), isolate);
4483 
4484  // Allocate new content.
4485  int real_size = map->NumberOfOwnDescriptors();
4486  int property_count = real_size;
4487  if (expected_additional_properties > 0) {
4488  property_count += expected_additional_properties;
4489  } else {
4490  // Make space for two more properties.
4491  property_count += NameDictionary::kInitialCapacity;
4492  }
4493  Handle<NameDictionary> dictionary =
4494  NameDictionary::New(isolate, property_count);
4495 
4496  Handle<DescriptorArray> descs(map->instance_descriptors(), isolate);
4497  for (int i = 0; i < real_size; i++) {
4498  PropertyDetails details = descs->GetDetails(i);
4499  Handle<Name> key(descs->GetKey(i), isolate);
4500  Handle<Object> value;
4501  if (details.location() == kField) {
4502  FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4503  if (details.kind() == kData) {
4504  if (object->IsUnboxedDoubleField(index)) {
4505  double old_value = object->RawFastDoublePropertyAt(index);
4506  value = isolate->factory()->NewHeapNumber(old_value);
4507  } else {
4508  value = handle(object->RawFastPropertyAt(index), isolate);
4509  if (details.representation().IsDouble()) {
4510  DCHECK(value->IsMutableHeapNumber());
4511  double old_value = Handle<MutableHeapNumber>::cast(value)->value();
4512  value = isolate->factory()->NewHeapNumber(old_value);
4513  }
4514  }
4515  } else {
4516  DCHECK_EQ(kAccessor, details.kind());
4517  value = handle(object->RawFastPropertyAt(index), isolate);
4518  }
4519 
4520  } else {
4521  DCHECK_EQ(kDescriptor, details.location());
4522  value = handle(descs->GetStrongValue(i), isolate);
4523  }
4524  DCHECK(!value.is_null());
4525  PropertyDetails d(details.kind(), details.attributes(),
4526  PropertyCellType::kNoCell);
4527  dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
4528  }
4529 
4530  // Copy the next enumeration index from instance descriptor.
4531  dictionary->SetNextEnumerationIndex(real_size + 1);
4532 
4533  // From here on we cannot fail and we shouldn't GC anymore.
4534  DisallowHeapAllocation no_allocation;
4535 
4536  Heap* heap = isolate->heap();
4537  int old_instance_size = map->instance_size();
4538  heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
4539 
4540  // Resize the object in the heap if necessary.
4541  int new_instance_size = new_map->instance_size();
4542  int instance_size_delta = old_instance_size - new_instance_size;
4543  DCHECK_GE(instance_size_delta, 0);
4544 
4545  if (instance_size_delta > 0) {
4546  heap->CreateFillerObjectAt(object->address() + new_instance_size,
4547  instance_size_delta, ClearRecordedSlots::kYes);
4548  }
4549 
4550  // We are storing the new map using release store after creating a filler for
4551  // the left-over space to avoid races with the sweeper thread.
4552  object->synchronized_set_map(*new_map);
4553 
4554  object->SetProperties(*dictionary);
4555 
4556  // Ensure that in-object space of slow-mode object does not contain random
4557  // garbage.
4558  int inobject_properties = new_map->GetInObjectProperties();
4559  if (inobject_properties) {
4560  Heap* heap = isolate->heap();
4561  heap->ClearRecordedSlotRange(
4562  object->address() + map->GetInObjectPropertyOffset(0),
4563  object->address() + new_instance_size);
4564 
4565  for (int i = 0; i < inobject_properties; i++) {
4566  FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4567  object->RawFastPropertyAtPut(index, Smi::kZero);
4568  }
4569  }
4570 
4571  isolate->counters()->props_to_dictionary()->Increment();
4572 
4573 #ifdef DEBUG
4574  if (FLAG_trace_normalization) {
4575  StdoutStream os;
4576  os << "Object properties have been normalized:\n";
4577  object->Print(os);
4578  }
4579 #endif
4580 }
4581 
4582 } // namespace
4583 
4584 // static
4585 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
4586  Isolate* isolate) {
4587  if (!old_map->is_prototype_map()) return;
4588 
4589  InvalidatePrototypeChains(*old_map);
4590 
4591  // If the map was registered with its prototype before, ensure that it
4592  // registers with its new prototype now. This preserves the invariant that
4593  // when a map on a prototype chain is registered with its prototype, then
4594  // all prototypes further up the chain are also registered with their
4595  // respective prototypes.
4596  UpdatePrototypeUserRegistration(old_map, new_map, isolate);
4597 }
4598 
4599 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
4600  int expected_additional_properties) {
4601  if (object->map() == *new_map) return;
4602  Handle<Map> old_map(object->map(), object->GetIsolate());
4603  NotifyMapChange(old_map, new_map, object->GetIsolate());
4604 
4605  if (old_map->is_dictionary_map()) {
4606  // For slow-to-fast migrations JSObject::MigrateSlowToFast()
4607  // must be used instead.
4608  CHECK(new_map->is_dictionary_map());
4609 
4610  // Slow-to-slow migration is trivial.
4611  object->synchronized_set_map(*new_map);
4612  } else if (!new_map->is_dictionary_map()) {
4613  MigrateFastToFast(object, new_map);
4614  if (old_map->is_prototype_map()) {
4615  DCHECK(!old_map->is_stable());
4616  DCHECK(new_map->is_stable());
4617  DCHECK(new_map->owns_descriptors());
4618  DCHECK(old_map->owns_descriptors());
4619  // Transfer ownership to the new map. Keep the descriptor pointer of the
4620  // old map intact because the concurrent marker might be iterating the
4621  // object with the old map.
4622  old_map->set_owns_descriptors(false);
4623  DCHECK(old_map->is_abandoned_prototype_map());
4624  // Ensure that no transition was inserted for prototype migrations.
4625  DCHECK_EQ(0, TransitionsAccessor(object->GetIsolate(), old_map)
4626  .NumberOfTransitions());
4627  DCHECK(new_map->GetBackPointer()->IsUndefined());
4628  DCHECK(object->map() != *old_map);
4629  }
4630  } else {
4631  MigrateFastToSlow(object, new_map, expected_additional_properties);
4632  }
4633 
4634  // Careful: Don't allocate here!
4635  // For some callers of this method, |object| might be in an inconsistent
4636  // state now: the new map might have a new elements_kind, but the object's
4637  // elements pointer hasn't been updated yet. Callers will fix this, but in
4638  // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
4639  // When adding code here, add a DisallowHeapAllocation too.
4640 }
4641 
4642 void JSObject::ForceSetPrototype(Handle<JSObject> object,
4643  Handle<Object> proto) {
4644  // object.__proto__ = proto;
4645  Handle<Map> old_map = Handle<Map>(object->map(), object->GetIsolate());
4646  Handle<Map> new_map =
4647  Map::Copy(object->GetIsolate(), old_map, "ForceSetPrototype");
4648  Map::SetPrototype(object->GetIsolate(), new_map, proto);
4649  JSObject::MigrateToMap(object, new_map);
4650 }
4651 
4652 int Map::NumberOfFields() const {
4653  DescriptorArray* descriptors = instance_descriptors();
4654  int result = 0;
4655  for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
4656  if (descriptors->GetDetails(i).location() == kField) result++;
4657  }
4658  return result;
4659 }
4660 
4661 Map::FieldCounts Map::GetFieldCounts() const {
4662  DescriptorArray* descriptors = instance_descriptors();
4663  int mutable_count = 0;
4664  int const_count = 0;
4665  for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
4666  PropertyDetails details = descriptors->GetDetails(i);
4667  if (details.location() == kField) {
4668  switch (details.constness()) {
4669  case PropertyConstness::kMutable:
4670  mutable_count++;
4671  break;
4672  case PropertyConstness::kConst:
4673  const_count++;
4674  break;
4675  }
4676  }
4677  }
4678  return FieldCounts(mutable_count, const_count);
4679 }
4680 
4681 bool Map::HasOutOfObjectProperties() const {
4682  return GetInObjectProperties() < NumberOfFields();
4683 }
4684 
4685 void DescriptorArray::GeneralizeAllFields() {
4686  int length = number_of_descriptors();
4687  for (int i = 0; i < length; i++) {
4688  PropertyDetails details = GetDetails(i);
4689  details = details.CopyWithRepresentation(Representation::Tagged());
4690  if (details.location() == kField) {
4691  DCHECK_EQ(kData, details.kind());
4692  details = details.CopyWithConstness(PropertyConstness::kMutable);
4693  SetValue(i, FieldType::Any());
4694  }
4695  set(ToDetailsIndex(i), MaybeObject::FromObject(details.AsSmi()));
4696  }
4697 }
4698 
4699 Handle<Map> Map::CopyGeneralizeAllFields(Isolate* isolate, Handle<Map> map,
4700  ElementsKind elements_kind,
4701  int modify_index, PropertyKind kind,
4702  PropertyAttributes attributes,
4703  const char* reason) {
4704  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
4705  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
4706  Handle<DescriptorArray> descriptors = DescriptorArray::CopyUpTo(
4707  isolate, old_descriptors, number_of_own_descriptors);
4708  descriptors->GeneralizeAllFields();
4709 
4710  Handle<LayoutDescriptor> new_layout_descriptor(
4711  LayoutDescriptor::FastPointerLayout(), isolate);
4712  Handle<Map> new_map = CopyReplaceDescriptors(
4713  isolate, map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
4714  MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
4715 
4716  // Unless the instance is being migrated, ensure that modify_index is a field.
4717  if (modify_index >= 0) {
4718  PropertyDetails details = descriptors->GetDetails(modify_index);
4719  if (details.constness() != PropertyConstness::kMutable ||
4720  details.location() != kField || details.attributes() != attributes) {
4721  int field_index = details.location() == kField
4722  ? details.field_index()
4723  : new_map->NumberOfFields();
4724  Descriptor d = Descriptor::DataField(
4725  isolate, handle(descriptors->GetKey(modify_index), isolate),
4726  field_index, attributes, Representation::Tagged());
4727  descriptors->Replace(modify_index, &d);
4728  if (details.location() != kField) {
4729  new_map->AccountAddedPropertyField();
4730  }
4731  } else {
4732  DCHECK(details.attributes() == attributes);
4733  }
4734 
4735  if (FLAG_trace_generalization) {
4736  MaybeHandle<FieldType> field_type = FieldType::None(isolate);
4737  if (details.location() == kField) {
4738  field_type = handle(
4739  map->instance_descriptors()->GetFieldType(modify_index), isolate);
4740  }
4741  map->PrintGeneralization(
4742  isolate, stdout, reason, modify_index,
4743  new_map->NumberOfOwnDescriptors(), new_map->NumberOfOwnDescriptors(),
4744  details.location() == kDescriptor, details.representation(),
4745  Representation::Tagged(), field_type, MaybeHandle<Object>(),
4746  FieldType::Any(isolate), MaybeHandle<Object>());
4747  }
4748  }
4749  new_map->set_elements_kind(elements_kind);
4750  return new_map;
4751 }
4752 
4753 void Map::DeprecateTransitionTree(Isolate* isolate) {
4754  if (is_deprecated()) return;
4755  DisallowHeapAllocation no_gc;
4756  TransitionsAccessor transitions(isolate, *this, &no_gc);
4757  int num_transitions = transitions.NumberOfTransitions();
4758  for (int i = 0; i < num_transitions; ++i) {
4759  transitions.GetTarget(i)->DeprecateTransitionTree(isolate);
4760  }
4761  DCHECK(!constructor_or_backpointer()->IsFunctionTemplateInfo());
4762  set_is_deprecated(true);
4763  if (FLAG_trace_maps) {
4764  LOG(isolate, MapEvent("Deprecate", *this, Map()));
4765  }
4766  dependent_code()->DeoptimizeDependentCodeGroup(
4767  isolate, DependentCode::kTransitionGroup);
4768  NotifyLeafMapLayoutChange(isolate);
4769 }
4770 
4771 
4772 // Installs |new_descriptors| over the current instance_descriptors to ensure
4773 // proper sharing of descriptor arrays.
4774 void Map::ReplaceDescriptors(Isolate* isolate, DescriptorArray* new_descriptors,
4775  LayoutDescriptor new_layout_descriptor) {
4776  // Don't overwrite the empty descriptor array or initial map's descriptors.
4777  if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
4778  return;
4779  }
4780 
4781  DescriptorArray* to_replace = instance_descriptors();
4782  // Replace descriptors by new_descriptors in all maps that share it. The old
4783  // descriptors will not be trimmed in the mark-compactor, we need to mark
4784  // all its elements.
4785  MarkingBarrierForElements(isolate->heap(), to_replace);
4786  Map current = *this;
4787  while (current->instance_descriptors() == to_replace) {
4788  Object* next = current->GetBackPointer();
4789  if (next->IsUndefined(isolate)) break; // Stop overwriting at initial map.
4790  current->SetEnumLength(kInvalidEnumCacheSentinel);
4791  current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
4792  current = Map::cast(next);
4793  }
4794  set_owns_descriptors(false);
4795 }
4796 
4797 Map Map::FindRootMap(Isolate* isolate) const {
4798  Map result = *this;
4799  while (true) {
4800  Object* back = result->GetBackPointer();
4801  if (back->IsUndefined(isolate)) {
4802  // Initial map always owns descriptors and doesn't have unused entries
4803  // in the descriptor array.
4804  DCHECK(result->owns_descriptors());
4805  DCHECK_EQ(result->NumberOfOwnDescriptors(),
4806  result->instance_descriptors()->number_of_descriptors());
4807  return result;
4808  }
4809  result = Map::cast(back);
4810  }
4811 }
4812 
4813 Map Map::FindFieldOwner(Isolate* isolate, int descriptor) const {
4814  DisallowHeapAllocation no_allocation;
4815  DCHECK_EQ(kField, instance_descriptors()->GetDetails(descriptor).location());
4816  Map result = *this;
4817  while (true) {
4818  Object* back = result->GetBackPointer();
4819  if (back->IsUndefined(isolate)) break;
4820  const Map parent = Map::cast(back);
4821  if (parent->NumberOfOwnDescriptors() <= descriptor) break;
4822  result = parent;
4823  }
4824  return result;
4825 }
4826 
4827 void Map::UpdateFieldType(Isolate* isolate, int descriptor, Handle<Name> name,
4828  PropertyConstness new_constness,
4829  Representation new_representation,
4830  const MaybeObjectHandle& new_wrapped_type) {
4831  DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeak());
4832  // We store raw pointers in the queue, so no allocations are allowed.
4833  DisallowHeapAllocation no_allocation;
4834  PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
4835  if (details.location() != kField) return;
4836  DCHECK_EQ(kData, details.kind());
4837 
4838  Zone zone(isolate->allocator(), ZONE_NAME);
4839  ZoneQueue<Map> backlog(&zone);
4840  backlog.push(*this);
4841 
4842  while (!backlog.empty()) {
4843  Map current = backlog.front();
4844  backlog.pop();
4845 
4846  TransitionsAccessor transitions(isolate, current, &no_allocation);
4847  int num_transitions = transitions.NumberOfTransitions();
4848  for (int i = 0; i < num_transitions; ++i) {
4849  Map target = transitions.GetTarget(i);
4850  backlog.push(target);
4851  }
4852  DescriptorArray* descriptors = current->instance_descriptors();
4853  PropertyDetails details = descriptors->GetDetails(descriptor);
4854 
4855  // Currently constness change implies map change.
4856  DCHECK_IMPLIES(new_constness != details.constness(),
4857  FLAG_modify_map_inplace);
4858 
4859  // It is allowed to change representation here only from None to something.
4860  DCHECK(details.representation().Equals(new_representation) ||
4861  details.representation().IsNone());
4862 
4863  // Skip if already updated the shared descriptor.
4864  if ((FLAG_modify_map_inplace && new_constness != details.constness()) ||
4865  descriptors->GetFieldType(descriptor) != *new_wrapped_type.object()) {
4866  DCHECK_IMPLIES(!FLAG_track_constant_fields,
4867  new_constness == PropertyConstness::kMutable);
4868  Descriptor d = Descriptor::DataField(
4869  name, descriptors->GetFieldIndex(descriptor), details.attributes(),
4870  new_constness, new_representation, new_wrapped_type);
4871  descriptors->Replace(descriptor, &d);
4872  }
4873  }
4874 }
4875 
4876 bool FieldTypeIsCleared(Representation rep, FieldType type) {
4877  return type->IsNone() && rep.IsHeapObject();
4878 }
4879 
4880 
4881 // static
4882 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
4883  Handle<FieldType> type1,
4884  Representation rep2,
4885  Handle<FieldType> type2,
4886  Isolate* isolate) {
4887  // Cleared field types need special treatment. They represent lost knowledge,
4888  // so we must be conservative, so their generalization with any other type
4889  // is "Any".
4890  if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
4891  return FieldType::Any(isolate);
4892  }
4893  if (type1->NowIs(type2)) return type2;
4894  if (type2->NowIs(type1)) return type1;
4895  return FieldType::Any(isolate);
4896 }
4897 
4898 // static
4899 void Map::GeneralizeField(Isolate* isolate, Handle<Map> map, int modify_index,
4900  PropertyConstness new_constness,
4901  Representation new_representation,
4902  Handle<FieldType> new_field_type) {
4903  // Check if we actually need to generalize the field type at all.
4904  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
4905  PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4906  PropertyConstness old_constness = old_details.constness();
4907  Representation old_representation = old_details.representation();
4908  Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
4909  isolate);
4910 
4911  // Return if the current map is general enough to hold requested constness and
4912  // representation/field type.
4913  if (((FLAG_modify_map_inplace &&
4914  IsGeneralizableTo(new_constness, old_constness)) ||
4915  (!FLAG_modify_map_inplace && (old_constness == new_constness))) &&
4916  old_representation.Equals(new_representation) &&
4917  !FieldTypeIsCleared(new_representation, *new_field_type) &&
4918  // Checking old_field_type for being cleared is not necessary because
4919  // the NowIs check below would fail anyway in that case.
4920  new_field_type->NowIs(old_field_type)) {
4921  DCHECK(GeneralizeFieldType(old_representation, old_field_type,
4922  new_representation, new_field_type, isolate)
4923  ->NowIs(old_field_type));
4924  return;
4925  }
4926 
4927  // Determine the field owner.
4928  Handle<Map> field_owner(map->FindFieldOwner(isolate, modify_index), isolate);
4929  Handle<DescriptorArray> descriptors(field_owner->instance_descriptors(),
4930  isolate);
4931  DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
4932 
4933  new_field_type =
4934  Map::GeneralizeFieldType(old_representation, old_field_type,
4935  new_representation, new_field_type, isolate);
4936  if (FLAG_modify_map_inplace) {
4937  new_constness = GeneralizeConstness(old_constness, new_constness);
4938  }
4939 
4940  PropertyDetails details = descriptors->GetDetails(modify_index);
4941  Handle<Name> name(descriptors->GetKey(modify_index), isolate);
4942 
4943  MaybeObjectHandle wrapped_type(WrapFieldType(isolate, new_field_type));
4944  field_owner->UpdateFieldType(isolate, modify_index, name, new_constness,
4945  new_representation, wrapped_type);
4946  field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
4947  isolate, DependentCode::kFieldOwnerGroup);
4948 
4949  if (FLAG_trace_generalization) {
4950  map->PrintGeneralization(
4951  isolate, stdout, "field type generalization", modify_index,
4952  map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
4953  details.representation(), details.representation(), old_field_type,
4954  MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
4955  }
4956 }
4957 
4958 // TODO(ishell): remove.
4959 // static
4960 Handle<Map> Map::ReconfigureProperty(Isolate* isolate, Handle<Map> map,
4961  int modify_index, PropertyKind new_kind,
4962  PropertyAttributes new_attributes,
4963  Representation new_representation,
4964  Handle<FieldType> new_field_type) {
4965  DCHECK_EQ(kData, new_kind); // Only kData case is supported.
4966  MapUpdater mu(isolate, map);
4967  return mu.ReconfigureToDataField(modify_index, new_attributes,
4968  PropertyConstness::kConst,
4969  new_representation, new_field_type);
4970 }
4971 
4972 // TODO(ishell): remove.
4973 // static
4974 Handle<Map> Map::ReconfigureElementsKind(Isolate* isolate, Handle<Map> map,
4975  ElementsKind new_elements_kind) {
4976  MapUpdater mu(isolate, map);
4977  return mu.ReconfigureElementsKind(new_elements_kind);
4978 }
4979 
4980 namespace {
4981 
4982 Map SearchMigrationTarget(Isolate* isolate, Map old_map) {
4983  DisallowHeapAllocation no_allocation;
4984  DisallowDeoptimization no_deoptimization(isolate);
4985 
4986  Map target = old_map;
4987  do {
4988  target = TransitionsAccessor(isolate, target, &no_allocation)
4989  .GetMigrationTarget();
4990  } while (!target.is_null() && target->is_deprecated());
4991  if (target.is_null()) return Map();
4992 
4993  // TODO(ishell): if this validation ever become a bottleneck consider adding a
4994  // bit to the Map telling whether it contains fields whose field types may be
4995  // cleared.
4996  // TODO(ishell): revisit handling of cleared field types in
4997  // TryReplayPropertyTransitions() and consider checking the target map's field
4998  // types instead of old_map's types.
4999  // Go to slow map updating if the old_map has fast properties with cleared
5000  // field types.
5001  int old_nof = old_map->NumberOfOwnDescriptors();
5002  DescriptorArray* old_descriptors = old_map->instance_descriptors();
5003  for (int i = 0; i < old_nof; i++) {
5004  PropertyDetails old_details = old_descriptors->GetDetails(i);
5005  if (old_details.location() == kField && old_details.kind() == kData) {
5006  FieldType old_type = old_descriptors->GetFieldType(i);
5007  if (FieldTypeIsCleared(old_details.representation(), old_type)) {
5008  return Map();
5009  }
5010  }
5011  }
5012 
5013  SLOW_DCHECK(Map::TryUpdateSlow(isolate, old_map) == target);
5014  return target;
5015 }
5016 } // namespace
5017 
5018 // TODO(ishell): Move TryUpdate() and friends to MapUpdater
5019 // static
5020 MaybeHandle<Map> Map::TryUpdate(Isolate* isolate, Handle<Map> old_map) {
5021  DisallowHeapAllocation no_allocation;
5022  DisallowDeoptimization no_deoptimization(isolate);
5023 
5024  if (!old_map->is_deprecated()) return old_map;
5025 
5026  if (FLAG_fast_map_update) {
5027  Map target_map = SearchMigrationTarget(isolate, *old_map);
5028  if (!target_map.is_null()) {
5029  return handle(target_map, isolate);
5030  }
5031  }
5032 
5033  Map new_map = TryUpdateSlow(isolate, *old_map);
5034  if (new_map.is_null()) return MaybeHandle<Map>();
5035  if (FLAG_fast_map_update) {
5036  TransitionsAccessor(isolate, *old_map, &no_allocation)
5037  .SetMigrationTarget(new_map);
5038  }
5039  return handle(new_map, isolate);
5040 }
5041 
5042 Map Map::TryUpdateSlow(Isolate* isolate, Map old_map) {
5043  DisallowHeapAllocation no_allocation;
5044  DisallowDeoptimization no_deoptimization(isolate);
5045 
5046  // Check the state of the root map.
5047  Map root_map = old_map->FindRootMap(isolate);
5048  if (root_map->is_deprecated()) {
5049  JSFunction* constructor = JSFunction::cast(root_map->GetConstructor());
5050  DCHECK(constructor->has_initial_map());
5051  DCHECK(constructor->initial_map()->is_dictionary_map());
5052  if (constructor->initial_map()->elements_kind() !=
5053  old_map->elements_kind()) {
5054  return Map();
5055  }
5056  return constructor->initial_map();
5057  }
5058  if (!old_map->EquivalentToForTransition(root_map)) return Map();
5059 
5060  ElementsKind from_kind = root_map->elements_kind();
5061  ElementsKind to_kind = old_map->elements_kind();
5062  if (from_kind != to_kind) {
5063  // Try to follow existing elements kind transitions.
5064  root_map = root_map->LookupElementsTransitionMap(isolate, to_kind);
5065  if (root_map.is_null()) return Map();
5066  // From here on, use the map with correct elements kind as root map.
5067  }
5068  return root_map->TryReplayPropertyTransitions(isolate, old_map);
5069 }
5070 
5071 Map Map::TryReplayPropertyTransitions(Isolate* isolate, Map old_map) {
5072  DisallowHeapAllocation no_allocation;
5073  DisallowDeoptimization no_deoptimization(isolate);
5074 
5075  int root_nof = NumberOfOwnDescriptors();
5076 
5077  int old_nof = old_map->NumberOfOwnDescriptors();
5078  DescriptorArray* old_descriptors = old_map->instance_descriptors();
5079 
5080  Map new_map = *this;
5081  for (int i = root_nof; i < old_nof; ++i) {
5082  PropertyDetails old_details = old_descriptors->GetDetails(i);
5083  Map transition =
5084  TransitionsAccessor(isolate, new_map, &no_allocation)
5085  .SearchTransition(old_descriptors->GetKey(i), old_details.kind(),
5086  old_details.attributes());
5087  if (transition.is_null()) return Map();
5088  new_map = transition;
5089  DescriptorArray* new_descriptors = new_map->instance_descriptors();
5090 
5091  PropertyDetails new_details = new_descriptors->GetDetails(i);
5092  DCHECK_EQ(old_details.kind(), new_details.kind());
5093  DCHECK_EQ(old_details.attributes(), new_details.attributes());
5094  if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
5095  return Map();
5096  }
5097  DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
5098  if (!old_details.representation().fits_into(new_details.representation())) {
5099  return Map();
5100  }
5101  if (new_details.location() == kField) {
5102  if (new_details.kind() == kData) {
5103  FieldType new_type = new_descriptors->GetFieldType(i);
5104  // Cleared field types need special treatment. They represent lost
5105  // knowledge, so we must first generalize the new_type to "Any".
5106  if (FieldTypeIsCleared(new_details.representation(), new_type)) {
5107  return Map();
5108  }
5109  DCHECK_EQ(kData, old_details.kind());
5110  if (old_details.location() == kField) {
5111  FieldType old_type = old_descriptors->GetFieldType(i);
5112  if (FieldTypeIsCleared(old_details.representation(), old_type) ||
5113  !old_type->NowIs(new_type)) {
5114  return Map();
5115  }
5116  } else {
5117  DCHECK_EQ(kDescriptor, old_details.location());
5118  DCHECK(!FLAG_track_constant_fields);
5119  Object* old_value = old_descriptors->GetStrongValue(i);
5120  if (!new_type->NowContains(old_value)) {
5121  return Map();
5122  }
5123  }
5124 
5125  } else {
5126  DCHECK_EQ(kAccessor, new_details.kind());
5127 #ifdef DEBUG
5128  FieldType new_type = new_descriptors->GetFieldType(i);
5129  DCHECK(new_type->IsAny());
5130 #endif
5131  UNREACHABLE();
5132  }
5133  } else {
5134  DCHECK_EQ(kDescriptor, new_details.location());
5135  if (old_details.location() == kField ||
5136  old_descriptors->GetStrongValue(i) !=
5137  new_descriptors->GetStrongValue(i)) {
5138  return Map();
5139  }
5140  }
5141  }
5142  if (new_map->NumberOfOwnDescriptors() != old_nof) return Map();
5143  return new_map;
5144 }
5145 
5146 
5147 // static
5148 Handle<Map> Map::Update(Isolate* isolate, Handle<Map> map) {
5149  if (!map->is_deprecated()) return map;
5150  if (FLAG_fast_map_update) {
5151  Map target_map = SearchMigrationTarget(isolate, *map);
5152  if (!target_map.is_null()) {
5153  return handle(target_map, isolate);
5154  }
5155  }
5156  MapUpdater mu(isolate, map);
5157  return mu.Update();
5158 }
5159 
5160 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
5161  ShouldThrow should_throw,
5162  Handle<Object> value) {
5163  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
5164  return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
5165  should_throw, value);
5166 }
5167 
5168 MaybeHandle<Object> Object::SetProperty(Isolate* isolate, Handle<Object> object,
5169  Handle<Name> name, Handle<Object> value,
5170  LanguageMode language_mode,
5171  StoreOrigin store_origin) {
5172  LookupIterator it(isolate, object, name);
5173  MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_origin));
5174  return value;
5175 }
5176 
5177 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
5178  Handle<Object> value,
5179  LanguageMode language_mode,
5180  StoreOrigin store_origin, bool* found) {
5181  it->UpdateProtector();
5182  DCHECK(it->IsFound());
5183  ShouldThrow should_throw =
5184  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5185 
5186  // Make sure that the top context does not change when doing callbacks or
5187  // interceptor calls.
5188  AssertNoContextChange ncc(it->isolate());
5189 
5190  do {
5191  switch (it->state()) {
5192  case LookupIterator::NOT_FOUND:
5193  UNREACHABLE();
5194 
5195  case LookupIterator::ACCESS_CHECK:
5196  if (it->HasAccess()) break;
5197  // Check whether it makes sense to reuse the lookup iterator. Here it
5198  // might still call into setters up the prototype chain.
5199  return JSObject::SetPropertyWithFailedAccessCheck(it, value,
5200  should_throw);
5201 
5202  case LookupIterator::JSPROXY:
5203  return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
5204  value, it->GetReceiver(), language_mode);
5205 
5206  case LookupIterator::INTERCEPTOR: {
5207  if (it->HolderIsReceiverOrHiddenPrototype()) {
5208  Maybe<bool> result =
5209  JSObject::SetPropertyWithInterceptor(it, should_throw, value);
5210  if (result.IsNothing() || result.FromJust()) return result;
5211  } else {
5212  Maybe<PropertyAttributes> maybe_attributes =
5213  JSObject::GetPropertyAttributesWithInterceptor(it);
5214  if (maybe_attributes.IsNothing()) return Nothing<bool>();
5215  if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
5216  return WriteToReadOnlyProperty(it, value, should_throw);
5217  }
5218  if (maybe_attributes.FromJust() == ABSENT) break;
5219  *found = false;
5220  return Nothing<bool>();
5221  }
5222  break;
5223  }
5224 
5225  case LookupIterator::ACCESSOR: {
5226  if (it->IsReadOnly()) {
5227  return WriteToReadOnlyProperty(it, value, should_throw);
5228  }
5229  Handle<Object> accessors = it->GetAccessors();
5230  if (accessors->IsAccessorInfo() &&
5231  !it->HolderIsReceiverOrHiddenPrototype() &&
5232  AccessorInfo::cast(*accessors)->is_special_data_property()) {
5233  *found = false;
5234  return Nothing<bool>();
5235  }
5236  return SetPropertyWithAccessor(it, value, should_throw);
5237  }
5238  case LookupIterator::INTEGER_INDEXED_EXOTIC: {
5239  // IntegerIndexedElementSet converts value to a Number/BigInt prior to
5240  // the bounds check. The bounds check has already happened here, but
5241  // perform the possibly effectful ToNumber (or ToBigInt) operation
5242  // anyways.
5243  auto holder = it->GetHolder<JSTypedArray>();
5244  Handle<Object> throwaway_value;
5245  if (holder->type() == kExternalBigInt64Array ||
5246  holder->type() == kExternalBigUint64Array) {
5247  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5248  it->isolate(), throwaway_value,
5249  BigInt::FromObject(it->isolate(), value), Nothing<bool>());
5250  } else {
5251  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5252  it->isolate(), throwaway_value,
5253  Object::ToNumber(it->isolate(), value), Nothing<bool>());
5254  }
5255 
5256  // FIXME: Throw a TypeError if the holder is neutered here
5257  // (IntegerIndexedElementSpec step 5).
5258 
5259  // TODO(verwaest): Per spec, we should return false here (steps 6-9
5260  // in IntegerIndexedElementSpec), resulting in an exception being thrown
5261  // on OOB accesses in strict code. Historically, v8 has not done made
5262  // this change due to uncertainty about web compat. (v8:4901)
5263  return Just(true);
5264  }
5265 
5266  case LookupIterator::DATA:
5267  if (it->IsReadOnly()) {
5268  return WriteToReadOnlyProperty(it, value, should_throw);
5269  }
5270  if (it->HolderIsReceiverOrHiddenPrototype()) {
5271  return SetDataProperty(it, value);
5272  }
5273  V8_FALLTHROUGH;
5274  case LookupIterator::TRANSITION:
5275  *found = false;
5276  return Nothing<bool>();
5277  }
5278  it->Next();
5279  } while (it->IsFound());
5280 
5281  *found = false;
5282  return Nothing<bool>();
5283 }
5284 
5285 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
5286  LanguageMode language_mode,
5287  StoreOrigin store_origin) {
5288  if (it->IsFound()) {
5289  bool found = true;
5290  Maybe<bool> result =
5291  SetPropertyInternal(it, value, language_mode, store_origin, &found);
5292  if (found) return result;
5293  }
5294 
5295  // If the receiver is the JSGlobalObject, the store was contextual. In case
5296  // the property did not exist yet on the global object itself, we have to
5297  // throw a reference error in strict mode. In sloppy mode, we continue.
5298  if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
5299  it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
5300  MessageTemplate::kNotDefined, it->name()));
5301  return Nothing<bool>();
5302  }
5303 
5304  ShouldThrow should_throw =
5305  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5306  return AddDataProperty(it, value, NONE, should_throw, store_origin);
5307 }
5308 
5309 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
5310  LanguageMode language_mode,
5311  StoreOrigin store_origin) {
5312  Isolate* isolate = it->isolate();
5313 
5314  if (it->IsFound()) {
5315  bool found = true;
5316  Maybe<bool> result =
5317  SetPropertyInternal(it, value, language_mode, store_origin, &found);
5318  if (found) return result;
5319  }
5320 
5321  it->UpdateProtector();
5322 
5323  // The property either doesn't exist on the holder or exists there as a data
5324  // property.
5325 
5326  ShouldThrow should_throw =
5327  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
5328 
5329  if (!it->GetReceiver()->IsJSReceiver()) {
5330  return WriteToReadOnlyProperty(it, value, should_throw);
5331  }
5332  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
5333 
5334  LookupIterator::Configuration c = LookupIterator::OWN;
5335  LookupIterator own_lookup =
5336  it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
5337  : LookupIterator(isolate, receiver, it->name(), c);
5338 
5339  for (; own_lookup.IsFound(); own_lookup.Next()) {
5340  switch (own_lookup.state()) {
5341  case LookupIterator::ACCESS_CHECK:
5342  if (!own_lookup.HasAccess()) {
5343  return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
5344  should_throw);
5345  }
5346  break;
5347 
5348  case LookupIterator::ACCESSOR:
5349  if (own_lookup.GetAccessors()->IsAccessorInfo()) {
5350  if (own_lookup.IsReadOnly()) {
5351  return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
5352  }
5353  return JSObject::SetPropertyWithAccessor(&own_lookup, value,
5354  should_throw);
5355  }
5356  V8_FALLTHROUGH;
5357  case LookupIterator::INTEGER_INDEXED_EXOTIC:
5358  return RedefineIncompatibleProperty(isolate, it->GetName(), value,
5359  should_throw);
5360 
5361  case LookupIterator::DATA: {
5362  if (own_lookup.IsReadOnly()) {
5363  return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
5364  }
5365  return SetDataProperty(&own_lookup, value);
5366  }
5367 
5368  case LookupIterator::INTERCEPTOR:
5369  case LookupIterator::JSPROXY: {
5370  PropertyDescriptor desc;
5371  Maybe<bool> owned =
5372  JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
5373  MAYBE_RETURN(owned, Nothing<bool>());
5374  if (!owned.FromJust()) {
5375  return JSReceiver::CreateDataProperty(&own_lookup, value,
5376  should_throw);
5377  }
5378  if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
5379  !desc.writable()) {
5380  return RedefineIncompatibleProperty(isolate, it->GetName(), value,
5381  should_throw);
5382  }
5383 
5384  PropertyDescriptor value_desc;
5385  value_desc.set_value(value);
5386  return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
5387  &value_desc, should_throw);
5388  }
5389 
5390  case LookupIterator::NOT_FOUND:
5391  case LookupIterator::TRANSITION:
5392  UNREACHABLE();
5393  }
5394  }
5395 
5396  return AddDataProperty(&own_lookup, value, NONE, should_throw, store_origin);
5397 }
5398 
5399 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
5400  Handle<Object> receiver,
5401  Handle<Object> name,
5402  Handle<Object> value,
5403  ShouldThrow should_throw) {
5404  RETURN_FAILURE(
5405  isolate, should_throw,
5406  NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
5407  Object::TypeOf(isolate, receiver), receiver));
5408 }
5409 
5410 
5411 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
5412  Handle<Object> value,
5413  ShouldThrow should_throw) {
5414  if (it->IsFound() && !it->HolderIsReceiver()) {
5415  // "Override mistake" attempted, record a use count to track this per
5416  // v8:8175
5417  v8::Isolate::UseCounterFeature feature =
5418  should_throw == kThrowOnError
5419  ? v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeStrict
5420  : v8::Isolate::kAttemptOverrideReadOnlyOnPrototypeSloppy;
5421  it->isolate()->CountUsage(feature);
5422  }
5423  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
5424  it->GetName(), value, should_throw);
5425 }
5426 
5427 
5428 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
5429  Handle<Object> receiver,
5430  Handle<Object> name,
5431  Handle<Object> value,
5432  ShouldThrow should_throw) {
5433  RETURN_FAILURE(isolate, should_throw,
5434  NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
5435  Object::TypeOf(isolate, receiver), receiver));
5436 }
5437 
5438 
5439 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
5440  Handle<Object> name,
5441  Handle<Object> value,
5442  ShouldThrow should_throw) {
5443  RETURN_FAILURE(isolate, should_throw,
5444  NewTypeError(MessageTemplate::kRedefineDisallowed, name));
5445 }
5446 
5447 
5448 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
5449  DCHECK_IMPLIES(it->GetReceiver()->IsJSProxy(),
5450  it->GetName()->IsPrivateName());
5451  DCHECK_IMPLIES(!it->IsElement() && it->GetName()->IsPrivateName(),
5452  it->state() == LookupIterator::DATA);
5453  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
5454 
5455  // Store on the holder which may be hidden behind the receiver.
5456  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
5457 
5458  Handle<Object> to_assign = value;
5459  // Convert the incoming value to a number for storing into typed arrays.
5460  if (it->IsElement() && receiver->IsJSObject() &&
5461  JSObject::cast(*receiver)->HasFixedTypedArrayElements()) {
5462  ElementsKind elements_kind = JSObject::cast(*receiver)->GetElementsKind();
5463  if (elements_kind == BIGINT64_ELEMENTS ||
5464  elements_kind == BIGUINT64_ELEMENTS) {
5465  ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
5466  BigInt::FromObject(it->isolate(), value),
5467  Nothing<bool>());
5468  // We have to recheck the length. However, it can only change if the
5469  // underlying buffer was neutered, so just check that.
5470  if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
5471  return Just(true);
5472  // TODO(neis): According to the spec, this should throw a TypeError.
5473  }
5474  } else if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
5475  ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
5476  Object::ToNumber(it->isolate(), value),
5477  Nothing<bool>());
5478  // We have to recheck the length. However, it can only change if the
5479  // underlying buffer was neutered, so just check that.
5480  if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
5481  return Just(true);
5482  // TODO(neis): According to the spec, this should throw a TypeError.
5483  }
5484  }
5485  }
5486 
5487  // Possibly migrate to the most up-to-date map that will be able to store
5488  // |value| under it->name().
5489  it->PrepareForDataProperty(to_assign);
5490 
5491  // Write the property value.
5492  it->WriteDataValue(to_assign, false);
5493 
5494 #if VERIFY_HEAP
5495  if (FLAG_verify_heap) {
5496  receiver->HeapObjectVerify(it->isolate());
5497  }
5498 #endif
5499  return Just(true);
5500 }
5501 
5502 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
5503  PropertyAttributes attributes,
5504  ShouldThrow should_throw,
5505  StoreOrigin store_origin) {
5506  if (!it->GetReceiver()->IsJSReceiver()) {
5507  return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
5508  value, should_throw);
5509  }
5510 
5511  // Private symbols should be installed on JSProxy using
5512  // JSProxy::SetPrivateSymbol.
5513  if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate() &&
5514  !it->GetName()->IsPrivateName()) {
5515  RETURN_FAILURE(it->isolate(), should_throw,
5516  NewTypeError(MessageTemplate::kProxyPrivate));
5517  }
5518 
5519  DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
5520 
5521  Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
5522  DCHECK_IMPLIES(receiver->IsJSProxy(), it->GetName()->IsPrivateName());
5523  DCHECK_IMPLIES(receiver->IsJSProxy(),
5524  it->state() == LookupIterator::NOT_FOUND);
5525 
5526  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
5527  // instead. If the prototype is Null, the proxy is detached.
5528  if (receiver->IsJSGlobalProxy()) return Just(true);
5529 
5530  Isolate* isolate = it->isolate();
5531 
5532  if (it->ExtendingNonExtensible(receiver)) {
5533  RETURN_FAILURE(
5534  isolate, should_throw,
5535  NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
5536  }
5537 
5538  if (it->IsElement()) {
5539  if (receiver->IsJSArray()) {
5540  Handle<JSArray> array = Handle<JSArray>::cast(receiver);
5541  if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
5542  RETURN_FAILURE(isolate, should_throw,
5543  NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
5544  isolate->factory()->length_string(),
5545  Object::TypeOf(isolate, array), array));
5546  }
5547 
5548  if (FLAG_trace_external_array_abuse &&
5549  array->HasFixedTypedArrayElements()) {
5550  CheckArrayAbuse(array, "typed elements write", it->index(), true);
5551  }
5552 
5553  if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
5554  CheckArrayAbuse(array, "elements write", it->index(), false);
5555  }
5556  }
5557 
5558  Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
5559  JSObject::AddDataElement(receiver_obj, it->index(), value, attributes);
5560  JSObject::ValidateElements(*receiver_obj);
5561  return Just(true);
5562  } else {
5563  it->UpdateProtector();
5564  // Migrate to the most up-to-date map that will be able to store |value|
5565  // under it->name() with |attributes|.
5566  it->PrepareTransitionToDataProperty(receiver, value, attributes,
5567  store_origin);
5568  DCHECK_EQ(LookupIterator::TRANSITION, it->state());
5569  it->ApplyTransitionToDataProperty(receiver);
5570 
5571  // Write the property value.
5572  it->WriteDataValue(value, true);
5573 
5574 #if VERIFY_HEAP
5575  if (FLAG_verify_heap) {
5576  receiver->HeapObjectVerify(isolate);
5577  }
5578 #endif
5579  }
5580 
5581  return Just(true);
5582 }
5583 
5584 void Map::EnsureDescriptorSlack(Isolate* isolate, Handle<Map> map, int slack) {
5585  // Only supports adding slack to owned descriptors.
5586  DCHECK(map->owns_descriptors());
5587 
5588  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
5589  int old_size = map->NumberOfOwnDescriptors();
5590  if (slack <= descriptors->number_of_slack_descriptors()) return;
5591 
5592  Handle<DescriptorArray> new_descriptors =
5593  DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
5594 
5595  DisallowHeapAllocation no_allocation;
5596  // The descriptors are still the same, so keep the layout descriptor.
5597  LayoutDescriptor layout_descriptor = map->GetLayoutDescriptor();
5598 
5599  if (old_size == 0) {
5600  map->UpdateDescriptors(*new_descriptors, layout_descriptor);
5601  return;
5602  }
5603 
5604  // If the source descriptors had an enum cache we copy it. This ensures
5605  // that the maps to which we push the new descriptor array back can rely
5606  // on a cache always being available once it is set. If the map has more
5607  // enumerated descriptors than available in the original cache, the cache
5608  // will be lazily replaced by the extended cache when needed.
5609  new_descriptors->CopyEnumCacheFrom(*descriptors);
5610 
5611  // Replace descriptors by new_descriptors in all maps that share it. The old
5612  // descriptors will not be trimmed in the mark-compactor, we need to mark
5613  // all its elements.
5614  MarkingBarrierForElements(isolate->heap(), *descriptors);
5615 
5616  Map current = *map;
5617  while (current->instance_descriptors() == *descriptors) {
5618  Object* next = current->GetBackPointer();
5619  if (next->IsUndefined(isolate)) break; // Stop overwriting at initial map.
5620  current->UpdateDescriptors(*new_descriptors, layout_descriptor);
5621  current = Map::cast(next);
5622  }
5623  map->UpdateDescriptors(*new_descriptors, layout_descriptor);
5624 }
5625 
5626 // static
5627 Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,
5628  Handle<HeapObject> prototype) {
5629  Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
5630  isolate);
5631  if (map->prototype() == *prototype) return map;
5632  if (prototype->IsNull(isolate)) {
5633  return isolate->slow_object_with_null_prototype_map();
5634  }
5635  if (prototype->IsJSObject()) {
5636  Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
5637  if (!js_prototype->map()->is_prototype_map()) {
5638  JSObject::OptimizeAsPrototype(js_prototype);
5639  }
5640  Handle<PrototypeInfo> info =
5641  Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
5642  // TODO(verwaest): Use inobject slack tracking for this map.
5643  if (info->HasObjectCreateMap()) {
5644  map = handle(info->ObjectCreateMap(), isolate);
5645  } else {
5646  map = Map::CopyInitialMap(isolate, map);
5647  Map::SetPrototype(isolate, map, prototype);
5648  PrototypeInfo::SetObjectCreateMap(info, map);
5649  }
5650  return map;
5651  }
5652 
5653  return Map::TransitionToPrototype(isolate, map, prototype);
5654 }
5655 
5656 // static
5657 MaybeHandle<Map> Map::TryGetObjectCreateMap(Isolate* isolate,
5658  Handle<HeapObject> prototype) {
5659  Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
5660  isolate);
5661  if (map->prototype() == *prototype) return map;
5662  if (prototype->IsNull(isolate)) {
5663  return isolate->slow_object_with_null_prototype_map();
5664  }
5665  if (!prototype->IsJSObject()) return MaybeHandle<Map>();
5666  Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
5667  if (!js_prototype->map()->is_prototype_map()) return MaybeHandle<Map>();
5668  Handle<PrototypeInfo> info =
5669  Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
5670  if (!info->HasObjectCreateMap()) return MaybeHandle<Map>();
5671  return handle(info->ObjectCreateMap(), isolate);
5672 }
5673 
5674 template <class T>
5675 static int AppendUniqueCallbacks(Isolate* isolate,
5676  Handle<TemplateList> callbacks,
5677  Handle<typename T::Array> array,
5678  int valid_descriptors) {
5679  int nof_callbacks = callbacks->length();
5680 
5681  // Fill in new callback descriptors. Process the callbacks from
5682  // back to front so that the last callback with a given name takes
5683  // precedence over previously added callbacks with that name.
5684  for (int i = nof_callbacks - 1; i >= 0; i--) {
5685  Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)), isolate);
5686  Handle<Name> key(Name::cast(entry->name()), isolate);
5687  DCHECK(key->IsUniqueName());
5688  // Check if a descriptor with this name already exists before writing.
5689  if (!T::Contains(key, entry, valid_descriptors, array)) {
5690  T::Insert(key, entry, valid_descriptors, array);
5691  valid_descriptors++;
5692  }
5693  }
5694 
5695  return valid_descriptors;
5696 }
5697 
5699  typedef FixedArray Array;
5700  static bool Contains(Handle<Name> key,
5701  Handle<AccessorInfo> entry,
5702  int valid_descriptors,
5703  Handle<FixedArray> array) {
5704  for (int i = 0; i < valid_descriptors; i++) {
5705  if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
5706  }
5707  return false;
5708  }
5709  static void Insert(Handle<Name> key,
5710  Handle<AccessorInfo> entry,
5711  int valid_descriptors,
5712  Handle<FixedArray> array) {
5713  DisallowHeapAllocation no_gc;
5714  array->set(valid_descriptors, *entry);
5715  }
5716 };
5717 
5718 int AccessorInfo::AppendUnique(Isolate* isolate, Handle<Object> descriptors,
5719  Handle<FixedArray> array,
5720  int valid_descriptors) {
5721  Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
5722  DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
5723  return AppendUniqueCallbacks<FixedArrayAppender>(isolate, callbacks, array,
5724  valid_descriptors);
5725 }
5726 
5727 static bool ContainsMap(MapHandles const& maps, Map map) {
5728  DCHECK(!map.is_null());
5729  for (Handle<Map> current : maps) {
5730  if (!current.is_null() && *current == map) return true;
5731  }
5732  return false;
5733 }
5734 
5735 Map Map::FindElementsKindTransitionedMap(Isolate* isolate,
5736  MapHandles const& candidates) {
5737  DisallowHeapAllocation no_allocation;
5738  DisallowDeoptimization no_deoptimization(isolate);
5739 
5740  if (is_prototype_map()) return Map();
5741 
5742  ElementsKind kind = elements_kind();
5743  bool packed = IsFastPackedElementsKind(kind);
5744 
5745  Map transition;
5746  if (IsTransitionableFastElementsKind(kind)) {
5747  // Check the state of the root map.
5748  Map root_map = FindRootMap(isolate);
5749  if (!EquivalentToForElementsKindTransition(root_map)) return Map();
5750  root_map = root_map->LookupElementsTransitionMap(isolate, kind);
5751  DCHECK(!root_map.is_null());
5752  // Starting from the next existing elements kind transition try to
5753  // replay the property transitions that does not involve instance rewriting
5754  // (ElementsTransitionAndStoreStub does not support that).
5755  for (root_map = root_map->ElementsTransitionMap();
5756  !root_map.is_null() && root_map->has_fast_elements();
5757  root_map = root_map->ElementsTransitionMap()) {
5758  Map current = root_map->TryReplayPropertyTransitions(isolate, *this);
5759  if (current.is_null()) continue;
5760  if (InstancesNeedRewriting(current)) continue;
5761 
5762  if (ContainsMap(candidates, current) &&
5763  (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
5764  transition = current;
5765  packed = packed && IsFastPackedElementsKind(current->elements_kind());
5766  }
5767  }
5768  }
5769  return transition;
5770 }
5771 
5772 static Map FindClosestElementsTransition(Isolate* isolate, Map map,
5773  ElementsKind to_kind) {
5774  // Ensure we are requested to search elements kind transition "near the root".
5775  DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
5776  map->NumberOfOwnDescriptors());
5777  Map current_map = map;
5778 
5779  ElementsKind kind = map->elements_kind();
5780  while (kind != to_kind) {
5781  Map next_map = current_map->ElementsTransitionMap();
5782  if (next_map.is_null()) return current_map;
5783  kind = next_map->elements_kind();
5784  current_map = next_map;
5785  }
5786 
5787  DCHECK_EQ(to_kind, current_map->elements_kind());
5788  return current_map;
5789 }
5790 
5791 Map Map::LookupElementsTransitionMap(Isolate* isolate, ElementsKind to_kind) {
5792  Map to_map = FindClosestElementsTransition(isolate, *this, to_kind);
5793  if (to_map->elements_kind() == to_kind) return to_map;
5794  return Map();
5795 }
5796 
5797 bool Map::IsMapInArrayPrototypeChain(Isolate* isolate) const {
5798  if (isolate->initial_array_prototype()->map() == *this) {
5799  return true;
5800  }
5801 
5802  if (isolate->initial_object_prototype()->map() == *this) {
5803  return true;
5804  }
5805 
5806  return false;
5807 }
5808 
5809 static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
5810  Handle<Map> map,
5811  ElementsKind to_kind) {
5812  DCHECK(IsTransitionElementsKind(map->elements_kind()));
5813 
5814  Handle<Map> current_map = map;
5815 
5816  ElementsKind kind = map->elements_kind();
5817  TransitionFlag flag;
5818  if (map->is_prototype_map()) {
5819  flag = OMIT_TRANSITION;
5820  } else {
5821  flag = INSERT_TRANSITION;
5822  if (IsFastElementsKind(kind)) {
5823  while (kind != to_kind && !IsTerminalElementsKind(kind)) {
5824  kind = GetNextTransitionElementsKind(kind);
5825  current_map = Map::CopyAsElementsKind(isolate, current_map, kind, flag);
5826  }
5827  }
5828  }
5829 
5830  // In case we are exiting the fast elements kind system, just add the map in
5831  // the end.
5832  if (kind != to_kind) {
5833  current_map = Map::CopyAsElementsKind(isolate, current_map, to_kind, flag);
5834  }
5835 
5836  DCHECK(current_map->elements_kind() == to_kind);
5837  return current_map;
5838 }
5839 
5840 Handle<Map> Map::TransitionElementsTo(Isolate* isolate, Handle<Map> map,
5841  ElementsKind to_kind) {
5842  ElementsKind from_kind = map->elements_kind();
5843  if (from_kind == to_kind) return map;
5844 
5845  Context native_context = isolate->context()->native_context();
5846  if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
5847  if (*map == native_context->fast_aliased_arguments_map()) {
5848  DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5849  return handle(native_context->slow_aliased_arguments_map(), isolate);
5850  }
5851  } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
5852  if (*map == native_context->slow_aliased_arguments_map()) {
5853  DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5854  return handle(native_context->fast_aliased_arguments_map(), isolate);
5855  }
5856  } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
5857  // Reuse map transitions for JSArrays.
5858  DisallowHeapAllocation no_gc;
5859  if (native_context->GetInitialJSArrayMap(from_kind) == *map) {
5860  Object* maybe_transitioned_map =
5861  native_context->get(Context::ArrayMapIndex(to_kind));
5862  if (maybe_transitioned_map->IsMap()) {
5863  return handle(Map::cast(maybe_transitioned_map), isolate);
5864  }
5865  }
5866  }
5867 
5868  DCHECK(!map->IsUndefined(isolate));
5869  // Check if we can go back in the elements kind transition chain.
5870  if (IsHoleyElementsKind(from_kind) &&
5871  to_kind == GetPackedElementsKind(from_kind) &&
5872  map->GetBackPointer()->IsMap() &&
5873  Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
5874  return handle(Map::cast(map->GetBackPointer()), isolate);
5875  }
5876 
5877  bool allow_store_transition = IsTransitionElementsKind(from_kind);
5878  // Only store fast element maps in ascending generality.
5879  if (IsFastElementsKind(to_kind)) {
5880  allow_store_transition =
5881  allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
5882  IsMoreGeneralElementsKindTransition(from_kind, to_kind);
5883  }
5884 
5885  if (!allow_store_transition) {
5886  return Map::CopyAsElementsKind(isolate, map, to_kind, OMIT_TRANSITION);
5887  }
5888 
5889  return Map::ReconfigureElementsKind(isolate, map, to_kind);
5890 }
5891 
5892 
5893 // static
5894 Handle<Map> Map::AsElementsKind(Isolate* isolate, Handle<Map> map,
5895  ElementsKind kind) {
5896  Handle<Map> closest_map(FindClosestElementsTransition(isolate, *map, kind),
5897  isolate);
5898 
5899  if (closest_map->elements_kind() == kind) {
5900  return closest_map;
5901  }
5902 
5903  return AddMissingElementsTransitions(isolate, closest_map, kind);
5904 }
5905 
5906 
5907 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
5908  ElementsKind to_kind) {
5909  Handle<Map> map(object->map(), object->GetIsolate());
5910  return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind);
5911 }
5912 
5913 
5914 void JSProxy::Revoke(Handle<JSProxy> proxy) {
5915  Isolate* isolate = proxy->GetIsolate();
5916  // ES#sec-proxy-revocation-functions
5917  if (!proxy->IsRevoked()) {
5918  // 5. Set p.[[ProxyTarget]] to null.
5919  proxy->set_target(ReadOnlyRoots(isolate).null_value());
5920  // 6. Set p.[[ProxyHandler]] to null.
5921  proxy->set_handler(ReadOnlyRoots(isolate).null_value());
5922  }
5923  DCHECK(proxy->IsRevoked());
5924 }
5925 
5926 // static
5927 Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) {
5928  Isolate* isolate = proxy->GetIsolate();
5929  Handle<JSReceiver> object = Handle<JSReceiver>::cast(proxy);
5930  for (int i = 0; i < JSProxy::kMaxIterationLimit; i++) {
5931  Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
5932  if (proxy->IsRevoked()) {
5933  isolate->Throw(*isolate->factory()->NewTypeError(
5934  MessageTemplate::kProxyRevoked,
5935  isolate->factory()->NewStringFromAsciiChecked("IsArray")));
5936  return Nothing<bool>();
5937  }
5938  object = handle(JSReceiver::cast(proxy->target()), isolate);
5939  if (object->IsJSArray()) return Just(true);
5940  if (!object->IsJSProxy()) return Just(false);
5941  }
5942 
5943  // Too deep recursion, throw a RangeError.
5944  isolate->StackOverflow();
5945  return Nothing<bool>();
5946 }
5947 
5948 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
5949  Handle<Name> name) {
5950  DCHECK(!name->IsPrivate());
5951  STACK_CHECK(isolate, Nothing<bool>());
5952  // 1. (Assert)
5953  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
5954  Handle<Object> handler(proxy->handler(), isolate);
5955  // 3. If handler is null, throw a TypeError exception.
5956  // 4. Assert: Type(handler) is Object.
5957  if (proxy->IsRevoked()) {
5958  isolate->Throw(*isolate->factory()->NewTypeError(
5959  MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
5960  return Nothing<bool>();
5961  }
5962  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
5963  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
5964  // 6. Let trap be ? GetMethod(handler, "has").
5965  Handle<Object> trap;
5966  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5967  isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
5968  isolate->factory()->has_string()),
5969  Nothing<bool>());
5970  // 7. If trap is undefined, then
5971  if (trap->IsUndefined(isolate)) {
5972  // 7a. Return target.[[HasProperty]](P).
5973  return JSReceiver::HasProperty(target, name);
5974  }
5975  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)).
5976  Handle<Object> trap_result_obj;
5977  Handle<Object> args[] = {target, name};
5978  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5979  isolate, trap_result_obj,
5980  Execution::Call(isolate, trap, handler, arraysize(args), args),
5981  Nothing<bool>());
5982  bool boolean_trap_result = trap_result_obj->BooleanValue(isolate);
5983  // 9. If booleanTrapResult is false, then:
5984  if (!boolean_trap_result) {
5985  MAYBE_RETURN(JSProxy::CheckHasTrap(isolate, name, target), Nothing<bool>());
5986  }
5987  // 10. Return booleanTrapResult.
5988  return Just(boolean_trap_result);
5989 }
5990 
5991 Maybe<bool> JSProxy::CheckHasTrap(Isolate* isolate, Handle<Name> name,
5992  Handle<JSReceiver> target) {
5993  // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
5994  PropertyDescriptor target_desc;
5995  Maybe<bool> target_found =
5996  JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
5997  MAYBE_RETURN(target_found, Nothing<bool>());
5998  // 9b. If targetDesc is not undefined, then:
5999  if (target_found.FromJust()) {
6000  // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
6001  // exception.
6002  if (!target_desc.configurable()) {
6003  isolate->Throw(*isolate->factory()->NewTypeError(
6004  MessageTemplate::kProxyHasNonConfigurable, name));
6005  return Nothing<bool>();
6006  }
6007  // 9b ii. Let extensibleTarget be ? IsExtensible(target).
6008  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
6009  MAYBE_RETURN(extensible_target, Nothing<bool>());
6010  // 9b iii. If extensibleTarget is false, throw a TypeError exception.
6011  if (!extensible_target.FromJust()) {
6012  isolate->Throw(*isolate->factory()->NewTypeError(
6013  MessageTemplate::kProxyHasNonExtensible, name));
6014  return Nothing<bool>();
6015  }
6016  }
6017  return Just(true);
6018 }
6019 
6020 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
6021  Handle<Object> value, Handle<Object> receiver,
6022  LanguageMode language_mode) {
6023  DCHECK(!name->IsPrivate());
6024  Isolate* isolate = proxy->GetIsolate();
6025  STACK_CHECK(isolate, Nothing<bool>());
6026  Factory* factory = isolate->factory();
6027  Handle<String> trap_name = factory->set_string();
6028  ShouldThrow should_throw =
6029  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
6030 
6031  if (proxy->IsRevoked()) {
6032  isolate->Throw(
6033  *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
6034  return Nothing<bool>();
6035  }
6036  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
6037  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
6038 
6039  Handle<Object> trap;
6040  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6041  isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
6042  if (trap->IsUndefined(isolate)) {
6043  LookupIterator it =
6044  LookupIterator::PropertyOrElement(isolate, receiver, name, target);
6045  return Object::SetSuperProperty(&it, value, language_mode,
6046  StoreOrigin::kMaybeKeyed);
6047  }
6048 
6049  Handle<Object> trap_result;
6050  Handle<Object> args[] = {target, name, value, receiver};
6051  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6052  isolate, trap_result,
6053  Execution::Call(isolate, trap, handler, arraysize(args), args),
6054  Nothing<bool>());
6055  if (!trap_result->BooleanValue(isolate)) {
6056  RETURN_FAILURE(isolate, should_throw,
6057  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
6058  trap_name, name));
6059  }
6060 
6061  MaybeHandle<Object> result =
6062  JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet);
6063 
6064  if (result.is_null()) {
6065  return Nothing<bool>();
6066  }
6067  return Just(true);
6068 }
6069 
6070 
6071 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
6072  Handle<Name> name,
6073  LanguageMode language_mode) {
6074  DCHECK(!name->IsPrivate());
6075  ShouldThrow should_throw =
6076  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
6077  Isolate* isolate = proxy->GetIsolate();
6078  STACK_CHECK(isolate, Nothing<bool>());
6079  Factory* factory = isolate->factory();
6080  Handle<String> trap_name = factory->deleteProperty_string();
6081 
6082  if (proxy->IsRevoked()) {
6083  isolate->Throw(
6084  *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
6085  return Nothing<bool>();
6086  }
6087  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
6088  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
6089 
6090  Handle<Object> trap;
6091  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6092  isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
6093  if (trap->IsUndefined(isolate)) {
6094  return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
6095  }
6096 
6097  Handle<Object> trap_result;
6098  Handle<Object> args[] = {target, name};
6099  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6100  isolate, trap_result,
6101  Execution::Call(isolate, trap, handler, arraysize(args), args),
6102  Nothing<bool>());
6103  if (!trap_result->BooleanValue(isolate)) {
6104  RETURN_FAILURE(isolate, should_throw,
6105  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
6106  trap_name, name));
6107  }
6108 
6109  // Enforce the invariant.
6110  PropertyDescriptor target_desc;
6111  Maybe<bool> owned =
6112  JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
6113  MAYBE_RETURN(owned, Nothing<bool>());
6114  if (owned.FromJust() && !target_desc.configurable()) {
6115  isolate->Throw(*factory->NewTypeError(
6116  MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
6117  return Nothing<bool>();
6118  }
6119  return Just(true);
6120 }
6121 
6122 
6123 // static
6124 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
6125  Handle<Object> handler) {
6126  if (!target->IsJSReceiver()) {
6127  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
6128  JSProxy);
6129  }
6130  if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
6131  THROW_NEW_ERROR(isolate,
6132  NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
6133  JSProxy);
6134  }
6135  if (!handler->IsJSReceiver()) {
6136  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
6137  JSProxy);
6138  }
6139  if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
6140  THROW_NEW_ERROR(isolate,
6141  NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
6142  JSProxy);
6143  }
6144  return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
6145  Handle<JSReceiver>::cast(handler));
6146 }
6147 
6148 
6149 // static
6150 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
6151  DCHECK(proxy->map()->is_constructor());
6152  if (proxy->IsRevoked()) {
6153  THROW_NEW_ERROR(proxy->GetIsolate(),
6154  NewTypeError(MessageTemplate::kProxyRevoked), Context);
6155  }
6156  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()),
6157  proxy->GetIsolate());
6158  return JSReceiver::GetFunctionRealm(target);
6159 }
6160 
6161 
6162 // static
6163 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
6164  Handle<JSBoundFunction> function) {
6165  DCHECK(function->map()->is_constructor());
6166  return JSReceiver::GetFunctionRealm(
6167  handle(function->bound_target_function(), function->GetIsolate()));
6168 }
6169 
6170 // static
6171 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
6172  Handle<JSBoundFunction> function) {
6173  Handle<String> prefix = isolate->factory()->bound__string();
6174  Handle<String> target_name = prefix;
6175  Factory* factory = isolate->factory();
6176  // Concatenate the "bound " up to the last non-bound target.
6177  while (function->bound_target_function()->IsJSBoundFunction()) {
6178  ASSIGN_RETURN_ON_EXCEPTION(isolate, target_name,
6179  factory->NewConsString(prefix, target_name),
6180  String);
6181  function = handle(JSBoundFunction::cast(function->bound_target_function()),
6182  isolate);
6183  }
6184  if (function->bound_target_function()->IsJSFunction()) {
6185  Handle<JSFunction> target(
6186  JSFunction::cast(function->bound_target_function()), isolate);
6187  Handle<Object> name = JSFunction::GetName(isolate, target);
6188  if (!name->IsString()) return target_name;
6189  return factory->NewConsString(target_name, Handle<String>::cast(name));
6190  }
6191  // This will omit the proper target name for bound JSProxies.
6192  return target_name;
6193 }
6194 
6195 // static
6196 Maybe<int> JSBoundFunction::GetLength(Isolate* isolate,
6197  Handle<JSBoundFunction> function) {
6198  int nof_bound_arguments = function->bound_arguments()->length();
6199  while (function->bound_target_function()->IsJSBoundFunction()) {
6200  function = handle(JSBoundFunction::cast(function->bound_target_function()),
6201  isolate);
6202  // Make sure we never overflow {nof_bound_arguments}, the number of
6203  // arguments of a function is strictly limited by the max length of an
6204  // JSAarray, Smi::kMaxValue is thus a reasonably good overestimate.
6205  int length = function->bound_arguments()->length();
6206  if (V8_LIKELY(Smi::kMaxValue - nof_bound_arguments > length)) {
6207  nof_bound_arguments += length;
6208  } else {
6209  nof_bound_arguments = Smi::kMaxValue;
6210  }
6211  }
6212  // All non JSFunction targets get a direct property and don't use this
6213  // accessor.
6214  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
6215  isolate);
6216  Maybe<int> target_length = JSFunction::GetLength(isolate, target);
6217  if (target_length.IsNothing()) return target_length;
6218 
6219  int length = Max(0, target_length.FromJust() - nof_bound_arguments);
6220  return Just(length);
6221 }
6222 
6223 // static
6224 Handle<Object> JSFunction::GetName(Isolate* isolate,
6225  Handle<JSFunction> function) {
6226  if (function->shared()->name_should_print_as_anonymous()) {
6227  return isolate->factory()->anonymous_string();
6228  }
6229  return handle(function->shared()->Name(), isolate);
6230 }
6231 
6232 // static
6233 Maybe<int> JSFunction::GetLength(Isolate* isolate,
6234  Handle<JSFunction> function) {
6235  int length = 0;
6236  if (function->shared()->is_compiled()) {
6237  length = function->shared()->GetLength();
6238  } else {
6239  // If the function isn't compiled yet, the length is not computed
6240  // correctly yet. Compile it now and return the right length.
6241  if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
6242  length = function->shared()->GetLength();
6243  }
6244  if (isolate->has_pending_exception()) return Nothing<int>();
6245  }
6246  DCHECK_GE(length, 0);
6247  return Just(length);
6248 }
6249 
6250 // static
6251 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
6252  DCHECK(function->map()->is_constructor());
6253  return handle(function->context()->native_context(), function->GetIsolate());
6254 }
6255 
6256 
6257 // static
6258 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
6259  DCHECK(object->map()->is_constructor());
6260  DCHECK(!object->IsJSFunction());
6261  return object->GetCreationContext();
6262 }
6263 
6264 
6265 // static
6266 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
6267  if (receiver->IsJSProxy()) {
6268  return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
6269  }
6270 
6271  if (receiver->IsJSFunction()) {
6272  return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
6273  }
6274 
6275  if (receiver->IsJSBoundFunction()) {
6276  return JSBoundFunction::GetFunctionRealm(
6277  Handle<JSBoundFunction>::cast(receiver));
6278  }
6279 
6280  return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
6281 }
6282 
6283 
6284 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
6285  PropertyDescriptor desc;
6286  Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
6287  it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
6288  MAYBE_RETURN(found, Nothing<PropertyAttributes>());
6289  if (!found.FromJust()) return Just(ABSENT);
6290  return Just(desc.ToAttributes());
6291 }
6292 
6293 
6294 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
6295  DCHECK(object->map()->GetInObjectProperties() ==
6296  map->GetInObjectProperties());
6297  ElementsKind obj_kind = object->map()->elements_kind();
6298  ElementsKind map_kind = map->elements_kind();
6299  if (map_kind != obj_kind) {
6300  ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
6301  if (IsDictionaryElementsKind(obj_kind)) {
6302  to_kind = obj_kind;
6303  }
6304  if (IsDictionaryElementsKind(to_kind)) {
6305  NormalizeElements(object);
6306  } else {
6307  TransitionElementsKind(object, to_kind);
6308  }
6309  map = Map::ReconfigureElementsKind(object->GetIsolate(), map, to_kind);
6310  }
6311  int number_of_fields = map->NumberOfFields();
6312  int inobject = map->GetInObjectProperties();
6313  int unused = map->UnusedPropertyFields();
6314  int total_size = number_of_fields + unused;
6315  int external = total_size - inobject;
6316  // Allocate mutable double boxes if necessary. It is always necessary if we
6317  // have external properties, but is also necessary if we only have inobject
6318  // properties but don't unbox double fields.
6319  if (!FLAG_unbox_double_fields || external > 0) {
6320  Isolate* isolate = object->GetIsolate();
6321 
6322  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
6323  Handle<FixedArray> storage;
6324  if (!FLAG_unbox_double_fields) {
6325  storage = isolate->factory()->NewFixedArray(inobject);
6326  }
6327 
6328  Handle<PropertyArray> array =
6329  isolate->factory()->NewPropertyArray(external);
6330 
6331  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
6332  PropertyDetails details = descriptors->GetDetails(i);
6333  Representation representation = details.representation();
6334  if (!representation.IsDouble()) continue;
6335  FieldIndex index = FieldIndex::ForDescriptor(*map, i);
6336  if (map->IsUnboxedDoubleField(index)) continue;
6337  auto box = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
6338  if (index.is_inobject()) {
6339  storage->set(index.property_index(), *box);
6340  } else {
6341  array->set(index.outobject_array_index(), *box);
6342  }
6343  }
6344 
6345  object->SetProperties(*array);
6346 
6347  if (!FLAG_unbox_double_fields) {
6348  for (int i = 0; i < inobject; i++) {
6349  FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
6350  Object* value = storage->get(i);
6351  object->RawFastPropertyAtPut(index, value);
6352  }
6353  }
6354  }
6355  object->synchronized_set_map(*map);
6356 }
6357 
6358 
6359 void JSObject::MigrateInstance(Handle<JSObject> object) {
6360  Handle<Map> original_map(object->map(), object->GetIsolate());
6361  Handle<Map> map = Map::Update(object->GetIsolate(), original_map);
6362  map->set_is_migration_target(true);
6363  MigrateToMap(object, map);
6364  if (FLAG_trace_migration) {
6365  object->PrintInstanceMigration(stdout, *original_map, *map);
6366  }
6367 #if VERIFY_HEAP
6368  if (FLAG_verify_heap) {
6369  object->JSObjectVerify(object->GetIsolate());
6370  }
6371 #endif
6372 }
6373 
6374 
6375 // static
6376 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
6377  Isolate* isolate = object->GetIsolate();
6378  DisallowDeoptimization no_deoptimization(isolate);
6379  Handle<Map> original_map(object->map(), isolate);
6380  Handle<Map> new_map;
6381  if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) {
6382  return false;
6383  }
6384  JSObject::MigrateToMap(object, new_map);
6385  if (FLAG_trace_migration && *original_map != object->map()) {
6386  object->PrintInstanceMigration(stdout, *original_map, object->map());
6387  }
6388 #if VERIFY_HEAP
6389  if (FLAG_verify_heap) {
6390  object->JSObjectVerify(isolate);
6391  }
6392 #endif
6393  return true;
6394 }
6395 
6396 void JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object,
6397  Handle<Name> name, Handle<Object> value,
6398  PropertyAttributes attributes) {
6399  LookupIterator it(isolate, object, name, object,
6400  LookupIterator::OWN_SKIP_INTERCEPTOR);
6401  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
6402 #ifdef DEBUG
6403  uint32_t index;
6404  DCHECK(!object->IsJSProxy());
6405  DCHECK(!name->AsArrayIndex(&index));
6406  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
6407  DCHECK(maybe.IsJust());
6408  DCHECK(!it.IsFound());
6409  DCHECK(object->map()->is_extensible() || name->IsPrivate());
6410 #endif
6411  CHECK(AddDataProperty(&it, value, attributes, kThrowOnError,
6412  StoreOrigin::kNamed)
6413  .IsJust());
6414 }
6415 
6416 
6417 // Reconfigures a property to a data property with attributes, even if it is not
6418 // reconfigurable.
6419 // Requires a LookupIterator that does not look at the prototype chain beyond
6420 // hidden prototypes.
6421 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
6422  LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
6423  AccessorInfoHandling handling) {
6424  MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(it, value, attributes,
6425  kThrowOnError, handling));
6426  return value;
6427 }
6428 
6429 
6430 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
6431  LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
6432  ShouldThrow should_throw, AccessorInfoHandling handling) {
6433  it->UpdateProtector();
6434  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
6435 
6436  for (; it->IsFound(); it->Next()) {
6437  switch (it->state()) {
6438  case LookupIterator::JSPROXY:
6439  case LookupIterator::NOT_FOUND:
6440  case LookupIterator::TRANSITION:
6441  UNREACHABLE();
6442 
6443  case LookupIterator::ACCESS_CHECK:
6444  if (!it->HasAccess()) {
6445  it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
6446  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
6447  return Just(true);
6448  }
6449  break;
6450 
6451  // If there's an interceptor, try to store the property with the
6452  // interceptor.
6453  // In case of success, the attributes will have been reset to the default
6454  // attributes of the interceptor, rather than the incoming attributes.
6455  //
6456  // TODO(verwaest): JSProxy afterwards verify the attributes that the
6457  // JSProxy claims it has, and verifies that they are compatible. If not,
6458  // they throw. Here we should do the same.
6459  case LookupIterator::INTERCEPTOR:
6460  if (handling == DONT_FORCE_FIELD) {
6461  Maybe<bool> result =
6462  JSObject::SetPropertyWithInterceptor(it, should_throw, value);
6463  if (result.IsNothing() || result.FromJust()) return result;
6464  }
6465  break;
6466 
6467  case LookupIterator::ACCESSOR: {
6468  Handle<Object> accessors = it->GetAccessors();
6469 
6470  // Special handling for AccessorInfo, which behaves like a data
6471  // property.
6472  if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
6473  PropertyAttributes current_attributes = it->property_attributes();
6474  // Ensure the context isn't changed after calling into accessors.
6475  AssertNoContextChange ncc(it->isolate());
6476 
6477  // Update the attributes before calling the setter. The setter may
6478  // later change the shape of the property.
6479  if (current_attributes != attributes) {
6480  it->TransitionToAccessorPair(accessors, attributes);
6481  }
6482 
6483  return JSObject::SetPropertyWithAccessor(it, value, should_throw);
6484  }
6485 
6486  it->ReconfigureDataProperty(value, attributes);
6487  return Just(true);
6488  }
6489  case LookupIterator::INTEGER_INDEXED_EXOTIC:
6490  return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
6491  should_throw);
6492 
6493  case LookupIterator::DATA: {
6494  // Regular property update if the attributes match.
6495  if (it->property_attributes() == attributes) {
6496  return SetDataProperty(it, value);
6497  }
6498 
6499  // Special case: properties of typed arrays cannot be reconfigured to
6500  // non-writable nor to non-enumerable.
6501  if (it->IsElement() && object->HasFixedTypedArrayElements()) {
6502  return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
6503  value, should_throw);
6504  }
6505 
6506  // Reconfigure the data property if the attributes mismatch.
6507  it->ReconfigureDataProperty(value, attributes);
6508 
6509  return Just(true);
6510  }
6511  }
6512  }
6513 
6514  return AddDataProperty(it, value, attributes, should_throw,
6515  StoreOrigin::kNamed);
6516 }
6517 
6518 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
6519  Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
6520  PropertyAttributes attributes) {
6521  DCHECK(!value->IsTheHole());
6522  LookupIterator it(object, name, object, LookupIterator::OWN);
6523  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6524 }
6525 
6526 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
6527  Handle<JSObject> object, uint32_t index, Handle<Object> value,
6528  PropertyAttributes attributes) {
6529  Isolate* isolate = object->GetIsolate();
6530  LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
6531  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6532 }
6533 
6534 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
6535  Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
6536  PropertyAttributes attributes) {
6537  Isolate* isolate = object->GetIsolate();
6538  LookupIterator it = LookupIterator::PropertyOrElement(
6539  isolate, object, name, object, LookupIterator::OWN);
6540  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
6541 }
6542 
6543 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
6544  LookupIterator* it) {
6545  return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
6546 }
6547 
6548 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
6549  LookupIterator* it) {
6550  for (; it->IsFound(); it->Next()) {
6551  switch (it->state()) {
6552  case LookupIterator::NOT_FOUND:
6553  case LookupIterator::TRANSITION:
6554  UNREACHABLE();
6555  case LookupIterator::JSPROXY:
6556  return JSProxy::GetPropertyAttributes(it);
6557  case LookupIterator::INTERCEPTOR: {
6558  Maybe<PropertyAttributes> result =
6559  JSObject::GetPropertyAttributesWithInterceptor(it);
6560  if (result.IsNothing()) return result;
6561  if (result.FromJust() != ABSENT) return result;
6562  break;
6563  }
6564  case LookupIterator::ACCESS_CHECK:
6565  if (it->HasAccess()) break;
6566  return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
6567  case LookupIterator::INTEGER_INDEXED_EXOTIC:
6568  return Just(ABSENT);
6569  case LookupIterator::ACCESSOR:
6570  if (it->GetHolder<Object>()->IsJSModuleNamespace()) {
6571  return JSModuleNamespace::GetPropertyAttributes(it);
6572  } else {
6573  return Just(it->property_attributes());
6574  }
6575  case LookupIterator::DATA:
6576  return Just(it->property_attributes());
6577  }
6578  }
6579  return Just(ABSENT);
6580 }
6581 
6582 
6583 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
6584  Handle<WeakFixedArray> array(
6585  isolate->factory()->NewWeakFixedArray(kEntries, TENURED));
6586  return Handle<NormalizedMapCache>::cast(array);
6587 }
6588 
6589 
6590 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
6591  PropertyNormalizationMode mode) {
6592  DisallowHeapAllocation no_gc;
6593  MaybeObject value = WeakFixedArray::Get(GetIndex(fast_map));
6594  HeapObject* heap_object;
6595  if (!value->GetHeapObjectIfWeak(&heap_object)) {
6596  return MaybeHandle<Map>();
6597  }
6598 
6599  Map normalized_map = Map::cast(heap_object);
6600  if (!normalized_map->EquivalentToForNormalization(*fast_map, mode)) {
6601  return MaybeHandle<Map>();
6602  }
6603  return handle(normalized_map, GetIsolate());
6604 }
6605 
6606 void NormalizedMapCache::Set(Handle<Map> fast_map, Handle<Map> normalized_map) {
6607  DisallowHeapAllocation no_gc;
6608  DCHECK(normalized_map->is_dictionary_map());
6609  WeakFixedArray::Set(GetIndex(fast_map),
6610  HeapObjectReference::Weak(*normalized_map));
6611 }
6612 
6613 void JSObject::NormalizeProperties(Handle<JSObject> object,
6614  PropertyNormalizationMode mode,
6615  int expected_additional_properties,
6616  const char* reason) {
6617  if (!object->HasFastProperties()) return;
6618 
6619  Handle<Map> map(object->map(), object->GetIsolate());
6620  Handle<Map> new_map = Map::Normalize(object->GetIsolate(), map, mode, reason);
6621 
6622  MigrateToMap(object, new_map, expected_additional_properties);
6623 }
6624 
6625 
6626 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
6627  int unused_property_fields,
6628  const char* reason) {
6629  if (object->HasFastProperties()) return;
6630  DCHECK(!object->IsJSGlobalObject());
6631  Isolate* isolate = object->GetIsolate();
6632  Factory* factory = isolate->factory();
6633  Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
6634 
6635  // Make sure we preserve dictionary representation if there are too many
6636  // descriptors.
6637  int number_of_elements = dictionary->NumberOfElements();
6638  if (number_of_elements > kMaxNumberOfDescriptors) return;
6639 
6640  Handle<FixedArray> iteration_order =
6641  NameDictionary::IterationIndices(isolate, dictionary);
6642 
6643  int instance_descriptor_length = iteration_order->length();
6644  int number_of_fields = 0;
6645 
6646  // Compute the length of the instance descriptor.
6647  ReadOnlyRoots roots(isolate);
6648  for (int i = 0; i < instance_descriptor_length; i++) {
6649  int index = Smi::ToInt(iteration_order->get(i));
6650  DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(index)));
6651 
6652  PropertyKind kind = dictionary->DetailsAt(index).kind();
6653  if (kind == kData) {
6654  if (FLAG_track_constant_fields) {
6655  number_of_fields += 1;
6656  } else {
6657  Object* value = dictionary->ValueAt(index);
6658  if (!value->IsJSFunction()) {
6659  number_of_fields += 1;
6660  }
6661  }
6662  }
6663  }
6664 
6665  Handle<Map> old_map(object->map(), isolate);
6666 
6667  int inobject_props = old_map->GetInObjectProperties();
6668 
6669  // Allocate new map.
6670  Handle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map);
6671  if (new_map->has_named_interceptor() || new_map->is_access_check_needed()) {
6672  // Force certain slow paths when API interceptors are used, or if an access
6673  // check is required.
6674  new_map->set_may_have_interesting_symbols(true);
6675  }
6676  new_map->set_is_dictionary_map(false);
6677 
6678  NotifyMapChange(old_map, new_map, isolate);
6679 
6680 
6681  if (instance_descriptor_length == 0) {
6682  DisallowHeapAllocation no_gc;
6683  DCHECK_LE(unused_property_fields, inobject_props);
6684  // Transform the object.
6685  new_map->SetInObjectUnusedPropertyFields(inobject_props);
6686  object->synchronized_set_map(*new_map);
6687  object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
6688  // Check that it really works.
6689  DCHECK(object->HasFastProperties());
6690  if (FLAG_trace_maps) {
6691  LOG(isolate, MapEvent("SlowToFast", *old_map, *new_map, reason));
6692  }
6693  return;
6694  }
6695 
6696  // Allocate the instance descriptor.
6697  Handle<DescriptorArray> descriptors =
6698  DescriptorArray::Allocate(isolate, instance_descriptor_length, 0);
6699 
6700  int number_of_allocated_fields =
6701  number_of_fields + unused_property_fields - inobject_props;
6702  if (number_of_allocated_fields < 0) {
6703  // There is enough inobject space for all fields (including unused).
6704  number_of_allocated_fields = 0;
6705  unused_property_fields = inobject_props - number_of_fields;
6706  }
6707 
6708  // Allocate the property array for the fields.
6709  Handle<PropertyArray> fields =
6710  factory->NewPropertyArray(number_of_allocated_fields);
6711 
6712  bool is_transitionable_elements_kind =
6713  IsTransitionableFastElementsKind(old_map->elements_kind());
6714 
6715  // Fill in the instance descriptor and the fields.
6716  int current_offset = 0;
6717  for (int i = 0; i < instance_descriptor_length; i++) {
6718  int index = Smi::ToInt(iteration_order->get(i));
6719  Name k = dictionary->NameAt(index);
6720  // Dictionary keys are internalized upon insertion.
6721  // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
6722  CHECK(k->IsUniqueName());
6723  Handle<Name> key(k, isolate);
6724 
6725  // Properly mark the {new_map} if the {key} is an "interesting symbol".
6726  if (key->IsInterestingSymbol()) {
6727  new_map->set_may_have_interesting_symbols(true);
6728  }
6729 
6730  Object* value = dictionary->ValueAt(index);
6731 
6732  PropertyDetails details = dictionary->DetailsAt(index);
6733  DCHECK_EQ(kField, details.location());
6734  DCHECK_EQ(PropertyConstness::kMutable, details.constness());
6735 
6736  Descriptor d;
6737  if (details.kind() == kData) {
6738  if (!FLAG_track_constant_fields && value->IsJSFunction()) {
6739  d = Descriptor::DataConstant(key, handle(value, isolate),
6740  details.attributes());
6741  } else {
6742  // Ensure that we make constant field only when elements kind is not
6743  // transitionable.
6744  PropertyConstness constness =
6745  FLAG_track_constant_fields && !is_transitionable_elements_kind
6746  ? PropertyConstness::kConst
6747  : PropertyConstness::kMutable;
6748  d = Descriptor::DataField(
6749  key, current_offset, details.attributes(), constness,
6750  // TODO(verwaest): value->OptimalRepresentation();
6751  Representation::Tagged(),
6752  MaybeObjectHandle(FieldType::Any(isolate)));
6753  }
6754  } else {
6755  DCHECK_EQ(kAccessor, details.kind());
6756  d = Descriptor::AccessorConstant(key, handle(value, isolate),
6757  details.attributes());
6758  }
6759  details = d.GetDetails();
6760  if (details.location() == kField) {
6761  if (current_offset < inobject_props) {
6762  object->InObjectPropertyAtPut(current_offset, value,
6763  UPDATE_WRITE_BARRIER);
6764  } else {
6765  int offset = current_offset - inobject_props;
6766  fields->set(offset, value);
6767  }
6768  current_offset += details.field_width_in_words();
6769  }
6770  descriptors->Set(i, &d);
6771  }
6772  DCHECK(current_offset == number_of_fields);
6773 
6774  descriptors->Sort();
6775 
6776  Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
6777  isolate, new_map, descriptors, descriptors->number_of_descriptors());
6778 
6779  DisallowHeapAllocation no_gc;
6780  new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
6781  if (number_of_allocated_fields == 0) {
6782  new_map->SetInObjectUnusedPropertyFields(unused_property_fields);
6783  } else {
6784  new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields);
6785  }
6786 
6787  if (FLAG_trace_maps) {
6788  LOG(isolate, MapEvent("SlowToFast", *old_map, *new_map, reason));
6789  }
6790  // Transform the object.
6791  object->synchronized_set_map(*new_map);
6792 
6793  object->SetProperties(*fields);
6794  DCHECK(object->IsJSObject());
6795 
6796  // Check that it really works.
6797  DCHECK(object->HasFastProperties());
6798 }
6799 
6800 void JSObject::RequireSlowElements(NumberDictionary dictionary) {
6801  if (dictionary->requires_slow_elements()) return;
6802  dictionary->set_requires_slow_elements();
6803  if (map()->is_prototype_map()) {
6804  // If this object is a prototype (the callee will check), invalidate any
6805  // prototype chains involving it.
6806  InvalidatePrototypeChains(map());
6807  }
6808 }
6809 
6810 Handle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject> object) {
6811  DCHECK(!object->HasFixedTypedArrayElements());
6812  Isolate* isolate = object->GetIsolate();
6813  bool is_sloppy_arguments = object->HasSloppyArgumentsElements();
6814  {
6815  DisallowHeapAllocation no_gc;
6816  FixedArrayBase elements = object->elements();
6817 
6818  if (is_sloppy_arguments) {
6819  elements = SloppyArgumentsElements::cast(elements)->arguments();
6820  }
6821 
6822  if (elements->IsNumberDictionary()) {
6823  return handle(NumberDictionary::cast(elements), isolate);
6824  }
6825  }
6826 
6827  DCHECK(object->HasSmiOrObjectElements() || object->HasDoubleElements() ||
6828  object->HasFastArgumentsElements() ||
6829  object->HasFastStringWrapperElements());
6830 
6831  Handle<NumberDictionary> dictionary =
6832  object->GetElementsAccessor()->Normalize(object);
6833 
6834  // Switch to using the dictionary as the backing storage for elements.
6835  ElementsKind target_kind = is_sloppy_arguments
6836  ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
6837  : object->HasFastStringWrapperElements()
6838  ? SLOW_STRING_WRAPPER_ELEMENTS
6839  : DICTIONARY_ELEMENTS;
6840  Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
6841  // Set the new map first to satify the elements type assert in set_elements().
6842  JSObject::MigrateToMap(object, new_map);
6843 
6844  if (is_sloppy_arguments) {
6845  SloppyArgumentsElements::cast(object->elements())
6846  ->set_arguments(*dictionary);
6847  } else {
6848  object->set_elements(*dictionary);
6849  }
6850 
6851  isolate->counters()->elements_to_dictionary()->Increment();
6852 
6853 #ifdef DEBUG
6854  if (FLAG_trace_normalization) {
6855  StdoutStream os;
6856  os << "Object elements have been normalized:\n";
6857  object->Print(os);
6858  }
6859 #endif
6860 
6861  DCHECK(object->HasDictionaryElements() ||
6862  object->HasSlowArgumentsElements() ||
6863  object->HasSlowStringWrapperElements());
6864  return dictionary;
6865 }
6866 
6867 namespace {
6868 
6869 Object* SetHashAndUpdateProperties(HeapObject* properties, int hash) {
6870  DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6871  DCHECK(PropertyArray::HashField::is_valid(hash));
6872 
6873  ReadOnlyRoots roots = properties->GetReadOnlyRoots();
6874  if (properties == roots.empty_fixed_array() ||
6875  properties == roots.empty_property_array() ||
6876  properties == roots.empty_property_dictionary()) {
6877  return Smi::FromInt(hash);
6878  }
6879 
6880  if (properties->IsPropertyArray()) {
6881  PropertyArray::cast(properties)->SetHash(hash);
6882  DCHECK_LT(0, PropertyArray::cast(properties)->length());
6883  return properties;
6884  }
6885 
6886  if (properties->IsGlobalDictionary()) {
6887  GlobalDictionary::cast(properties)->SetHash(hash);
6888  return properties;
6889  }
6890 
6891  DCHECK(properties->IsNameDictionary());
6892  NameDictionary::cast(properties)->SetHash(hash);
6893  return properties;
6894 }
6895 
6896 int GetIdentityHashHelper(JSReceiver* object) {
6897  DisallowHeapAllocation no_gc;
6898  Object* properties = object->raw_properties_or_hash();
6899  if (properties->IsSmi()) {
6900  return Smi::ToInt(properties);
6901  }
6902 
6903  if (properties->IsPropertyArray()) {
6904  return PropertyArray::cast(properties)->Hash();
6905  }
6906 
6907  if (properties->IsNameDictionary()) {
6908  return NameDictionary::cast(properties)->Hash();
6909  }
6910 
6911  if (properties->IsGlobalDictionary()) {
6912  return GlobalDictionary::cast(properties)->Hash();
6913  }
6914 
6915 #ifdef DEBUG
6916  ReadOnlyRoots roots = object->GetReadOnlyRoots();
6917  DCHECK(properties == roots.empty_fixed_array() ||
6918  properties == roots.empty_property_dictionary());
6919 #endif
6920 
6921  return PropertyArray::kNoHashSentinel;
6922 }
6923 } // namespace
6924 
6925 void JSReceiver::SetIdentityHash(int hash) {
6926  DisallowHeapAllocation no_gc;
6927  DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6928  DCHECK(PropertyArray::HashField::is_valid(hash));
6929 
6930  HeapObject* existing_properties = HeapObject::cast(raw_properties_or_hash());
6931  Object* new_properties =
6932  SetHashAndUpdateProperties(existing_properties, hash);
6933  set_raw_properties_or_hash(new_properties);
6934 }
6935 
6936 void JSReceiver::SetProperties(HeapObject* properties) {
6937  DCHECK_IMPLIES(properties->IsPropertyArray() &&
6938  PropertyArray::cast(properties)->length() == 0,
6939  properties == GetReadOnlyRoots().empty_property_array());
6940  DisallowHeapAllocation no_gc;
6941  int hash = GetIdentityHashHelper(this);
6942  Object* new_properties = properties;
6943 
6944  // TODO(cbruni): Make GetIdentityHashHelper return a bool so that we
6945  // don't have to manually compare against kNoHashSentinel.
6946  if (hash != PropertyArray::kNoHashSentinel) {
6947  new_properties = SetHashAndUpdateProperties(properties, hash);
6948  }
6949 
6950  set_raw_properties_or_hash(new_properties);
6951 }
6952 
6953 Object* JSReceiver::GetIdentityHash() {
6954  DisallowHeapAllocation no_gc;
6955 
6956  int hash = GetIdentityHashHelper(this);
6957  if (hash == PropertyArray::kNoHashSentinel) {
6958  return GetReadOnlyRoots().undefined_value();
6959  }
6960 
6961  return Smi::FromInt(hash);
6962 }
6963 
6964 // static
6965 Smi JSReceiver::CreateIdentityHash(Isolate* isolate, JSReceiver* key) {
6966  DisallowHeapAllocation no_gc;
6967  int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax);
6968  DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
6969 
6970  key->SetIdentityHash(hash);
6971  return Smi::FromInt(hash);
6972 }
6973 
6974 Smi JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) {
6975  DisallowHeapAllocation no_gc;
6976 
6977  int hash = GetIdentityHashHelper(this);
6978  if (hash != PropertyArray::kNoHashSentinel) {
6979  return Smi::FromInt(hash);
6980  }
6981 
6982  return JSReceiver::CreateIdentityHash(isolate, this);
6983 }
6984 
6985 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
6986  ShouldThrow should_throw) {
6987  Isolate* isolate = it->isolate();
6988  // Make sure that the top context does not change when doing callbacks or
6989  // interceptor calls.
6990  AssertNoContextChange ncc(isolate);
6991 
6992  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
6993  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
6994  if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
6995 
6996  Handle<JSObject> holder = it->GetHolder<JSObject>();
6997  Handle<Object> receiver = it->GetReceiver();
6998  if (!receiver->IsJSReceiver()) {
6999  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
7000  Object::ConvertReceiver(isolate, receiver),
7001  Nothing<bool>());
7002  }
7003 
7004  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
7005  *holder, should_throw);
7006  Handle<Object> result;
7007  if (it->IsElement()) {
7008  result = args.CallIndexedDeleter(interceptor, it->index());
7009  } else {
7010  result = args.CallNamedDeleter(interceptor, it->name());
7011  }
7012 
7013  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7014  if (result.is_null()) return Nothing<bool>();
7015 
7016  DCHECK(result->IsBoolean());
7017  // Rebox CustomArguments::kReturnValueOffset before returning.
7018  return Just(result->IsTrue(isolate));
7019 }
7020 
7021 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
7022  int entry) {
7023  DCHECK(!object->HasFastProperties());
7024  Isolate* isolate = object->GetIsolate();
7025 
7026  if (object->IsJSGlobalObject()) {
7027  // If we have a global object, invalidate the cell and swap in a new one.
7028  Handle<GlobalDictionary> dictionary(
7029  JSGlobalObject::cast(*object)->global_dictionary(), isolate);
7030  DCHECK_NE(GlobalDictionary::kNotFound, entry);
7031 
7032  auto cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
7033  cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
7034  cell->set_property_details(
7035  PropertyDetails::Empty(PropertyCellType::kUninitialized));
7036  } else {
7037  Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
7038  DCHECK_NE(NameDictionary::kNotFound, entry);
7039 
7040  dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
7041  object->SetProperties(*dictionary);
7042  }
7043  if (object->map()->is_prototype_map()) {
7044  // Invalidate prototype validity cell as this may invalidate transitioning
7045  // store IC handlers.
7046  JSObject::InvalidatePrototypeChains(object->map());
7047  }
7048 }
7049 
7050 
7051 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
7052  LanguageMode language_mode) {
7053  it->UpdateProtector();
7054 
7055  Isolate* isolate = it->isolate();
7056 
7057  if (it->state() == LookupIterator::JSPROXY) {
7058  return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
7059  it->GetName(), language_mode);
7060  }
7061 
7062  if (it->GetReceiver()->IsJSProxy()) {
7063  if (it->state() != LookupIterator::NOT_FOUND) {
7064  DCHECK_EQ(LookupIterator::DATA, it->state());
7065  DCHECK(it->name()->IsPrivate());
7066  it->Delete();
7067  }
7068  return Just(true);
7069  }
7070  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
7071 
7072  for (; it->IsFound(); it->Next()) {
7073  switch (it->state()) {
7074  case LookupIterator::JSPROXY:
7075  case LookupIterator::NOT_FOUND:
7076  case LookupIterator::TRANSITION:
7077  UNREACHABLE();
7078  case LookupIterator::ACCESS_CHECK:
7079  if (it->HasAccess()) break;
7080  isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
7081  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7082  return Just(false);
7083  case LookupIterator::INTERCEPTOR: {
7084  ShouldThrow should_throw =
7085  is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
7086  Maybe<bool> result =
7087  JSObject::DeletePropertyWithInterceptor(it, should_throw);
7088  // An exception was thrown in the interceptor. Propagate.
7089  if (isolate->has_pending_exception()) return Nothing<bool>();
7090  // Delete with interceptor succeeded. Return result.
7091  // TODO(neis): In strict mode, we should probably throw if the
7092  // interceptor returns false.
7093  if (result.IsJust()) return result;
7094  break;
7095  }
7096  case LookupIterator::INTEGER_INDEXED_EXOTIC:
7097  return Just(true);
7098  case LookupIterator::DATA:
7099  case LookupIterator::ACCESSOR: {
7100  if (!it->IsConfigurable()) {
7101  // Fail if the property is not configurable.
7102  if (is_strict(language_mode)) {
7103  isolate->Throw(*isolate->factory()->NewTypeError(
7104  MessageTemplate::kStrictDeleteProperty, it->GetName(),
7105  receiver));
7106  return Nothing<bool>();
7107  }
7108  return Just(false);
7109  }
7110 
7111  it->Delete();
7112 
7113  return Just(true);
7114  }
7115  }
7116  }
7117 
7118  return Just(true);
7119 }
7120 
7121 
7122 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
7123  LanguageMode language_mode) {
7124  LookupIterator it(object->GetIsolate(), object, index, object,
7125  LookupIterator::OWN);
7126  return DeleteProperty(&it, language_mode);
7127 }
7128 
7129 
7130 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
7131  Handle<Name> name,
7132  LanguageMode language_mode) {
7133  LookupIterator it(object, name, object, LookupIterator::OWN);
7134  return DeleteProperty(&it, language_mode);
7135 }
7136 
7137 
7138 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
7139  Handle<Name> name,
7140  LanguageMode language_mode) {
7141  LookupIterator it = LookupIterator::PropertyOrElement(
7142  object->GetIsolate(), object, name, object, LookupIterator::OWN);
7143  return DeleteProperty(&it, language_mode);
7144 }
7145 
7146 // ES6 19.1.2.4
7147 // static
7148 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
7149  Handle<Object> key,
7150  Handle<Object> attributes) {
7151  // 1. If Type(O) is not Object, throw a TypeError exception.
7152  if (!object->IsJSReceiver()) {
7153  Handle<String> fun_name =
7154  isolate->factory()->InternalizeUtf8String("Object.defineProperty");
7155  THROW_NEW_ERROR_RETURN_FAILURE(
7156  isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
7157  }
7158  // 2. Let key be ToPropertyKey(P).
7159  // 3. ReturnIfAbrupt(key).
7160  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
7161  // 4. Let desc be ToPropertyDescriptor(Attributes).
7162  // 5. ReturnIfAbrupt(desc).
7163  PropertyDescriptor desc;
7164  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
7165  return ReadOnlyRoots(isolate).exception();
7166  }
7167  // 6. Let success be DefinePropertyOrThrow(O,key, desc).
7168  Maybe<bool> success = DefineOwnProperty(
7169  isolate, Handle<JSReceiver>::cast(object), key, &desc, kThrowOnError);
7170  // 7. ReturnIfAbrupt(success).
7171  MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
7172  CHECK(success.FromJust());
7173  // 8. Return O.
7174  return *object;
7175 }
7176 
7177 
7178 // ES6 19.1.2.3.1
7179 // static
7180 MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
7181  Handle<Object> object,
7182  Handle<Object> properties) {
7183  // 1. If Type(O) is not Object, throw a TypeError exception.
7184  if (!object->IsJSReceiver()) {
7185  Handle<String> fun_name =
7186  isolate->factory()->InternalizeUtf8String("Object.defineProperties");
7187  THROW_NEW_ERROR(isolate,
7188  NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
7189  Object);
7190  }
7191  // 2. Let props be ToObject(Properties).
7192  // 3. ReturnIfAbrupt(props).
7193  Handle<JSReceiver> props;
7194  ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
7195  Object::ToObject(isolate, properties), Object);
7196 
7197  // 4. Let keys be props.[[OwnPropertyKeys]]().
7198  // 5. ReturnIfAbrupt(keys).
7199  Handle<FixedArray> keys;
7200  ASSIGN_RETURN_ON_EXCEPTION(
7201  isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
7202  ALL_PROPERTIES),
7203  Object);
7204  // 6. Let descriptors be an empty List.
7205  int capacity = keys->length();
7206  std::vector<PropertyDescriptor> descriptors(capacity);
7207  size_t descriptors_index = 0;
7208  // 7. Repeat for each element nextKey of keys in List order,
7209  for (int i = 0; i < keys->length(); ++i) {
7210  Handle<Object> next_key(keys->get(i), isolate);
7211  // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
7212  // 7b. ReturnIfAbrupt(propDesc).
7213  bool success = false;
7214  LookupIterator it = LookupIterator::PropertyOrElement(
7215  isolate, props, next_key, &success, LookupIterator::OWN);
7216  DCHECK(success);
7217  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
7218  if (maybe.IsNothing()) return MaybeHandle<Object>();
7219  PropertyAttributes attrs = maybe.FromJust();
7220  // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
7221  if (attrs == ABSENT) continue;
7222  if (attrs & DONT_ENUM) continue;
7223  // 7c i. Let descObj be Get(props, nextKey).
7224  // 7c ii. ReturnIfAbrupt(descObj).
7225  Handle<Object> desc_obj;
7226  ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
7227  Object);
7228  // 7c iii. Let desc be ToPropertyDescriptor(descObj).
7229  success = PropertyDescriptor::ToPropertyDescriptor(
7230  isolate, desc_obj, &descriptors[descriptors_index]);
7231  // 7c iv. ReturnIfAbrupt(desc).
7232  if (!success) return MaybeHandle<Object>();
7233  // 7c v. Append the pair (a two element List) consisting of nextKey and
7234  // desc to the end of descriptors.
7235  descriptors[descriptors_index].set_name(next_key);
7236  descriptors_index++;
7237  }
7238  // 8. For each pair from descriptors in list order,
7239  for (size_t i = 0; i < descriptors_index; ++i) {
7240  PropertyDescriptor* desc = &descriptors[i];
7241  // 8a. Let P be the first element of pair.
7242  // 8b. Let desc be the second element of pair.
7243  // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
7244  Maybe<bool> status =
7245  DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
7246  desc->name(), desc, kThrowOnError);
7247  // 8d. ReturnIfAbrupt(status).
7248  if (status.IsNothing()) return MaybeHandle<Object>();
7249  CHECK(status.FromJust());
7250  }
7251  // 9. Return o.
7252  return object;
7253 }
7254 
7255 // static
7256 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
7257  Handle<JSReceiver> object,
7258  Handle<Object> key,
7259  PropertyDescriptor* desc,
7260  ShouldThrow should_throw) {
7261  if (object->IsJSArray()) {
7262  return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
7263  key, desc, should_throw);
7264  }
7265  if (object->IsJSProxy()) {
7266  return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
7267  key, desc, should_throw);
7268  }
7269  if (object->IsJSTypedArray()) {
7270  return JSTypedArray::DefineOwnProperty(
7271  isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw);
7272  }
7273 
7274  // OrdinaryDefineOwnProperty, by virtue of calling
7275  // DefineOwnPropertyIgnoreAttributes, can handle arguments
7276  // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
7277  return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
7278  desc, should_throw);
7279 }
7280 
7281 
7282 // static
7283 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
7284  Handle<JSObject> object,
7285  Handle<Object> key,
7286  PropertyDescriptor* desc,
7287  ShouldThrow should_throw) {
7288  bool success = false;
7289  DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey...
7290  LookupIterator it = LookupIterator::PropertyOrElement(
7291  isolate, object, key, &success, LookupIterator::OWN);
7292  DCHECK(success); // ...so creating a LookupIterator can't fail.
7293 
7294  // Deal with access checks first.
7295  if (it.state() == LookupIterator::ACCESS_CHECK) {
7296  if (!it.HasAccess()) {
7297  isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
7298  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7299  return Just(true);
7300  }
7301  it.Next();
7302  }
7303 
7304  return OrdinaryDefineOwnProperty(&it, desc, should_throw);
7305 }
7306 
7307 
7308 // ES6 9.1.6.1
7309 // static
7310 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
7311  PropertyDescriptor* desc,
7312  ShouldThrow should_throw) {
7313  Isolate* isolate = it->isolate();
7314  // 1. Let current be O.[[GetOwnProperty]](P).
7315  // 2. ReturnIfAbrupt(current).
7316  PropertyDescriptor current;
7317  MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
7318 
7319  it->Restart();
7320  // Handle interceptor
7321  for (; it->IsFound(); it->Next()) {
7322  if (it->state() == LookupIterator::INTERCEPTOR) {
7323  if (it->HolderIsReceiverOrHiddenPrototype()) {
7324  Maybe<bool> result = DefinePropertyWithInterceptorInternal(
7325  it, it->GetInterceptor(), should_throw, *desc);
7326  if (result.IsNothing() || result.FromJust()) {
7327  return result;
7328  }
7329  }
7330  }
7331  }
7332 
7333  // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
7334  // the iterator every time. Currently, the reasons why we need it are:
7335  // - handle interceptors correctly
7336  // - handle accessors correctly (which might change the holder's map)
7337  it->Restart();
7338  // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
7339  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
7340  bool extensible = JSObject::IsExtensible(object);
7341 
7342  return ValidateAndApplyPropertyDescriptor(
7343  isolate, it, extensible, desc, &current, should_throw, Handle<Name>());
7344 }
7345 
7346 
7347 // ES6 9.1.6.2
7348 // static
7349 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
7350  Isolate* isolate, bool extensible, PropertyDescriptor* desc,
7351  PropertyDescriptor* current, Handle<Name> property_name,
7352  ShouldThrow should_throw) {
7353  // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
7354  // Extensible, Desc, Current).
7355  return ValidateAndApplyPropertyDescriptor(
7356  isolate, nullptr, extensible, desc, current, should_throw, property_name);
7357 }
7358 
7359 
7360 // ES6 9.1.6.3
7361 // static
7362 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
7363  Isolate* isolate, LookupIterator* it, bool extensible,
7364  PropertyDescriptor* desc, PropertyDescriptor* current,
7365  ShouldThrow should_throw, Handle<Name> property_name) {
7366  // We either need a LookupIterator, or a property name.
7367  DCHECK((it == nullptr) != property_name.is_null());
7368  Handle<JSObject> object;
7369  if (it != nullptr) object = Handle<JSObject>::cast(it->GetReceiver());
7370  bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
7371  bool desc_is_accessor_descriptor =
7372  PropertyDescriptor::IsAccessorDescriptor(desc);
7373  bool desc_is_generic_descriptor =
7374  PropertyDescriptor::IsGenericDescriptor(desc);
7375  // 1. (Assert)
7376  // 2. If current is undefined, then
7377  if (current->is_empty()) {
7378  // 2a. If extensible is false, return false.
7379  if (!extensible) {
7380  RETURN_FAILURE(
7381  isolate, should_throw,
7382  NewTypeError(MessageTemplate::kDefineDisallowed,
7383  it != nullptr ? it->GetName() : property_name));
7384  }
7385  // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
7386  // (This is equivalent to !IsAccessorDescriptor(desc).)
7387  DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
7388  !desc_is_accessor_descriptor);
7389  if (!desc_is_accessor_descriptor) {
7390  // 2c i. If O is not undefined, create an own data property named P of
7391  // object O whose [[Value]], [[Writable]], [[Enumerable]] and
7392  // [[Configurable]] attribute values are described by Desc. If the value
7393  // of an attribute field of Desc is absent, the attribute of the newly
7394  // created property is set to its default value.
7395  if (it != nullptr) {
7396  if (!desc->has_writable()) desc->set_writable(false);
7397  if (!desc->has_enumerable()) desc->set_enumerable(false);
7398  if (!desc->has_configurable()) desc->set_configurable(false);
7399  Handle<Object> value(
7400  desc->has_value()
7401  ? desc->value()
7402  : Handle<Object>::cast(isolate->factory()->undefined_value()));
7403  MaybeHandle<Object> result =
7404  JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
7405  desc->ToAttributes());
7406  if (result.is_null()) return Nothing<bool>();
7407  }
7408  } else {
7409  // 2d. Else Desc must be an accessor Property Descriptor,
7410  DCHECK(desc_is_accessor_descriptor);
7411  // 2d i. If O is not undefined, create an own accessor property named P
7412  // of object O whose [[Get]], [[Set]], [[Enumerable]] and
7413  // [[Configurable]] attribute values are described by Desc. If the value
7414  // of an attribute field of Desc is absent, the attribute of the newly
7415  // created property is set to its default value.
7416  if (it != nullptr) {
7417  if (!desc->has_enumerable()) desc->set_enumerable(false);
7418  if (!desc->has_configurable()) desc->set_configurable(false);
7419  Handle<Object> getter(
7420  desc->has_get()
7421  ? desc->get()
7422  : Handle<Object>::cast(isolate->factory()->null_value()));
7423  Handle<Object> setter(
7424  desc->has_set()
7425  ? desc->set()
7426  : Handle<Object>::cast(isolate->factory()->null_value()));
7427  MaybeHandle<Object> result =
7428  JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
7429  if (result.is_null()) return Nothing<bool>();
7430  }
7431  }
7432  // 2e. Return true.
7433  return Just(true);
7434  }
7435  // 3. Return true, if every field in Desc is absent.
7436  // 4. Return true, if every field in Desc also occurs in current and the
7437  // value of every field in Desc is the same value as the corresponding field
7438  // in current when compared using the SameValue algorithm.
7439  if ((!desc->has_enumerable() ||
7440  desc->enumerable() == current->enumerable()) &&
7441  (!desc->has_configurable() ||
7442  desc->configurable() == current->configurable()) &&
7443  (!desc->has_value() ||
7444  (current->has_value() && current->value()->SameValue(*desc->value()))) &&
7445  (!desc->has_writable() ||
7446  (current->has_writable() && current->writable() == desc->writable())) &&
7447  (!desc->has_get() ||
7448  (current->has_get() && current->get()->SameValue(*desc->get()))) &&
7449  (!desc->has_set() ||
7450  (current->has_set() && current->set()->SameValue(*desc->set())))) {
7451  return Just(true);
7452  }
7453  // 5. If the [[Configurable]] field of current is false, then
7454  if (!current->configurable()) {
7455  // 5a. Return false, if the [[Configurable]] field of Desc is true.
7456  if (desc->has_configurable() && desc->configurable()) {
7457  RETURN_FAILURE(
7458  isolate, should_throw,
7459  NewTypeError(MessageTemplate::kRedefineDisallowed,
7460  it != nullptr ? it->GetName() : property_name));
7461  }
7462  // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
7463  // [[Enumerable]] fields of current and Desc are the Boolean negation of
7464  // each other.
7465  if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
7466  RETURN_FAILURE(
7467  isolate, should_throw,
7468  NewTypeError(MessageTemplate::kRedefineDisallowed,
7469  it != nullptr ? it->GetName() : property_name));
7470  }
7471  }
7472 
7473  bool current_is_data_descriptor =
7474  PropertyDescriptor::IsDataDescriptor(current);
7475  // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
7476  if (desc_is_generic_descriptor) {
7477  // Nothing to see here.
7478 
7479  // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
7480  // different results, then:
7481  } else if (current_is_data_descriptor != desc_is_data_descriptor) {
7482  // 7a. Return false, if the [[Configurable]] field of current is false.
7483  if (!current->configurable()) {
7484  RETURN_FAILURE(
7485  isolate, should_throw,
7486  NewTypeError(MessageTemplate::kRedefineDisallowed,
7487  it != nullptr ? it->GetName() : property_name));
7488  }
7489  // 7b. If IsDataDescriptor(current) is true, then:
7490  if (current_is_data_descriptor) {
7491  // 7b i. If O is not undefined, convert the property named P of object O
7492  // from a data property to an accessor property. Preserve the existing
7493  // values of the converted property's [[Configurable]] and [[Enumerable]]
7494  // attributes and set the rest of the property's attributes to their
7495  // default values.
7496  // --> Folded into step 10.
7497  } else {
7498  // 7c i. If O is not undefined, convert the property named P of object O
7499  // from an accessor property to a data property. Preserve the existing
7500  // values of the converted property’s [[Configurable]] and [[Enumerable]]
7501  // attributes and set the rest of the property’s attributes to their
7502  // default values.
7503  // --> Folded into step 10.
7504  }
7505 
7506  // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
7507  // true, then:
7508  } else if (current_is_data_descriptor && desc_is_data_descriptor) {
7509  // 8a. If the [[Configurable]] field of current is false, then:
7510  if (!current->configurable()) {
7511  // 8a i. Return false, if the [[Writable]] field of current is false and
7512  // the [[Writable]] field of Desc is true.
7513  if (!current->writable() && desc->has_writable() && desc->writable()) {
7514  RETURN_FAILURE(
7515  isolate, should_throw,
7516  NewTypeError(MessageTemplate::kRedefineDisallowed,
7517  it != nullptr ? it->GetName() : property_name));
7518  }
7519  // 8a ii. If the [[Writable]] field of current is false, then:
7520  if (!current->writable()) {
7521  // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
7522  // SameValue(Desc.[[Value]], current.[[Value]]) is false.
7523  if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
7524  RETURN_FAILURE(
7525  isolate, should_throw,
7526  NewTypeError(MessageTemplate::kRedefineDisallowed,
7527  it != nullptr ? it->GetName() : property_name));
7528  }
7529  }
7530  }
7531  } else {
7532  // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
7533  // are both true,
7534  DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
7535  desc_is_accessor_descriptor);
7536  // 9a. If the [[Configurable]] field of current is false, then:
7537  if (!current->configurable()) {
7538  // 9a i. Return false, if the [[Set]] field of Desc is present and
7539  // SameValue(Desc.[[Set]], current.[[Set]]) is false.
7540  if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
7541  RETURN_FAILURE(
7542  isolate, should_throw,
7543  NewTypeError(MessageTemplate::kRedefineDisallowed,
7544  it != nullptr ? it->GetName() : property_name));
7545  }
7546  // 9a ii. Return false, if the [[Get]] field of Desc is present and
7547  // SameValue(Desc.[[Get]], current.[[Get]]) is false.
7548  if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
7549  RETURN_FAILURE(
7550  isolate, should_throw,
7551  NewTypeError(MessageTemplate::kRedefineDisallowed,
7552  it != nullptr ? it->GetName() : property_name));
7553  }
7554  }
7555  }
7556 
7557  // 10. If O is not undefined, then:
7558  if (it != nullptr) {
7559  // 10a. For each field of Desc that is present, set the corresponding
7560  // attribute of the property named P of object O to the value of the field.
7561  PropertyAttributes attrs = NONE;
7562 
7563  if (desc->has_enumerable()) {
7564  attrs = static_cast<PropertyAttributes>(
7565  attrs | (desc->enumerable() ? NONE : DONT_ENUM));
7566  } else {
7567  attrs = static_cast<PropertyAttributes>(
7568  attrs | (current->enumerable() ? NONE : DONT_ENUM));
7569  }
7570  if (desc->has_configurable()) {
7571  attrs = static_cast<PropertyAttributes>(
7572  attrs | (desc->configurable() ? NONE : DONT_DELETE));
7573  } else {
7574  attrs = static_cast<PropertyAttributes>(
7575  attrs | (current->configurable() ? NONE : DONT_DELETE));
7576  }
7577  if (desc_is_data_descriptor ||
7578  (desc_is_generic_descriptor && current_is_data_descriptor)) {
7579  if (desc->has_writable()) {
7580  attrs = static_cast<PropertyAttributes>(
7581  attrs | (desc->writable() ? NONE : READ_ONLY));
7582  } else {
7583  attrs = static_cast<PropertyAttributes>(
7584  attrs | (current->writable() ? NONE : READ_ONLY));
7585  }
7586  Handle<Object> value(
7587  desc->has_value() ? desc->value()
7588  : current->has_value()
7589  ? current->value()
7590  : Handle<Object>::cast(
7591  isolate->factory()->undefined_value()));
7592  return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs,
7593  should_throw);
7594  } else {
7595  DCHECK(desc_is_accessor_descriptor ||
7596  (desc_is_generic_descriptor &&
7597  PropertyDescriptor::IsAccessorDescriptor(current)));
7598  Handle<Object> getter(
7599  desc->has_get()
7600  ? desc->get()
7601  : current->has_get()
7602  ? current->get()
7603  : Handle<Object>::cast(isolate->factory()->null_value()));
7604  Handle<Object> setter(
7605  desc->has_set()
7606  ? desc->set()
7607  : current->has_set()
7608  ? current->set()
7609  : Handle<Object>::cast(isolate->factory()->null_value()));
7610  MaybeHandle<Object> result =
7611  JSObject::DefineAccessor(it, getter, setter, attrs);
7612  if (result.is_null()) return Nothing<bool>();
7613  }
7614  }
7615 
7616  // 11. Return true.
7617  return Just(true);
7618 }
7619 
7620 // static
7621 Maybe<bool> JSReceiver::CreateDataProperty(Isolate* isolate,
7622  Handle<JSReceiver> object,
7623  Handle<Name> key,
7624  Handle<Object> value,
7625  ShouldThrow should_throw) {
7626  LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, key,
7627  LookupIterator::OWN);
7628  return CreateDataProperty(&it, value, should_throw);
7629 }
7630 
7631 // static
7632 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
7633  Handle<Object> value,
7634  ShouldThrow should_throw) {
7635  DCHECK(!it->check_prototype_chain());
7636  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
7637  Isolate* isolate = receiver->GetIsolate();
7638 
7639  if (receiver->IsJSObject()) {
7640  return JSObject::CreateDataProperty(it, value, should_throw); // Shortcut.
7641  }
7642 
7643  PropertyDescriptor new_desc;
7644  new_desc.set_value(value);
7645  new_desc.set_writable(true);
7646  new_desc.set_enumerable(true);
7647  new_desc.set_configurable(true);
7648 
7649  return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
7650  &new_desc, should_throw);
7651 }
7652 
7653 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
7654  Handle<Object> value,
7655  ShouldThrow should_throw) {
7656  DCHECK(it->GetReceiver()->IsJSObject());
7657  MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
7658  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
7659  Isolate* isolate = receiver->GetIsolate();
7660 
7661  if (it->IsFound()) {
7662  Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
7663  MAYBE_RETURN(attributes, Nothing<bool>());
7664  if ((attributes.FromJust() & DONT_DELETE) != 0) {
7665  RETURN_FAILURE(
7666  isolate, should_throw,
7667  NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
7668  }
7669  } else {
7670  if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
7671  RETURN_FAILURE(
7672  isolate, should_throw,
7673  NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
7674  }
7675  }
7676 
7677  RETURN_ON_EXCEPTION_VALUE(it->isolate(),
7678  DefineOwnPropertyIgnoreAttributes(it, value, NONE),
7679  Nothing<bool>());
7680 
7681  return Just(true);
7682 }
7683 
7684 // TODO(jkummerow): Consider unification with FastAsArrayLength() in
7685 // accessors.cc.
7686 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
7687  DCHECK(value->IsNumber() || value->IsName());
7688  if (value->ToArrayLength(length)) return true;
7689  if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
7690  return false;
7691 }
7692 
7693 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
7694  return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
7695 }
7696 
7697 
7698 // ES6 9.4.2.1
7699 // static
7700 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
7701  Handle<Object> name,
7702  PropertyDescriptor* desc,
7703  ShouldThrow should_throw) {
7704  // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
7705  // 2. If P is "length", then:
7706  // TODO(jkummerow): Check if we need slow string comparison.
7707  if (*name == ReadOnlyRoots(isolate).length_string()) {
7708  // 2a. Return ArraySetLength(A, Desc).
7709  return ArraySetLength(isolate, o, desc, should_throw);
7710  }
7711  // 3. Else if P is an array index, then:
7712  uint32_t index = 0;
7713  if (PropertyKeyToArrayIndex(name, &index)) {
7714  // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
7715  PropertyDescriptor old_len_desc;
7716  Maybe<bool> success = GetOwnPropertyDescriptor(
7717  isolate, o, isolate->factory()->length_string(), &old_len_desc);
7718  // 3b. (Assert)
7719  DCHECK(success.FromJust());
7720  USE(success);
7721  // 3c. Let oldLen be oldLenDesc.[[Value]].
7722  uint32_t old_len = 0;
7723  CHECK(old_len_desc.value()->ToArrayLength(&old_len));
7724  // 3d. Let index be ToUint32(P).
7725  // (Already done above.)
7726  // 3e. (Assert)
7727  // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
7728  // return false.
7729  if (index >= old_len && old_len_desc.has_writable() &&
7730  !old_len_desc.writable()) {
7731  RETURN_FAILURE(isolate, should_throw,
7732  NewTypeError(MessageTemplate::kDefineDisallowed, name));
7733  }
7734  // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
7735  Maybe<bool> succeeded =
7736  OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
7737  // 3h. Assert: succeeded is not an abrupt completion.
7738  // In our case, if should_throw == kThrowOnError, it can be!
7739  // 3i. If succeeded is false, return false.
7740  if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
7741  // 3j. If index >= oldLen, then:
7742  if (index >= old_len) {
7743  // 3j i. Set oldLenDesc.[[Value]] to index + 1.
7744  old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
7745  // 3j ii. Let succeeded be
7746  // OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
7747  succeeded = OrdinaryDefineOwnProperty(isolate, o,
7748  isolate->factory()->length_string(),
7749  &old_len_desc, should_throw);
7750  // 3j iii. Assert: succeeded is true.
7751  DCHECK(succeeded.FromJust());
7752  USE(succeeded);
7753  }
7754  // 3k. Return true.
7755  return Just(true);
7756  }
7757 
7758  // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
7759  return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
7760 }
7761 
7762 
7763 // Part of ES6 9.4.2.4 ArraySetLength.
7764 // static
7765 bool JSArray::AnythingToArrayLength(Isolate* isolate,
7766  Handle<Object> length_object,
7767  uint32_t* output) {
7768  // Fast path: check numbers and strings that can be converted directly
7769  // and unobservably.
7770  if (length_object->ToArrayLength(output)) return true;
7771  if (length_object->IsString() &&
7772  Handle<String>::cast(length_object)->AsArrayIndex(output)) {
7773  return true;
7774  }
7775  // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
7776  // 3. Let newLen be ToUint32(Desc.[[Value]]).
7777  Handle<Object> uint32_v;
7778  if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
7779  // 4. ReturnIfAbrupt(newLen).
7780  return false;
7781  }
7782  // 5. Let numberLen be ToNumber(Desc.[[Value]]).
7783  Handle<Object> number_v;
7784  if (!Object::ToNumber(isolate, length_object).ToHandle(&number_v)) {
7785  // 6. ReturnIfAbrupt(newLen).
7786  return false;
7787  }
7788  // 7. If newLen != numberLen, throw a RangeError exception.
7789  if (uint32_v->Number() != number_v->Number()) {
7790  Handle<Object> exception =
7791  isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
7792  isolate->Throw(*exception);
7793  return false;
7794  }
7795  CHECK(uint32_v->ToArrayLength(output));
7796  return true;
7797 }
7798 
7799 
7800 // ES6 9.4.2.4
7801 // static
7802 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
7803  PropertyDescriptor* desc,
7804  ShouldThrow should_throw) {
7805  // 1. If the [[Value]] field of Desc is absent, then
7806  if (!desc->has_value()) {
7807  // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
7808  return OrdinaryDefineOwnProperty(
7809  isolate, a, isolate->factory()->length_string(), desc, should_throw);
7810  }
7811  // 2. Let newLenDesc be a copy of Desc.
7812  // (Actual copying is not necessary.)
7813  PropertyDescriptor* new_len_desc = desc;
7814  // 3. - 7. Convert Desc.[[Value]] to newLen.
7815  uint32_t new_len = 0;
7816  if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
7817  DCHECK(isolate->has_pending_exception());
7818  return Nothing<bool>();
7819  }
7820  // 8. Set newLenDesc.[[Value]] to newLen.
7821  // (Done below, if needed.)
7822  // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
7823  PropertyDescriptor old_len_desc;
7824  Maybe<bool> success = GetOwnPropertyDescriptor(
7825  isolate, a, isolate->factory()->length_string(), &old_len_desc);
7826  // 10. (Assert)
7827  DCHECK(success.FromJust());
7828  USE(success);
7829  // 11. Let oldLen be oldLenDesc.[[Value]].
7830  uint32_t old_len = 0;
7831  CHECK(old_len_desc.value()->ToArrayLength(&old_len));
7832  // 12. If newLen >= oldLen, then
7833  if (new_len >= old_len) {
7834  // 8. Set newLenDesc.[[Value]] to newLen.
7835  // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
7836  new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
7837  return OrdinaryDefineOwnProperty(isolate, a,
7838  isolate->factory()->length_string(),
7839  new_len_desc, should_throw);
7840  }
7841  // 13. If oldLenDesc.[[Writable]] is false, return false.
7842  if (!old_len_desc.writable()) {
7843  RETURN_FAILURE(isolate, should_throw,
7844  NewTypeError(MessageTemplate::kRedefineDisallowed,
7845  isolate->factory()->length_string()));
7846  }
7847  // 14. If newLenDesc.[[Writable]] is absent or has the value true,
7848  // let newWritable be true.
7849  bool new_writable = false;
7850  if (!new_len_desc->has_writable() || new_len_desc->writable()) {
7851  new_writable = true;
7852  } else {
7853  // 15. Else,
7854  // 15a. Need to defer setting the [[Writable]] attribute to false in case
7855  // any elements cannot be deleted.
7856  // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
7857  // 15c. Set newLenDesc.[[Writable]] to true.
7858  // (Not needed.)
7859  }
7860  // Most of steps 16 through 19 is implemented by JSArray::SetLength.
7861  JSArray::SetLength(a, new_len);
7862  // Steps 19d-ii, 20.
7863  if (!new_writable) {
7864  PropertyDescriptor readonly;
7865  readonly.set_writable(false);
7866  Maybe<bool> success = OrdinaryDefineOwnProperty(
7867  isolate, a, isolate->factory()->length_string(), &readonly,
7868  should_throw);
7869  DCHECK(success.FromJust());
7870  USE(success);
7871  }
7872  uint32_t actual_new_len = 0;
7873  CHECK(a->length()->ToArrayLength(&actual_new_len));
7874  // Steps 19d-v, 21. Return false if there were non-deletable elements.
7875  bool result = actual_new_len == new_len;
7876  if (!result) {
7877  RETURN_FAILURE(
7878  isolate, should_throw,
7879  NewTypeError(MessageTemplate::kStrictDeleteProperty,
7880  isolate->factory()->NewNumberFromUint(actual_new_len - 1),
7881  a));
7882  }
7883  return Just(result);
7884 }
7885 
7886 
7887 // ES6 9.5.6
7888 // static
7889 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
7890  Handle<Object> key,
7891  PropertyDescriptor* desc,
7892  ShouldThrow should_throw) {
7893  STACK_CHECK(isolate, Nothing<bool>());
7894  if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
7895  DCHECK(!Handle<Symbol>::cast(key)->IsPrivateName());
7896  return JSProxy::SetPrivateSymbol(isolate, proxy, Handle<Symbol>::cast(key),
7897  desc, should_throw);
7898  }
7899  Handle<String> trap_name = isolate->factory()->defineProperty_string();
7900  // 1. Assert: IsPropertyKey(P) is true.
7901  DCHECK(key->IsName() || key->IsNumber());
7902  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
7903  Handle<Object> handler(proxy->handler(), isolate);
7904  // 3. If handler is null, throw a TypeError exception.
7905  // 4. Assert: Type(handler) is Object.
7906  if (proxy->IsRevoked()) {
7907  isolate->Throw(*isolate->factory()->NewTypeError(
7908  MessageTemplate::kProxyRevoked, trap_name));
7909  return Nothing<bool>();
7910  }
7911  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
7912  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
7913  // 6. Let trap be ? GetMethod(handler, "defineProperty").
7914  Handle<Object> trap;
7915  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7916  isolate, trap,
7917  Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
7918  Nothing<bool>());
7919  // 7. If trap is undefined, then:
7920  if (trap->IsUndefined(isolate)) {
7921  // 7a. Return target.[[DefineOwnProperty]](P, Desc).
7922  return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
7923  should_throw);
7924  }
7925  // 8. Let descObj be FromPropertyDescriptor(Desc).
7926  Handle<Object> desc_obj = desc->ToObject(isolate);
7927  // 9. Let booleanTrapResult be
7928  // ToBoolean(? Call(trap, handler, «target, P, descObj»)).
7929  Handle<Name> property_name =
7930  key->IsName()
7931  ? Handle<Name>::cast(key)
7932  : Handle<Name>::cast(isolate->factory()->NumberToString(key));
7933  // Do not leak private property names.
7934  DCHECK(!property_name->IsPrivate());
7935  Handle<Object> trap_result_obj;
7936  Handle<Object> args[] = {target, property_name, desc_obj};
7937  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7938  isolate, trap_result_obj,
7939  Execution::Call(isolate, trap, handler, arraysize(args), args),
7940  Nothing<bool>());
7941  // 10. If booleanTrapResult is false, return false.
7942  if (!trap_result_obj->BooleanValue(isolate)) {
7943  RETURN_FAILURE(isolate, should_throw,
7944  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
7945  trap_name, property_name));
7946  }
7947  // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
7948  PropertyDescriptor target_desc;
7949  Maybe<bool> target_found =
7950  JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
7951  MAYBE_RETURN(target_found, Nothing<bool>());
7952  // 12. Let extensibleTarget be ? IsExtensible(target).
7953  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
7954  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
7955  bool extensible_target = maybe_extensible.FromJust();
7956  // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
7957  // is false, then:
7958  // 13a. Let settingConfigFalse be true.
7959  // 14. Else let settingConfigFalse be false.
7960  bool setting_config_false = desc->has_configurable() && !desc->configurable();
7961  // 15. If targetDesc is undefined, then
7962  if (!target_found.FromJust()) {
7963  // 15a. If extensibleTarget is false, throw a TypeError exception.
7964  if (!extensible_target) {
7965  isolate->Throw(*isolate->factory()->NewTypeError(
7966  MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
7967  return Nothing<bool>();
7968  }
7969  // 15b. If settingConfigFalse is true, throw a TypeError exception.
7970  if (setting_config_false) {
7971  isolate->Throw(*isolate->factory()->NewTypeError(
7972  MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7973  return Nothing<bool>();
7974  }
7975  } else {
7976  // 16. Else targetDesc is not undefined,
7977  // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
7978  // targetDesc) is false, throw a TypeError exception.
7979  Maybe<bool> valid =
7980  IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
7981  &target_desc, property_name, kDontThrow);
7982  MAYBE_RETURN(valid, Nothing<bool>());
7983  if (!valid.FromJust()) {
7984  isolate->Throw(*isolate->factory()->NewTypeError(
7985  MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
7986  return Nothing<bool>();
7987  }
7988  // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
7989  // true, throw a TypeError exception.
7990  if (setting_config_false && target_desc.configurable()) {
7991  isolate->Throw(*isolate->factory()->NewTypeError(
7992  MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7993  return Nothing<bool>();
7994  }
7995  }
7996  // 17. Return true.
7997  return Just(true);
7998 }
7999 
8000 // static
8001 Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
8002  Handle<Symbol> private_name,
8003  PropertyDescriptor* desc,
8004  ShouldThrow should_throw) {
8005  DCHECK(!private_name->IsPrivateName());
8006  // Despite the generic name, this can only add private data properties.
8007  if (!PropertyDescriptor::IsDataDescriptor(desc) ||
8008  desc->ToAttributes() != DONT_ENUM) {
8009  RETURN_FAILURE(isolate, should_throw,
8010  NewTypeError(MessageTemplate::kProxyPrivate));
8011  }
8012  DCHECK(proxy->map()->is_dictionary_map());
8013  Handle<Object> value =
8014  desc->has_value()
8015  ? desc->value()
8016  : Handle<Object>::cast(isolate->factory()->undefined_value());
8017 
8018  LookupIterator it(proxy, private_name, proxy);
8019 
8020  if (it.IsFound()) {
8021  DCHECK_EQ(LookupIterator::DATA, it.state());
8022  DCHECK_EQ(DONT_ENUM, it.property_attributes());
8023  it.WriteDataValue(value, false);
8024  return Just(true);
8025  }
8026 
8027  Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
8028  PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell);
8029  Handle<NameDictionary> result =
8030  NameDictionary::Add(isolate, dict, private_name, value, details);
8031  if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
8032  return Just(true);
8033 }
8034 
8035 // static
8036 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
8037  Handle<JSReceiver> object,
8038  Handle<Object> key,
8039  PropertyDescriptor* desc) {
8040  bool success = false;
8041  DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey...
8042  LookupIterator it = LookupIterator::PropertyOrElement(
8043  isolate, object, key, &success, LookupIterator::OWN);
8044  DCHECK(success); // ...so creating a LookupIterator can't fail.
8045  return GetOwnPropertyDescriptor(&it, desc);
8046 }
8047 
8048 namespace {
8049 
8050 Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
8051  PropertyDescriptor* desc) {
8052  if (it->state() == LookupIterator::ACCESS_CHECK) {
8053  if (it->HasAccess()) {
8054  it->Next();
8055  } else if (!JSObject::AllCanRead(it) ||
8056  it->state() != LookupIterator::INTERCEPTOR) {
8057  it->Restart();
8058  return Just(false);
8059  }
8060  }
8061 
8062  if (it->state() != LookupIterator::INTERCEPTOR) return Just(false);
8063 
8064  Isolate* isolate = it->isolate();
8065  Handle<InterceptorInfo> interceptor = it->GetInterceptor();
8066  if (interceptor->descriptor()->IsUndefined(isolate)) return Just(false);
8067 
8068  Handle<Object> result;
8069  Handle<JSObject> holder = it->GetHolder<JSObject>();
8070 
8071  Handle<Object> receiver = it->GetReceiver();
8072  if (!receiver->IsJSReceiver()) {
8073  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
8074  Object::ConvertReceiver(isolate, receiver),
8075  Nothing<bool>());
8076  }
8077 
8078  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
8079  *holder, kDontThrow);
8080  if (it->IsElement()) {
8081  result = args.CallIndexedDescriptor(interceptor, it->index());
8082  } else {
8083  result = args.CallNamedDescriptor(interceptor, it->name());
8084  }
8085  if (!result.is_null()) {
8086  // Request successfully intercepted, try to set the property
8087  // descriptor.
8088  Utils::ApiCheck(
8089  PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
8090  it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
8091  : "v8::NamedPropertyDescriptorCallback",
8092  "Invalid property descriptor.");
8093 
8094  return Just(true);
8095  }
8096 
8097  it->Next();
8098  return Just(false);
8099 }
8100 } // namespace
8101 
8102 // ES6 9.1.5.1
8103 // Returns true on success, false if the property didn't exist, nothing if
8104 // an exception was thrown.
8105 // static
8106 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
8107  PropertyDescriptor* desc) {
8108  Isolate* isolate = it->isolate();
8109  // "Virtual" dispatch.
8110  if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
8111  return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
8112  it->GetName(), desc);
8113  }
8114 
8115  Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
8116  MAYBE_RETURN(intercepted, Nothing<bool>());
8117  if (intercepted.FromJust()) {
8118  return Just(true);
8119  }
8120 
8121  // Request was not intercepted, continue as normal.
8122  // 1. (Assert)
8123  // 2. If O does not have an own property with key P, return undefined.
8124  Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
8125  MAYBE_RETURN(maybe, Nothing<bool>());
8126  PropertyAttributes attrs = maybe.FromJust();
8127  if (attrs == ABSENT) return Just(false);
8128  DCHECK(!isolate->has_pending_exception());
8129 
8130  // 3. Let D be a newly created Property Descriptor with no fields.
8131  DCHECK(desc->is_empty());
8132  // 4. Let X be O's own property whose key is P.
8133  // 5. If X is a data property, then
8134  bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
8135  it->GetAccessors()->IsAccessorPair();
8136  if (!is_accessor_pair) {
8137  // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
8138  Handle<Object> value;
8139  if (!Object::GetProperty(it).ToHandle(&value)) {
8140  DCHECK(isolate->has_pending_exception());
8141  return Nothing<bool>();
8142  }
8143  desc->set_value(value);
8144  // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
8145  desc->set_writable((attrs & READ_ONLY) == 0);
8146  } else {
8147  // 6. Else X is an accessor property, so
8148  Handle<AccessorPair> accessors =
8149  Handle<AccessorPair>::cast(it->GetAccessors());
8150  // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
8151  desc->set_get(
8152  AccessorPair::GetComponent(isolate, accessors, ACCESSOR_GETTER));
8153  // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
8154  desc->set_set(
8155  AccessorPair::GetComponent(isolate, accessors, ACCESSOR_SETTER));
8156  }
8157 
8158  // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
8159  desc->set_enumerable((attrs & DONT_ENUM) == 0);
8160  // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
8161  desc->set_configurable((attrs & DONT_DELETE) == 0);
8162  // 9. Return D.
8163  DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
8164  PropertyDescriptor::IsDataDescriptor(desc));
8165  return Just(true);
8166 }
8167 
8168 
8169 // ES6 9.5.5
8170 // static
8171 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
8172  Handle<JSProxy> proxy,
8173  Handle<Name> name,
8174  PropertyDescriptor* desc) {
8175  DCHECK(!name->IsPrivate());
8176  STACK_CHECK(isolate, Nothing<bool>());
8177 
8178  Handle<String> trap_name =
8179  isolate->factory()->getOwnPropertyDescriptor_string();
8180  // 1. (Assert)
8181  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
8182  Handle<Object> handler(proxy->handler(), isolate);
8183  // 3. If handler is null, throw a TypeError exception.
8184  // 4. Assert: Type(handler) is Object.
8185  if (proxy->IsRevoked()) {
8186  isolate->Throw(*isolate->factory()->NewTypeError(
8187  MessageTemplate::kProxyRevoked, trap_name));
8188  return Nothing<bool>();
8189  }
8190  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
8191  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8192  // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
8193  Handle<Object> trap;
8194  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8195  isolate, trap,
8196  Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
8197  Nothing<bool>());
8198  // 7. If trap is undefined, then
8199  if (trap->IsUndefined(isolate)) {
8200  // 7a. Return target.[[GetOwnProperty]](P).
8201  return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
8202  }
8203  // 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
8204  Handle<Object> trap_result_obj;
8205  Handle<Object> args[] = {target, name};
8206  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8207  isolate, trap_result_obj,
8208  Execution::Call(isolate, trap, handler, arraysize(args), args),
8209  Nothing<bool>());
8210  // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
8211  // TypeError exception.
8212  if (!trap_result_obj->IsJSReceiver() &&
8213  !trap_result_obj->IsUndefined(isolate)) {
8214  isolate->Throw(*isolate->factory()->NewTypeError(
8215  MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
8216  return Nothing<bool>();
8217  }
8218  // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
8219  PropertyDescriptor target_desc;
8220  Maybe<bool> found =
8221  JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
8222  MAYBE_RETURN(found, Nothing<bool>());
8223  // 11. If trapResultObj is undefined, then
8224  if (trap_result_obj->IsUndefined(isolate)) {
8225  // 11a. If targetDesc is undefined, return undefined.
8226  if (!found.FromJust()) return Just(false);
8227  // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
8228  // exception.
8229  if (!target_desc.configurable()) {
8230  isolate->Throw(*isolate->factory()->NewTypeError(
8231  MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
8232  return Nothing<bool>();
8233  }
8234  // 11c. Let extensibleTarget be ? IsExtensible(target).
8235  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
8236  MAYBE_RETURN(extensible_target, Nothing<bool>());
8237  // 11d. (Assert)
8238  // 11e. If extensibleTarget is false, throw a TypeError exception.
8239  if (!extensible_target.FromJust()) {
8240  isolate->Throw(*isolate->factory()->NewTypeError(
8241  MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
8242  return Nothing<bool>();
8243  }
8244  // 11f. Return undefined.
8245  return Just(false);
8246  }
8247  // 12. Let extensibleTarget be ? IsExtensible(target).
8248  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
8249  MAYBE_RETURN(extensible_target, Nothing<bool>());
8250  // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
8251  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
8252  desc)) {
8253  DCHECK(isolate->has_pending_exception());
8254  return Nothing<bool>();
8255  }
8256  // 14. Call CompletePropertyDescriptor(resultDesc).
8257  PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
8258  // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
8259  // resultDesc, targetDesc).
8260  Maybe<bool> valid =
8261  IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
8262  desc, &target_desc, name, kDontThrow);
8263  MAYBE_RETURN(valid, Nothing<bool>());
8264  // 16. If valid is false, throw a TypeError exception.
8265  if (!valid.FromJust()) {
8266  isolate->Throw(*isolate->factory()->NewTypeError(
8267  MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
8268  return Nothing<bool>();
8269  }
8270  // 17. If resultDesc.[[Configurable]] is false, then
8271  if (!desc->configurable()) {
8272  // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
8273  if (target_desc.is_empty() || target_desc.configurable()) {
8274  // 17a i. Throw a TypeError exception.
8275  isolate->Throw(*isolate->factory()->NewTypeError(
8276  MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
8277  name));
8278  return Nothing<bool>();
8279  }
8280  }
8281  // 18. Return resultDesc.
8282  return Just(true);
8283 }
8284 
8285 
8286 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
8287  IntegrityLevel level,
8288  ShouldThrow should_throw) {
8289  DCHECK(level == SEALED || level == FROZEN);
8290 
8291  if (receiver->IsJSObject()) {
8292  Handle<JSObject> object = Handle<JSObject>::cast(receiver);
8293 
8294  if (!object->HasSloppyArgumentsElements() &&
8295  !object->IsJSModuleNamespace()) { // Fast path.
8296  // Prevent memory leaks by not adding unnecessary transitions.
8297  Maybe<bool> test = JSObject::TestIntegrityLevel(object, level);
8298  MAYBE_RETURN(test, Nothing<bool>());
8299  if (test.FromJust()) return test;
8300 
8301  if (level == SEALED) {
8302  return JSObject::PreventExtensionsWithTransition<SEALED>(object,
8303  should_throw);
8304  } else {
8305  return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
8306  should_throw);
8307  }
8308  }
8309  }
8310 
8311  Isolate* isolate = receiver->GetIsolate();
8312 
8313  MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
8314  Nothing<bool>());
8315 
8316  Handle<FixedArray> keys;
8317  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8318  isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
8319 
8320  PropertyDescriptor no_conf;
8321  no_conf.set_configurable(false);
8322 
8323  PropertyDescriptor no_conf_no_write;
8324  no_conf_no_write.set_configurable(false);
8325  no_conf_no_write.set_writable(false);
8326 
8327  if (level == SEALED) {
8328  for (int i = 0; i < keys->length(); ++i) {
8329  Handle<Object> key(keys->get(i), isolate);
8330  MAYBE_RETURN(
8331  DefineOwnProperty(isolate, receiver, key, &no_conf, kThrowOnError),
8332  Nothing<bool>());
8333  }
8334  return Just(true);
8335  }
8336 
8337  for (int i = 0; i < keys->length(); ++i) {
8338  Handle<Object> key(keys->get(i), isolate);
8339  PropertyDescriptor current_desc;
8340  Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
8341  isolate, receiver, key, &current_desc);
8342  MAYBE_RETURN(owned, Nothing<bool>());
8343  if (owned.FromJust()) {
8344  PropertyDescriptor desc =
8345  PropertyDescriptor::IsAccessorDescriptor(&current_desc)
8346  ? no_conf
8347  : no_conf_no_write;
8348  MAYBE_RETURN(
8349  DefineOwnProperty(isolate, receiver, key, &desc, kThrowOnError),
8350  Nothing<bool>());
8351  }
8352  }
8353  return Just(true);
8354 }
8355 
8356 namespace {
8357 
8358 template <typename Dictionary>
8359 bool TestDictionaryPropertiesIntegrityLevel(Dictionary dict,
8360  ReadOnlyRoots roots,
8361  PropertyAttributes level) {
8362  DCHECK(level == SEALED || level == FROZEN);
8363 
8364  uint32_t capacity = dict->Capacity();
8365  for (uint32_t i = 0; i < capacity; i++) {
8366  Object* key;
8367  if (!dict->ToKey(roots, i, &key)) continue;
8368  if (key->FilterKey(ALL_PROPERTIES)) continue;
8369  PropertyDetails details = dict->DetailsAt(i);
8370  if (details.IsConfigurable()) return false;
8371  if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
8372  return false;
8373  }
8374  }
8375  return true;
8376 }
8377 
8378 bool TestFastPropertiesIntegrityLevel(Map map, PropertyAttributes level) {
8379  DCHECK(level == SEALED || level == FROZEN);
8380  DCHECK(!map->IsCustomElementsReceiverMap());
8381  DCHECK(!map->is_dictionary_map());
8382 
8383  DescriptorArray* descriptors = map->instance_descriptors();
8384  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
8385  for (int i = 0; i < number_of_own_descriptors; i++) {
8386  if (descriptors->GetKey(i)->IsPrivate()) continue;
8387  PropertyDetails details = descriptors->GetDetails(i);
8388  if (details.IsConfigurable()) return false;
8389  if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
8390  return false;
8391  }
8392  }
8393  return true;
8394 }
8395 
8396 bool TestPropertiesIntegrityLevel(JSObject* object, PropertyAttributes level) {
8397  DCHECK(!object->map()->IsCustomElementsReceiverMap());
8398 
8399  if (object->HasFastProperties()) {
8400  return TestFastPropertiesIntegrityLevel(object->map(), level);
8401  }
8402 
8403  return TestDictionaryPropertiesIntegrityLevel(
8404  object->property_dictionary(), object->GetReadOnlyRoots(), level);
8405 }
8406 
8407 bool TestElementsIntegrityLevel(JSObject* object, PropertyAttributes level) {
8408  DCHECK(!object->HasSloppyArgumentsElements());
8409 
8410  ElementsKind kind = object->GetElementsKind();
8411 
8412  if (IsDictionaryElementsKind(kind)) {
8413  return TestDictionaryPropertiesIntegrityLevel(
8414  NumberDictionary::cast(object->elements()), object->GetReadOnlyRoots(),
8415  level);
8416  }
8417 
8418  ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
8419  // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have
8420  // PropertyAttributes so just test if empty
8421  return accessor->NumberOfElements(object) == 0;
8422 }
8423 
8424 bool FastTestIntegrityLevel(JSObject* object, PropertyAttributes level) {
8425  DCHECK(!object->map()->IsCustomElementsReceiverMap());
8426 
8427  return !object->map()->is_extensible() &&
8428  TestElementsIntegrityLevel(object, level) &&
8429  TestPropertiesIntegrityLevel(object, level);
8430 }
8431 
8432 Maybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver,
8433  PropertyAttributes level) {
8434  DCHECK(level == SEALED || level == FROZEN);
8435 
8436  Maybe<bool> extensible = JSReceiver::IsExtensible(receiver);
8437  MAYBE_RETURN(extensible, Nothing<bool>());
8438  if (extensible.FromJust()) return Just(false);
8439 
8440  Isolate* isolate = receiver->GetIsolate();
8441 
8442  Handle<FixedArray> keys;
8443  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8444  isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
8445 
8446  for (int i = 0; i < keys->length(); ++i) {
8447  Handle<Object> key(keys->get(i), isolate);
8448  PropertyDescriptor current_desc;
8449  Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
8450  isolate, receiver, key, &current_desc);
8451  MAYBE_RETURN(owned, Nothing<bool>());
8452  if (owned.FromJust()) {
8453  if (current_desc.configurable()) return Just(false);
8454  if (level == FROZEN &&
8455  PropertyDescriptor::IsDataDescriptor(&current_desc) &&
8456  current_desc.writable()) {
8457  return Just(false);
8458  }
8459  }
8460  }
8461  return Just(true);
8462 }
8463 
8464 } // namespace
8465 
8466 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver,
8467  IntegrityLevel level) {
8468  if (!receiver->map()->IsCustomElementsReceiverMap()) {
8469  return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver),
8470  level);
8471  }
8472  return GenericTestIntegrityLevel(receiver, level);
8473 }
8474 
8475 Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object,
8476  IntegrityLevel level) {
8477  if (!object->map()->IsCustomElementsReceiverMap() &&
8478  !object->HasSloppyArgumentsElements()) {
8479  return Just(FastTestIntegrityLevel(*object, level));
8480  }
8481  return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(object), level);
8482 }
8483 
8484 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
8485  ShouldThrow should_throw) {
8486  if (object->IsJSProxy()) {
8487  return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
8488  should_throw);
8489  }
8490  DCHECK(object->IsJSObject());
8491  return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
8492  should_throw);
8493 }
8494 
8495 
8496 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
8497  ShouldThrow should_throw) {
8498  Isolate* isolate = proxy->GetIsolate();
8499  STACK_CHECK(isolate, Nothing<bool>());
8500  Factory* factory = isolate->factory();
8501  Handle<String> trap_name = factory->preventExtensions_string();
8502 
8503  if (proxy->IsRevoked()) {
8504  isolate->Throw(
8505  *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
8506  return Nothing<bool>();
8507  }
8508  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8509  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
8510 
8511  Handle<Object> trap;
8512  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8513  isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
8514  if (trap->IsUndefined(isolate)) {
8515  return JSReceiver::PreventExtensions(target, should_throw);
8516  }
8517 
8518  Handle<Object> trap_result;
8519  Handle<Object> args[] = {target};
8520  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8521  isolate, trap_result,
8522  Execution::Call(isolate, trap, handler, arraysize(args), args),
8523  Nothing<bool>());
8524  if (!trap_result->BooleanValue(isolate)) {
8525  RETURN_FAILURE(
8526  isolate, should_throw,
8527  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
8528  }
8529 
8530  // Enforce the invariant.
8531  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
8532  MAYBE_RETURN(target_result, Nothing<bool>());
8533  if (target_result.FromJust()) {
8534  isolate->Throw(*factory->NewTypeError(
8535  MessageTemplate::kProxyPreventExtensionsExtensible));
8536  return Nothing<bool>();
8537  }
8538  return Just(true);
8539 }
8540 
8541 
8542 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
8543  ShouldThrow should_throw) {
8544  Isolate* isolate = object->GetIsolate();
8545 
8546  if (!object->HasSloppyArgumentsElements()) {
8547  return PreventExtensionsWithTransition<NONE>(object, should_throw);
8548  }
8549 
8550  if (object->IsAccessCheckNeeded() &&
8551  !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
8552  isolate->ReportFailedAccessCheck(object);
8553  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
8554  RETURN_FAILURE(isolate, should_throw,
8555  NewTypeError(MessageTemplate::kNoAccess));
8556  }
8557 
8558  if (!object->map()->is_extensible()) return Just(true);
8559 
8560  if (object->IsJSGlobalProxy()) {
8561  PrototypeIterator iter(isolate, object);
8562  if (iter.IsAtEnd()) return Just(true);
8563  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
8564  return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
8565  should_throw);
8566  }
8567 
8568  if (object->map()->has_named_interceptor() ||
8569  object->map()->has_indexed_interceptor()) {
8570  RETURN_FAILURE(isolate, should_throw,
8571  NewTypeError(MessageTemplate::kCannotPreventExt));
8572  }
8573 
8574  if (!object->HasFixedTypedArrayElements()) {
8575  // If there are fast elements we normalize.
8576  Handle<NumberDictionary> dictionary = NormalizeElements(object);
8577  DCHECK(object->HasDictionaryElements() ||
8578  object->HasSlowArgumentsElements());
8579 
8580  // Make sure that we never go back to fast case.
8581  object->RequireSlowElements(*dictionary);
8582  }
8583 
8584  // Do a map transition, other objects with this map may still
8585  // be extensible.
8586  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
8587  Handle<Map> new_map =
8588  Map::Copy(isolate, handle(object->map(), isolate), "PreventExtensions");
8589 
8590  new_map->set_is_extensible(false);
8591  JSObject::MigrateToMap(object, new_map);
8592  DCHECK(!object->map()->is_extensible());
8593 
8594  return Just(true);
8595 }
8596 
8597 
8598 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
8599  if (object->IsJSProxy()) {
8600  return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
8601  }
8602  return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
8603 }
8604 
8605 
8606 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
8607  Isolate* isolate = proxy->GetIsolate();
8608  STACK_CHECK(isolate, Nothing<bool>());
8609  Factory* factory = isolate->factory();
8610  Handle<String> trap_name = factory->isExtensible_string();
8611 
8612  if (proxy->IsRevoked()) {
8613  isolate->Throw(
8614  *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
8615  return Nothing<bool>();
8616  }
8617  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
8618  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
8619 
8620  Handle<Object> trap;
8621  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8622  isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
8623  if (trap->IsUndefined(isolate)) {
8624  return JSReceiver::IsExtensible(target);
8625  }
8626 
8627  Handle<Object> trap_result;
8628  Handle<Object> args[] = {target};
8629  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8630  isolate, trap_result,
8631  Execution::Call(isolate, trap, handler, arraysize(args), args),
8632  Nothing<bool>());
8633 
8634  // Enforce the invariant.
8635  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
8636  MAYBE_RETURN(target_result, Nothing<bool>());
8637  if (target_result.FromJust() != trap_result->BooleanValue(isolate)) {
8638  isolate->Throw(
8639  *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
8640  factory->ToBoolean(target_result.FromJust())));
8641  return Nothing<bool>();
8642  }
8643  return target_result;
8644 }
8645 
8646 
8647 bool JSObject::IsExtensible(Handle<JSObject> object) {
8648  Isolate* isolate = object->GetIsolate();
8649  if (object->IsAccessCheckNeeded() &&
8650  !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
8651  return true;
8652  }
8653  if (object->IsJSGlobalProxy()) {
8654  PrototypeIterator iter(isolate, *object);
8655  if (iter.IsAtEnd()) return false;
8656  DCHECK(iter.GetCurrent()->IsJSGlobalObject());
8657  return iter.GetCurrent<JSObject>()->map()->is_extensible();
8658  }
8659  return object->map()->is_extensible();
8660 }
8661 
8662 namespace {
8663 
8664 template <typename Dictionary>
8665 void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
8666  Handle<Dictionary> dictionary,
8667  const PropertyAttributes attributes) {
8668  int capacity = dictionary->Capacity();
8669  for (int i = 0; i < capacity; i++) {
8670  Object* k;
8671  if (!dictionary->ToKey(roots, i, &k)) continue;
8672  if (k->FilterKey(ALL_PROPERTIES)) continue;
8673  PropertyDetails details = dictionary->DetailsAt(i);
8674  int attrs = attributes;
8675  // READ_ONLY is an invalid attribute for JS setters/getters.
8676  if ((attributes & READ_ONLY) && details.kind() == kAccessor) {
8677  Object* v = dictionary->ValueAt(i);
8678  if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
8679  }
8680  details = details.CopyAddAttributes(static_cast<PropertyAttributes>(attrs));
8681  dictionary->DetailsAtPut(isolate, i, details);
8682  }
8683 }
8684 
8685 } // namespace
8686 
8687 template <PropertyAttributes attrs>
8688 Maybe<bool> JSObject::PreventExtensionsWithTransition(
8689  Handle<JSObject> object, ShouldThrow should_throw) {
8690  STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
8691 
8692  // Sealing/freezing sloppy arguments or namespace objects should be handled
8693  // elsewhere.
8694  DCHECK(!object->HasSloppyArgumentsElements());
8695  DCHECK_IMPLIES(object->IsJSModuleNamespace(), attrs == NONE);
8696 
8697  Isolate* isolate = object->GetIsolate();
8698  if (object->IsAccessCheckNeeded() &&
8699  !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
8700  isolate->ReportFailedAccessCheck(object);
8701  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
8702  RETURN_FAILURE(isolate, should_throw,
8703  NewTypeError(MessageTemplate::kNoAccess));
8704  }
8705 
8706  if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
8707 
8708  if (object->IsJSGlobalProxy()) {
8709  PrototypeIterator iter(isolate, object);
8710  if (iter.IsAtEnd()) return Just(true);
8711  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
8712  return PreventExtensionsWithTransition<attrs>(
8713  PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
8714  }
8715 
8716  if (object->map()->has_named_interceptor() ||
8717  object->map()->has_indexed_interceptor()) {
8718  MessageTemplate message = MessageTemplate::kNone;
8719  switch (attrs) {
8720  case NONE:
8721  message = MessageTemplate::kCannotPreventExt;
8722  break;
8723 
8724  case SEALED:
8725  message = MessageTemplate::kCannotSeal;
8726  break;
8727 
8728  case FROZEN:
8729  message = MessageTemplate::kCannotFreeze;
8730  break;
8731  }
8732  RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
8733  }
8734 
8735  Handle<NumberDictionary> new_element_dictionary;
8736  if (!object->HasFixedTypedArrayElements() &&
8737  !object->HasDictionaryElements() &&
8738  !object->HasSlowStringWrapperElements()) {
8739  int length = object->IsJSArray()
8740  ? Smi::ToInt(Handle<JSArray>::cast(object)->length())
8741  : object->elements()->length();
8742  new_element_dictionary =
8743  length == 0 ? isolate->factory()->empty_slow_element_dictionary()
8744  : object->GetElementsAccessor()->Normalize(object);
8745  }
8746 
8747  Handle<Symbol> transition_marker;
8748  if (attrs == NONE) {
8749  transition_marker = isolate->factory()->nonextensible_symbol();
8750  } else if (attrs == SEALED) {
8751  transition_marker = isolate->factory()->sealed_symbol();
8752  } else {
8753  DCHECK(attrs == FROZEN);
8754  transition_marker = isolate->factory()->frozen_symbol();
8755  }
8756 
8757  Handle<Map> old_map(object->map(), isolate);
8758  TransitionsAccessor transitions(isolate, old_map);
8759  Map transition = transitions.SearchSpecial(*transition_marker);
8760  if (!transition.is_null()) {
8761  Handle<Map> transition_map(transition, isolate);
8762  DCHECK(transition_map->has_dictionary_elements() ||
8763  transition_map->has_fixed_typed_array_elements() ||
8764  transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
8765  DCHECK(!transition_map->is_extensible());
8766  JSObject::MigrateToMap(object, transition_map);
8767  } else if (transitions.CanHaveMoreTransitions()) {
8768  // Create a new descriptor array with the appropriate property attributes
8769  Handle<Map> new_map = Map::CopyForPreventExtensions(
8770  isolate, old_map, attrs, transition_marker, "CopyForPreventExtensions");
8771  JSObject::MigrateToMap(object, new_map);
8772  } else {
8773  DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
8774  // Slow path: need to normalize properties for safety
8775  NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
8776  "SlowPreventExtensions");
8777 
8778  // Create a new map, since other objects with this map may be extensible.
8779  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
8780  Handle<Map> new_map = Map::Copy(isolate, handle(object->map(), isolate),
8781  "SlowCopyForPreventExtensions");
8782  new_map->set_is_extensible(false);
8783  if (!new_element_dictionary.is_null()) {
8784  ElementsKind new_kind =
8785  IsStringWrapperElementsKind(old_map->elements_kind())
8786  ? SLOW_STRING_WRAPPER_ELEMENTS
8787  : DICTIONARY_ELEMENTS;
8788  new_map->set_elements_kind(new_kind);
8789  }
8790  JSObject::MigrateToMap(object, new_map);
8791 
8792  if (attrs != NONE) {
8793  ReadOnlyRoots roots(isolate);
8794  if (object->IsJSGlobalObject()) {
8795  Handle<GlobalDictionary> dictionary(
8796  JSGlobalObject::cast(*object)->global_dictionary(), isolate);
8797  ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
8798  } else {
8799  Handle<NameDictionary> dictionary(object->property_dictionary(),
8800  isolate);
8801  ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
8802  }
8803  }
8804  }
8805 
8806  // Both seal and preventExtensions always go through without modifications to
8807  // typed array elements. Freeze works only if there are no actual elements.
8808  if (object->HasFixedTypedArrayElements()) {
8809  if (attrs == FROZEN &&
8810  JSArrayBufferView::cast(*object)->byte_length() > 0) {
8811  isolate->Throw(*isolate->factory()->NewTypeError(
8812  MessageTemplate::kCannotFreezeArrayBufferView));
8813  return Nothing<bool>();
8814  }
8815  return Just(true);
8816  }
8817 
8818  DCHECK(object->map()->has_dictionary_elements() ||
8819  object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
8820  if (!new_element_dictionary.is_null()) {
8821  object->set_elements(*new_element_dictionary);
8822  }
8823 
8824  if (object->elements() !=
8825  ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
8826  Handle<NumberDictionary> dictionary(object->element_dictionary(), isolate);
8827  // Make sure we never go back to the fast case
8828  object->RequireSlowElements(*dictionary);
8829  if (attrs != NONE) {
8830  ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate), dictionary,
8831  attrs);
8832  }
8833  }
8834 
8835  return Just(true);
8836 }
8837 
8838 
8839 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
8840  Representation representation,
8841  FieldIndex index) {
8842  Isolate* isolate = object->GetIsolate();
8843  if (object->IsUnboxedDoubleField(index)) {
8844  double value = object->RawFastDoublePropertyAt(index);
8845  return isolate->factory()->NewHeapNumber(value);
8846  }
8847  Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
8848  return Object::WrapForRead(isolate, raw_value, representation);
8849 }
8850 
8851 // static
8852 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
8853  ToPrimitiveHint hint) {
8854  Isolate* const isolate = receiver->GetIsolate();
8855  Handle<Object> exotic_to_prim;
8856  ASSIGN_RETURN_ON_EXCEPTION(
8857  isolate, exotic_to_prim,
8858  GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
8859  if (!exotic_to_prim->IsUndefined(isolate)) {
8860  Handle<Object> hint_string =
8861  isolate->factory()->ToPrimitiveHintString(hint);
8862  Handle<Object> result;
8863  ASSIGN_RETURN_ON_EXCEPTION(
8864  isolate, result,
8865  Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
8866  Object);
8867  if (result->IsPrimitive()) return result;
8868  THROW_NEW_ERROR(isolate,
8869  NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8870  Object);
8871  }
8872  return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
8873  ? OrdinaryToPrimitiveHint::kString
8874  : OrdinaryToPrimitiveHint::kNumber);
8875 }
8876 
8877 
8878 // static
8879 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
8880  Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
8881  Isolate* const isolate = receiver->GetIsolate();
8882  Handle<String> method_names[2];
8883  switch (hint) {
8884  case OrdinaryToPrimitiveHint::kNumber:
8885  method_names[0] = isolate->factory()->valueOf_string();
8886  method_names[1] = isolate->factory()->toString_string();
8887  break;
8888  case OrdinaryToPrimitiveHint::kString:
8889  method_names[0] = isolate->factory()->toString_string();
8890  method_names[1] = isolate->factory()->valueOf_string();
8891  break;
8892  }
8893  for (Handle<String> name : method_names) {
8894  Handle<Object> method;
8895  ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
8896  JSReceiver::GetProperty(isolate, receiver, name),
8897  Object);
8898  if (method->IsCallable()) {
8899  Handle<Object> result;
8900  ASSIGN_RETURN_ON_EXCEPTION(
8901  isolate, result,
8902  Execution::Call(isolate, method, receiver, 0, nullptr), Object);
8903  if (result->IsPrimitive()) return result;
8904  }
8905  }
8906  THROW_NEW_ERROR(isolate,
8907  NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8908  Object);
8909 }
8910 
8911 
8912 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
8913 bool JSObject::HasEnumerableElements() {
8914  // TODO(cbruni): cleanup
8915  JSObject* object = this;
8916  switch (object->GetElementsKind()) {
8917  case PACKED_SMI_ELEMENTS:
8918  case PACKED_ELEMENTS:
8919  case PACKED_DOUBLE_ELEMENTS: {
8920  int length = object->IsJSArray()
8921  ? Smi::ToInt(JSArray::cast(object)->length())
8922  : object->elements()->length();
8923  return length > 0;
8924  }
8925  case HOLEY_SMI_ELEMENTS:
8926  case HOLEY_ELEMENTS: {
8927  FixedArray elements = FixedArray::cast(object->elements());
8928  int length = object->IsJSArray()
8929  ? Smi::ToInt(JSArray::cast(object)->length())
8930  : elements->length();
8931  Isolate* isolate = GetIsolate();
8932  for (int i = 0; i < length; i++) {
8933  if (!elements->is_the_hole(isolate, i)) return true;
8934  }
8935  return false;
8936  }
8937  case HOLEY_DOUBLE_ELEMENTS: {
8938  int length = object->IsJSArray()
8939  ? Smi::ToInt(JSArray::cast(object)->length())
8940  : object->elements()->length();
8941  // Zero-length arrays would use the empty FixedArray...
8942  if (length == 0) return false;
8943  // ...so only cast to FixedDoubleArray otherwise.
8944  FixedDoubleArray elements = FixedDoubleArray::cast(object->elements());
8945  for (int i = 0; i < length; i++) {
8946  if (!elements->is_the_hole(i)) return true;
8947  }
8948  return false;
8949  }
8950 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
8951 
8952  TYPED_ARRAYS(TYPED_ARRAY_CASE)
8953 #undef TYPED_ARRAY_CASE
8954  {
8955  int length = object->elements()->length();
8956  return length > 0;
8957  }
8958  case DICTIONARY_ELEMENTS: {
8959  NumberDictionary elements = NumberDictionary::cast(object->elements());
8960  return elements->NumberOfEnumerableProperties() > 0;
8961  }
8962  case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8963  case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8964  // We're approximating non-empty arguments objects here.
8965  return true;
8966  case FAST_STRING_WRAPPER_ELEMENTS:
8967  case SLOW_STRING_WRAPPER_ELEMENTS:
8968  if (String::cast(JSValue::cast(object)->value())->length() > 0) {
8969  return true;
8970  }
8971  return object->elements()->length() > 0;
8972  case NO_ELEMENTS:
8973  return false;
8974  }
8975  UNREACHABLE();
8976 }
8977 
8978 int Map::NumberOfEnumerableProperties() const {
8979  int result = 0;
8980  DescriptorArray* descs = instance_descriptors();
8981  int limit = NumberOfOwnDescriptors();
8982  for (int i = 0; i < limit; i++) {
8983  if ((descs->GetDetails(i).attributes() & ONLY_ENUMERABLE) == 0 &&
8984  !descs->GetKey(i)->FilterKey(ENUMERABLE_STRINGS)) {
8985  result++;
8986  }
8987  }
8988  return result;
8989 }
8990 
8991 int Map::NextFreePropertyIndex() const {
8992  int free_index = 0;
8993  int number_of_own_descriptors = NumberOfOwnDescriptors();
8994  DescriptorArray* descs = instance_descriptors();
8995  for (int i = 0; i < number_of_own_descriptors; i++) {
8996  PropertyDetails details = descs->GetDetails(i);
8997  if (details.location() == kField) {
8998  int candidate = details.field_index() + details.field_width_in_words();
8999  if (candidate > free_index) free_index = candidate;
9000  }
9001  }
9002  return free_index;
9003 }
9004 
9005 bool Map::OnlyHasSimpleProperties() const {
9006  // Wrapped string elements aren't explicitly stored in the elements backing
9007  // store, but are loaded indirectly from the underlying string.
9008  return !IsStringWrapperElementsKind(elements_kind()) &&
9009  !IsSpecialReceiverMap() && !has_hidden_prototype() &&
9010  !is_dictionary_map();
9011 }
9012 
9013 V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
9014  Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
9015  Handle<FixedArray>* result) {
9016  Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
9017 
9018  if (!map->IsJSObjectMap()) return Just(false);
9019  if (!map->OnlyHasSimpleProperties()) return Just(false);
9020 
9021  Handle<JSObject> object(JSObject::cast(*receiver), isolate);
9022 
9023  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9024  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9025  int number_of_own_elements =
9026  object->GetElementsAccessor()->GetCapacity(*object, object->elements());
9027  Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
9028  number_of_own_descriptors + number_of_own_elements);
9029  int count = 0;
9030 
9031  if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
9032  MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
9033  isolate, object, values_or_entries, get_entries, &count,
9034  ENUMERABLE_STRINGS),
9035  Nothing<bool>());
9036  }
9037 
9038  bool stable = object->map() == *map;
9039 
9040  for (int index = 0; index < number_of_own_descriptors; index++) {
9041  Handle<Name> next_key(descriptors->GetKey(index), isolate);
9042  if (!next_key->IsString()) continue;
9043  Handle<Object> prop_value;
9044 
9045  // Directly decode from the descriptor array if |from| did not change shape.
9046  if (stable) {
9047  PropertyDetails details = descriptors->GetDetails(index);
9048  if (!details.IsEnumerable()) continue;
9049  if (details.kind() == kData) {
9050  if (details.location() == kDescriptor) {
9051  prop_value = handle(descriptors->GetStrongValue(index), isolate);
9052  } else {
9053  Representation representation = details.representation();
9054  FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
9055  prop_value =
9056  JSObject::FastPropertyAt(object, representation, field_index);
9057  }
9058  } else {
9059  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9060  isolate, prop_value,
9061  JSReceiver::GetProperty(isolate, object, next_key),
9062  Nothing<bool>());
9063  stable = object->map() == *map;
9064  }
9065  } else {
9066  // If the map did change, do a slower lookup. We are still guaranteed that
9067  // the object has a simple shape, and that the key is a name.
9068  LookupIterator it(isolate, object, next_key,
9069  LookupIterator::OWN_SKIP_INTERCEPTOR);
9070  if (!it.IsFound()) continue;
9071  DCHECK(it.state() == LookupIterator::DATA ||
9072  it.state() == LookupIterator::ACCESSOR);
9073  if (!it.IsEnumerable()) continue;
9074  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9075  isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
9076  }
9077 
9078  if (get_entries) {
9079  prop_value = MakeEntryPair(isolate, next_key, prop_value);
9080  }
9081 
9082  values_or_entries->set(count, *prop_value);
9083  count++;
9084  }
9085 
9086  DCHECK_LE(count, values_or_entries->length());
9087  *result = FixedArray::ShrinkOrEmpty(isolate, values_or_entries, count);
9088  return Just(true);
9089 }
9090 
9091 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
9092  Handle<JSReceiver> object,
9093  PropertyFilter filter,
9094  bool try_fast_path,
9095  bool get_entries) {
9096  Handle<FixedArray> values_or_entries;
9097  if (try_fast_path && filter == ENUMERABLE_STRINGS) {
9098  Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
9099  isolate, object, get_entries, &values_or_entries);
9100  if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
9101  if (fast_values_or_entries.FromJust()) return values_or_entries;
9102  }
9103 
9104  PropertyFilter key_filter =
9105  static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
9106 
9107  Handle<FixedArray> keys;
9108  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9109  isolate, keys,
9110  KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
9111  GetKeysConversion::kConvertToString),
9112  MaybeHandle<FixedArray>());
9113 
9114  values_or_entries = isolate->factory()->NewFixedArray(keys->length());
9115  int length = 0;
9116 
9117  for (int i = 0; i < keys->length(); ++i) {
9118  Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
9119 
9120  if (filter & ONLY_ENUMERABLE) {
9121  PropertyDescriptor descriptor;
9122  Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
9123  isolate, object, key, &descriptor);
9124  MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
9125  if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
9126  }
9127 
9128  Handle<Object> value;
9129  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9130  isolate, value, JSReceiver::GetPropertyOrElement(isolate, object, key),
9131  MaybeHandle<FixedArray>());
9132 
9133  if (get_entries) {
9134  Handle<FixedArray> entry_storage =
9135  isolate->factory()->NewUninitializedFixedArray(2);
9136  entry_storage->set(0, *key);
9137  entry_storage->set(1, *value);
9138  value = isolate->factory()->NewJSArrayWithElements(entry_storage,
9139  PACKED_ELEMENTS, 2);
9140  }
9141 
9142  values_or_entries->set(length, *value);
9143  length++;
9144  }
9145  DCHECK_LE(length, values_or_entries->length());
9146  return FixedArray::ShrinkOrEmpty(isolate, values_or_entries, length);
9147 }
9148 
9149 MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
9150  PropertyFilter filter,
9151  bool try_fast_path) {
9152  return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
9153  try_fast_path, false);
9154 }
9155 
9156 MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
9157  PropertyFilter filter,
9158  bool try_fast_path) {
9159  return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
9160  try_fast_path, true);
9161 }
9162 
9163 Handle<FixedArray> JSReceiver::GetOwnElementIndices(Isolate* isolate,
9164  Handle<JSReceiver> receiver,
9165  Handle<JSObject> object) {
9166  KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
9167  ALL_PROPERTIES);
9168  accumulator.CollectOwnElementIndices(receiver, object);
9169  Handle<FixedArray> keys =
9170  accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
9171  DCHECK(keys->ContainsSortedNumbers());
9172  return keys;
9173 }
9174 
9175 bool Map::DictionaryElementsInPrototypeChainOnly(Isolate* isolate) {
9176  if (IsDictionaryElementsKind(elements_kind())) {
9177  return false;
9178  }
9179 
9180  for (PrototypeIterator iter(isolate, *this); !iter.IsAtEnd();
9181  iter.Advance()) {
9182  // Be conservative, don't walk into proxies.
9183  if (iter.GetCurrent()->IsJSProxy()) return true;
9184  // String wrappers have non-configurable, non-writable elements.
9185  if (iter.GetCurrent()->IsStringWrapper()) return true;
9186  JSObject* current = iter.GetCurrent<JSObject>();
9187 
9188  if (current->HasDictionaryElements() &&
9189  current->element_dictionary()->requires_slow_elements()) {
9190  return true;
9191  }
9192 
9193  if (current->HasSlowArgumentsElements()) {
9194  FixedArray parameter_map = FixedArray::cast(current->elements());
9195  Object* arguments = parameter_map->get(1);
9196  if (NumberDictionary::cast(arguments)->requires_slow_elements()) {
9197  return true;
9198  }
9199  }
9200  }
9201 
9202  return false;
9203 }
9204 
9205 
9206 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
9207  Handle<Name> name,
9208  Handle<Object> getter,
9209  Handle<Object> setter,
9210  PropertyAttributes attributes) {
9211  Isolate* isolate = object->GetIsolate();
9212 
9213  LookupIterator it = LookupIterator::PropertyOrElement(
9214  isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
9215  return DefineAccessor(&it, getter, setter, attributes);
9216 }
9217 
9218 
9219 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
9220  Handle<Object> getter,
9221  Handle<Object> setter,
9222  PropertyAttributes attributes) {
9223  Isolate* isolate = it->isolate();
9224 
9225  it->UpdateProtector();
9226 
9227  if (it->state() == LookupIterator::ACCESS_CHECK) {
9228  if (!it->HasAccess()) {
9229  isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
9230  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9231  return isolate->factory()->undefined_value();
9232  }
9233  it->Next();
9234  }
9235 
9236  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
9237  // Ignore accessors on typed arrays.
9238  if (it->IsElement() && object->HasFixedTypedArrayElements()) {
9239  return it->factory()->undefined_value();
9240  }
9241 
9242  DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
9243  getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
9244  DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
9245  setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
9246  it->TransitionToAccessorProperty(getter, setter, attributes);
9247 
9248  return isolate->factory()->undefined_value();
9249 }
9250 
9251 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
9252  Handle<Name> name,
9253  Handle<AccessorInfo> info,
9254  PropertyAttributes attributes) {
9255  Isolate* isolate = object->GetIsolate();
9256 
9257  LookupIterator it = LookupIterator::PropertyOrElement(
9258  isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
9259 
9260  // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
9261  // the FailedAccessCheckCallbackFunction doesn't throw an exception.
9262  //
9263  // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
9264  // remove reliance on default return values.
9265  if (it.state() == LookupIterator::ACCESS_CHECK) {
9266  if (!it.HasAccess()) {
9267  isolate->ReportFailedAccessCheck(object);
9268  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9269  return it.factory()->undefined_value();
9270  }
9271  it.Next();
9272  }
9273 
9274  // Ignore accessors on typed arrays.
9275  if (it.IsElement() && object->HasFixedTypedArrayElements()) {
9276  return it.factory()->undefined_value();
9277  }
9278 
9279  CHECK(GetPropertyAttributes(&it).IsJust());
9280 
9281  // ES5 forbids turning a property into an accessor if it's not
9282  // configurable. See 8.6.1 (Table 5).
9283  if (it.IsFound() && !it.IsConfigurable()) {
9284  return it.factory()->undefined_value();
9285  }
9286 
9287  it.TransitionToAccessorPair(info, attributes);
9288 
9289  return object;
9290 }
9291 
9292 Object* JSObject::SlowReverseLookup(Object* value) {
9293  if (HasFastProperties()) {
9294  int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
9295  DescriptorArray* descs = map()->instance_descriptors();
9296  bool value_is_number = value->IsNumber();
9297  for (int i = 0; i < number_of_own_descriptors; i++) {
9298  PropertyDetails details = descs->GetDetails(i);
9299  if (details.location() == kField) {
9300  DCHECK_EQ(kData, details.kind());
9301  FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
9302  if (IsUnboxedDoubleField(field_index)) {
9303  if (value_is_number) {
9304  double property = RawFastDoublePropertyAt(field_index);
9305  if (property == value->Number()) {
9306  return descs->GetKey(i);
9307  }
9308  }
9309  } else {
9310  Object* property = RawFastPropertyAt(field_index);
9311  if (field_index.is_double()) {
9312  DCHECK(property->IsMutableHeapNumber());
9313  if (value_is_number && property->Number() == value->Number()) {
9314  return descs->GetKey(i);
9315  }
9316  } else if (property == value) {
9317  return descs->GetKey(i);
9318  }
9319  }
9320  } else {
9321  DCHECK_EQ(kDescriptor, details.location());
9322  if (details.kind() == kData) {
9323  if (descs->GetStrongValue(i) == value) {
9324  return descs->GetKey(i);
9325  }
9326  }
9327  }
9328  }
9329  return GetReadOnlyRoots().undefined_value();
9330  } else if (IsJSGlobalObject()) {
9331  return JSGlobalObject::cast(this)->global_dictionary()->SlowReverseLookup(
9332  value);
9333  } else {
9334  return property_dictionary()->SlowReverseLookup(value);
9335  }
9336 }
9337 
9338 Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map, int instance_size,
9339  int inobject_properties) {
9340  Handle<Map> result = isolate->factory()->NewMap(
9341  map->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND,
9342  inobject_properties);
9343  Handle<Object> prototype(map->prototype(), isolate);
9344  Map::SetPrototype(isolate, result, prototype);
9345  result->set_constructor_or_backpointer(map->GetConstructor());
9346  result->set_bit_field(map->bit_field());
9347  result->set_bit_field2(map->bit_field2());
9348  int new_bit_field3 = map->bit_field3();
9349  new_bit_field3 = OwnsDescriptorsBit::update(new_bit_field3, true);
9350  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
9351  new_bit_field3 = EnumLengthBits::update(new_bit_field3,
9352  kInvalidEnumCacheSentinel);
9353  new_bit_field3 = IsDeprecatedBit::update(new_bit_field3, false);
9354  if (!map->is_dictionary_map()) {
9355  new_bit_field3 = IsUnstableBit::update(new_bit_field3, false);
9356  }
9357  result->set_bit_field3(new_bit_field3);
9358  return result;
9359 }
9360 
9361 Handle<Map> Map::Normalize(Isolate* isolate, Handle<Map> fast_map,
9362  PropertyNormalizationMode mode, const char* reason) {
9363  DCHECK(!fast_map->is_dictionary_map());
9364 
9365  Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
9366  isolate);
9367  bool use_cache =
9368  !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
9369  Handle<NormalizedMapCache> cache;
9370  if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
9371 
9372  Handle<Map> new_map;
9373  if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
9374 #ifdef VERIFY_HEAP
9375  if (FLAG_verify_heap) new_map->DictionaryMapVerify(isolate);
9376 #endif
9377 #ifdef ENABLE_SLOW_DCHECKS
9378  if (FLAG_enable_slow_asserts) {
9379  // The cached map should match newly created normalized map bit-by-bit,
9380  // except for the code cache, which can contain some ICs which can be
9381  // applied to the shared map, dependent code and weak cell cache.
9382  Handle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);
9383 
9384  if (new_map->is_prototype_map()) {
9385  // For prototype maps, the PrototypeInfo is not copied.
9386  DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
9387  reinterpret_cast<void*>(new_map->address()),
9388  kTransitionsOrPrototypeInfoOffset));
9389  DCHECK_EQ(fresh->raw_transitions(),
9390  MaybeObject::FromObject(Smi::kZero));
9391  STATIC_ASSERT(kDescriptorsOffset ==
9392  kTransitionsOrPrototypeInfoOffset + kPointerSize);
9393  DCHECK_EQ(
9394  0,
9395  memcmp(
9396  HeapObject::RawField(*fresh, kDescriptorsOffset).ToVoidPtr(),
9397  HeapObject::RawField(*new_map, kDescriptorsOffset).ToVoidPtr(),
9398  kDependentCodeOffset - kDescriptorsOffset));
9399  } else {
9400  DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
9401  reinterpret_cast<void*>(new_map->address()),
9402  Map::kDependentCodeOffset));
9403  }
9404  STATIC_ASSERT(Map::kPrototypeValidityCellOffset ==
9405  Map::kDependentCodeOffset + kPointerSize);
9406  int offset = Map::kPrototypeValidityCellOffset + kPointerSize;
9407  DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
9408  reinterpret_cast<void*>(new_map->address() + offset),
9409  Map::kSize - offset));
9410  }
9411 #endif
9412  } else {
9413  new_map = Map::CopyNormalized(isolate, fast_map, mode);
9414  if (use_cache) {
9415  cache->Set(fast_map, new_map);
9416  isolate->counters()->maps_normalized()->Increment();
9417  }
9418  if (FLAG_trace_maps) {
9419  LOG(isolate, MapEvent("Normalize", *fast_map, *new_map, reason));
9420  }
9421  }
9422  fast_map->NotifyLeafMapLayoutChange(isolate);
9423  return new_map;
9424 }
9425 
9426 Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,
9427  PropertyNormalizationMode mode) {
9428  int new_instance_size = map->instance_size();
9429  if (mode == CLEAR_INOBJECT_PROPERTIES) {
9430  new_instance_size -= map->GetInObjectProperties() * kPointerSize;
9431  }
9432 
9433  Handle<Map> result = RawCopy(
9434  isolate, map, new_instance_size,
9435  mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
9436  // Clear the unused_property_fields explicitly as this field should not
9437  // be accessed for normalized maps.
9438  result->SetInObjectUnusedPropertyFields(0);
9439  result->set_is_dictionary_map(true);
9440  result->set_is_migration_target(false);
9441  result->set_may_have_interesting_symbols(true);
9442  result->set_construction_counter(kNoSlackTracking);
9443 
9444 #ifdef VERIFY_HEAP
9445  if (FLAG_verify_heap) result->DictionaryMapVerify(isolate);
9446 #endif
9447 
9448  return result;
9449 }
9450 
9451 // Return an immutable prototype exotic object version of the input map.
9452 // Never even try to cache it in the transition tree, as it is intended
9453 // for the global object and its prototype chain, and excluding it saves
9454 // memory on the map transition tree.
9455 
9456 // static
9457 Handle<Map> Map::TransitionToImmutableProto(Isolate* isolate, Handle<Map> map) {
9458  Handle<Map> new_map = Map::Copy(isolate, map, "ImmutablePrototype");
9459  new_map->set_is_immutable_proto(true);
9460  return new_map;
9461 }
9462 
9463 namespace {
9464 void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
9465 #ifdef DEBUG
9466  // Strict function maps have Function as a constructor but the
9467  // Function's initial map is a sloppy function map. Same holds for
9468  // GeneratorFunction / AsyncFunction and its initial map.
9469  Object* constructor = map->GetConstructor();
9470  DCHECK(constructor->IsJSFunction());
9471  DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
9472  *map == *isolate->strict_function_map() ||
9473  *map == *isolate->strict_function_with_name_map() ||
9474  *map == *isolate->generator_function_map() ||
9475  *map == *isolate->generator_function_with_name_map() ||
9476  *map == *isolate->generator_function_with_home_object_map() ||
9477  *map == *isolate->generator_function_with_name_and_home_object_map() ||
9478  *map == *isolate->async_function_map() ||
9479  *map == *isolate->async_function_with_name_map() ||
9480  *map == *isolate->async_function_with_home_object_map() ||
9481  *map == *isolate->async_function_with_name_and_home_object_map());
9482 #endif
9483  // Initial maps must always own their descriptors and it's descriptor array
9484  // does not contain descriptors that do not belong to the map.
9485  DCHECK(map->owns_descriptors());
9486  DCHECK_EQ(map->NumberOfOwnDescriptors(),
9487  map->instance_descriptors()->number_of_descriptors());
9488 }
9489 } // namespace
9490 
9491 // static
9492 Handle<Map> Map::CopyInitialMapNormalized(Isolate* isolate, Handle<Map> map,
9493  PropertyNormalizationMode mode) {
9494  EnsureInitialMap(isolate, map);
9495  return CopyNormalized(isolate, map, mode);
9496 }
9497 
9498 // static
9499 Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
9500  int instance_size, int inobject_properties,
9501  int unused_property_fields) {
9502  EnsureInitialMap(isolate, map);
9503  Handle<Map> result =
9504  RawCopy(isolate, map, instance_size, inobject_properties);
9505 
9506  // Please note instance_type and instance_size are set when allocated.
9507  result->SetInObjectUnusedPropertyFields(unused_property_fields);
9508 
9509  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9510  if (number_of_own_descriptors > 0) {
9511  // The copy will use the same descriptors array.
9512  result->UpdateDescriptors(map->instance_descriptors(),
9513  map->GetLayoutDescriptor());
9514  result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
9515 
9516  DCHECK_EQ(result->NumberOfFields(),
9517  result->GetInObjectProperties() - result->UnusedPropertyFields());
9518  }
9519 
9520  return result;
9521 }
9522 
9523 Handle<Map> Map::CopyDropDescriptors(Isolate* isolate, Handle<Map> map) {
9524  Handle<Map> result =
9525  RawCopy(isolate, map, map->instance_size(),
9526  map->IsJSObjectMap() ? map->GetInObjectProperties() : 0);
9527 
9528  // Please note instance_type and instance_size are set when allocated.
9529  if (map->IsJSObjectMap()) {
9530  result->CopyUnusedPropertyFields(*map);
9531  }
9532  map->NotifyLeafMapLayoutChange(isolate);
9533  return result;
9534 }
9535 
9536 Handle<Map> Map::ShareDescriptor(Isolate* isolate, Handle<Map> map,
9537  Handle<DescriptorArray> descriptors,
9538  Descriptor* descriptor) {
9539  // Sanity check. This path is only to be taken if the map owns its descriptor
9540  // array, implying that its NumberOfOwnDescriptors equals the number of
9541  // descriptors in the descriptor array.
9542  DCHECK_EQ(map->NumberOfOwnDescriptors(),
9543  map->instance_descriptors()->number_of_descriptors());
9544 
9545  Handle<Map> result = CopyDropDescriptors(isolate, map);
9546  Handle<Name> name = descriptor->GetKey();
9547 
9548  // Properly mark the {result} if the {name} is an "interesting symbol".
9549  if (name->IsInterestingSymbol()) {
9550  result->set_may_have_interesting_symbols(true);
9551  }
9552 
9553  // Ensure there's space for the new descriptor in the shared descriptor array.
9554  if (descriptors->number_of_slack_descriptors() == 0) {
9555  int old_size = descriptors->number_of_descriptors();
9556  if (old_size == 0) {
9557  descriptors = DescriptorArray::Allocate(isolate, 0, 1);
9558  } else {
9559  int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
9560  EnsureDescriptorSlack(isolate, map, slack);
9561  descriptors = handle(map->instance_descriptors(), isolate);
9562  }
9563  }
9564 
9565  Handle<LayoutDescriptor> layout_descriptor =
9566  FLAG_unbox_double_fields
9567  ? LayoutDescriptor::ShareAppend(isolate, map,
9568  descriptor->GetDetails())
9569  : handle(LayoutDescriptor::FastPointerLayout(), isolate);
9570 
9571  {
9572  DisallowHeapAllocation no_gc;
9573  descriptors->Append(descriptor);
9574  result->InitializeDescriptors(*descriptors, *layout_descriptor);
9575  }
9576 
9577  DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
9578  ConnectTransition(isolate, map, result, name, SIMPLE_PROPERTY_TRANSITION);
9579 
9580  return result;
9581 }
9582 
9583 void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
9584  Handle<Map> child, Handle<Name> name,
9585  SimpleTransitionFlag flag) {
9586  DCHECK_IMPLIES(name->IsInterestingSymbol(),
9587  child->may_have_interesting_symbols());
9588  DCHECK_IMPLIES(parent->may_have_interesting_symbols(),
9589  child->may_have_interesting_symbols());
9590  // Do not track transitions during bootstrap except for element transitions.
9591  if (isolate->bootstrapper()->IsActive() &&
9592  !name.is_identical_to(isolate->factory()->elements_transition_symbol())) {
9593  if (FLAG_trace_maps) {
9594  LOG(isolate,
9595  MapEvent("Transition", *parent, *child,
9596  child->is_prototype_map() ? "prototype" : "", *name));
9597  }
9598  return;
9599  }
9600  if (!parent->GetBackPointer()->IsUndefined(isolate)) {
9601  parent->set_owns_descriptors(false);
9602  } else {
9603  // |parent| is initial map and it must keep the ownership, there must be no
9604  // descriptors in the descriptors array that do not belong to the map.
9605  DCHECK(parent->owns_descriptors());
9606  DCHECK_EQ(parent->NumberOfOwnDescriptors(),
9607  parent->instance_descriptors()->number_of_descriptors());
9608  }
9609  if (parent->is_prototype_map()) {
9610  DCHECK(child->is_prototype_map());
9611  if (FLAG_trace_maps) {
9612  LOG(isolate, MapEvent("Transition", *parent, *child, "prototype", *name));
9613  }
9614  } else {
9615  TransitionsAccessor(isolate, parent).Insert(name, child, flag);
9616  if (FLAG_trace_maps) {
9617  LOG(isolate, MapEvent("Transition", *parent, *child, "", *name));
9618  }
9619  }
9620 }
9621 
9622 Handle<Map> Map::CopyReplaceDescriptors(
9623  Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
9624  Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
9625  MaybeHandle<Name> maybe_name, const char* reason,
9626  SimpleTransitionFlag simple_flag) {
9627  DCHECK(descriptors->IsSortedNoDuplicates());
9628 
9629  Handle<Map> result = CopyDropDescriptors(isolate, map);
9630 
9631  // Properly mark the {result} if the {name} is an "interesting symbol".
9632  Handle<Name> name;
9633  if (maybe_name.ToHandle(&name) && name->IsInterestingSymbol()) {
9634  result->set_may_have_interesting_symbols(true);
9635  }
9636 
9637  if (!map->is_prototype_map()) {
9638  if (flag == INSERT_TRANSITION &&
9639  TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
9640  result->InitializeDescriptors(*descriptors, *layout_descriptor);
9641 
9642  DCHECK(!maybe_name.is_null());
9643  ConnectTransition(isolate, map, result, name, simple_flag);
9644  } else {
9645  descriptors->GeneralizeAllFields();
9646  result->InitializeDescriptors(*descriptors,
9647  LayoutDescriptor::FastPointerLayout());
9648  }
9649  } else {
9650  result->InitializeDescriptors(*descriptors, *layout_descriptor);
9651  }
9652  if (FLAG_trace_maps &&
9653  // Mirror conditions above that did not call ConnectTransition().
9654  (map->is_prototype_map() ||
9655  !(flag == INSERT_TRANSITION &&
9656  TransitionsAccessor(isolate, map).CanHaveMoreTransitions()))) {
9657  LOG(isolate, MapEvent("ReplaceDescriptors", *map, *result, reason,
9658  maybe_name.is_null() ? Name() : *name));
9659  }
9660  return result;
9661 }
9662 
9663 
9664 // Creates transition tree starting from |split_map| and adding all descriptors
9665 // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
9666 // The way how it is done is tricky because of GC and special descriptors
9667 // marking logic.
9668 Handle<Map> Map::AddMissingTransitions(
9669  Isolate* isolate, Handle<Map> split_map,
9670  Handle<DescriptorArray> descriptors,
9671  Handle<LayoutDescriptor> full_layout_descriptor) {
9672  DCHECK(descriptors->IsSortedNoDuplicates());
9673  int split_nof = split_map->NumberOfOwnDescriptors();
9674  int nof_descriptors = descriptors->number_of_descriptors();
9675  DCHECK_LT(split_nof, nof_descriptors);
9676 
9677  // Start with creating last map which will own full descriptors array.
9678  // This is necessary to guarantee that GC will mark the whole descriptor
9679  // array if any of the allocations happening below fail.
9680  // Number of unused properties is temporarily incorrect and the layout
9681  // descriptor could unnecessarily be in slow mode but we will fix after
9682  // all the other intermediate maps are created.
9683  // Also the last map might have interesting symbols, we temporarily set
9684  // the flag and clear it right before the descriptors are installed. This
9685  // makes heap verification happy and ensures the flag ends up accurate.
9686  Handle<Map> last_map = CopyDropDescriptors(isolate, split_map);
9687  last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
9688  last_map->SetInObjectUnusedPropertyFields(0);
9689  last_map->set_may_have_interesting_symbols(true);
9690 
9691  // During creation of intermediate maps we violate descriptors sharing
9692  // invariant since the last map is not yet connected to the transition tree
9693  // we create here. But it is safe because GC never trims map's descriptors
9694  // if there are no dead transitions from that map and this is exactly the
9695  // case for all the intermediate maps we create here.
9696  Handle<Map> map = split_map;
9697  for (int i = split_nof; i < nof_descriptors - 1; ++i) {
9698  Handle<Map> new_map = CopyDropDescriptors(isolate, map);
9699  InstallDescriptors(isolate, map, new_map, i, descriptors,
9700  full_layout_descriptor);
9701 
9702  map = new_map;
9703  }
9704  map->NotifyLeafMapLayoutChange(isolate);
9705  last_map->set_may_have_interesting_symbols(false);
9706  InstallDescriptors(isolate, map, last_map, nof_descriptors - 1, descriptors,
9707  full_layout_descriptor);
9708  return last_map;
9709 }
9710 
9711 
9712 // Since this method is used to rewrite an existing transition tree, it can
9713 // always insert transitions without checking.
9714 void Map::InstallDescriptors(Isolate* isolate, Handle<Map> parent,
9715  Handle<Map> child, int new_descriptor,
9716  Handle<DescriptorArray> descriptors,
9717  Handle<LayoutDescriptor> full_layout_descriptor) {
9718  DCHECK(descriptors->IsSortedNoDuplicates());
9719 
9720  child->set_instance_descriptors(*descriptors);
9721  child->SetNumberOfOwnDescriptors(new_descriptor + 1);
9722  child->CopyUnusedPropertyFields(*parent);
9723  PropertyDetails details = descriptors->GetDetails(new_descriptor);
9724  if (details.location() == kField) {
9725  child->AccountAddedPropertyField();
9726  }
9727 
9728  if (FLAG_unbox_double_fields) {
9729  Handle<LayoutDescriptor> layout_descriptor =
9730  LayoutDescriptor::AppendIfFastOrUseFull(isolate, parent, details,
9731  full_layout_descriptor);
9732  child->set_layout_descriptor(*layout_descriptor);
9733 #ifdef VERIFY_HEAP
9734  // TODO(ishell): remove these checks from VERIFY_HEAP mode.
9735  if (FLAG_verify_heap) {
9736  CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9737  }
9738 #else
9739  SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9740 #endif
9741  child->set_visitor_id(Map::GetVisitorId(*child));
9742  }
9743 
9744  Handle<Name> name = handle(descriptors->GetKey(new_descriptor), isolate);
9745  if (parent->may_have_interesting_symbols() || name->IsInterestingSymbol()) {
9746  child->set_may_have_interesting_symbols(true);
9747  }
9748  ConnectTransition(isolate, parent, child, name, SIMPLE_PROPERTY_TRANSITION);
9749 }
9750 
9751 Handle<Map> Map::CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
9752  ElementsKind kind, TransitionFlag flag) {
9753  // Only certain objects are allowed to have non-terminal fast transitional
9754  // elements kinds.
9755  DCHECK(map->IsJSObjectMap());
9756  DCHECK_IMPLIES(
9757  !map->CanHaveFastTransitionableElementsKind(),
9758  IsDictionaryElementsKind(kind) || IsTerminalElementsKind(kind));
9759 
9760  Map maybe_elements_transition_map;
9761  if (flag == INSERT_TRANSITION) {
9762  // Ensure we are requested to add elements kind transition "near the root".
9763  DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
9764  map->NumberOfOwnDescriptors());
9765 
9766  maybe_elements_transition_map = map->ElementsTransitionMap();
9767  DCHECK(maybe_elements_transition_map.is_null() ||
9768  (maybe_elements_transition_map->elements_kind() ==
9769  DICTIONARY_ELEMENTS &&
9770  kind == DICTIONARY_ELEMENTS));
9771  DCHECK(!IsFastElementsKind(kind) ||
9772  IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
9773  DCHECK(kind != map->elements_kind());
9774  }
9775 
9776  bool insert_transition =
9777  flag == INSERT_TRANSITION &&
9778  TransitionsAccessor(isolate, map).CanHaveMoreTransitions() &&
9779  maybe_elements_transition_map.is_null();
9780 
9781  if (insert_transition) {
9782  Handle<Map> new_map = CopyForElementsTransition(isolate, map);
9783  new_map->set_elements_kind(kind);
9784 
9785  Handle<Name> name = isolate->factory()->elements_transition_symbol();
9786  ConnectTransition(isolate, map, new_map, name, SPECIAL_TRANSITION);
9787  return new_map;
9788  }
9789 
9790  // Create a new free-floating map only if we are not allowed to store it.
9791  Handle<Map> new_map = Copy(isolate, map, "CopyAsElementsKind");
9792  new_map->set_elements_kind(kind);
9793  return new_map;
9794 }
9795 
9796 Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
9797  Handle<SharedFunctionInfo> shared_info) {
9798  DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
9799  // Initial map for sloppy mode function is stored in the function
9800  // constructor. Initial maps for strict mode are cached as special transitions
9801  // using |strict_function_transition_symbol| as a key.
9802  if (is_sloppy(shared_info->language_mode())) return initial_map;
9803 
9804  Handle<Map> function_map(Map::cast(isolate->native_context()->get(
9805  shared_info->function_map_index())),
9806  isolate);
9807 
9808  STATIC_ASSERT(LanguageModeSize == 2);
9809  DCHECK_EQ(LanguageMode::kStrict, shared_info->language_mode());
9810  Handle<Symbol> transition_symbol =
9811  isolate->factory()->strict_function_transition_symbol();
9812  Map maybe_transition = TransitionsAccessor(isolate, initial_map)
9813  .SearchSpecial(*transition_symbol);
9814  if (!maybe_transition.is_null()) {
9815  return handle(maybe_transition, isolate);
9816  }
9817  initial_map->NotifyLeafMapLayoutChange(isolate);
9818 
9819  // Create new map taking descriptors from the |function_map| and all
9820  // the other details from the |initial_map|.
9821  Handle<Map> map =
9822  Map::CopyInitialMap(isolate, function_map, initial_map->instance_size(),
9823  initial_map->GetInObjectProperties(),
9824  initial_map->UnusedPropertyFields());
9825  map->SetConstructor(initial_map->GetConstructor());
9826  map->set_prototype(initial_map->prototype());
9827  map->set_construction_counter(initial_map->construction_counter());
9828 
9829  if (TransitionsAccessor(isolate, initial_map).CanHaveMoreTransitions()) {
9830  Map::ConnectTransition(isolate, initial_map, map, transition_symbol,
9831  SPECIAL_TRANSITION);
9832  }
9833  return map;
9834 }
9835 
9836 Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
9837  DCHECK(!map->is_prototype_map());
9838  Handle<Map> new_map = CopyDropDescriptors(isolate, map);
9839 
9840  if (map->owns_descriptors()) {
9841  // In case the map owned its own descriptors, share the descriptors and
9842  // transfer ownership to the new map.
9843  // The properties did not change, so reuse descriptors.
9844  new_map->InitializeDescriptors(map->instance_descriptors(),
9845  map->GetLayoutDescriptor());
9846  } else {
9847  // In case the map did not own its own descriptors, a split is forced by
9848  // copying the map; creating a new descriptor array cell.
9849  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9850  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9851  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
9852  isolate, descriptors, number_of_own_descriptors);
9853  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9854  isolate);
9855  new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
9856  }
9857  return new_map;
9858 }
9859 
9860 Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map, const char* reason) {
9861  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
9862  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9863  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
9864  isolate, descriptors, number_of_own_descriptors);
9865  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9866  isolate);
9867  return CopyReplaceDescriptors(
9868  isolate, map, new_descriptors, new_layout_descriptor, OMIT_TRANSITION,
9869  MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
9870 }
9871 
9872 
9873 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
9874  Handle<Map> copy =
9875  Copy(isolate, handle(isolate->object_function()->initial_map(), isolate),
9876  "MapCreate");
9877 
9878  // Check that we do not overflow the instance size when adding the extra
9879  // inobject properties. If the instance size overflows, we allocate as many
9880  // properties as we can as inobject properties.
9881  if (inobject_properties > JSObject::kMaxInObjectProperties) {
9882  inobject_properties = JSObject::kMaxInObjectProperties;
9883  }
9884 
9885  int new_instance_size =
9886  JSObject::kHeaderSize + kPointerSize * inobject_properties;
9887 
9888  // Adjust the map with the extra inobject properties.
9889  copy->set_instance_size(new_instance_size);
9890  copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kPointerSize);
9891  DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties);
9892  copy->SetInObjectUnusedPropertyFields(inobject_properties);
9893  copy->set_visitor_id(Map::GetVisitorId(*copy));
9894  return copy;
9895 }
9896 
9897 Handle<Map> Map::CopyForPreventExtensions(Isolate* isolate, Handle<Map> map,
9898  PropertyAttributes attrs_to_add,
9899  Handle<Symbol> transition_marker,
9900  const char* reason) {
9901  int num_descriptors = map->NumberOfOwnDescriptors();
9902  Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
9903  isolate, handle(map->instance_descriptors(), isolate), num_descriptors,
9904  attrs_to_add);
9905  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9906  isolate);
9907  Handle<Map> new_map = CopyReplaceDescriptors(
9908  isolate, map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
9909  transition_marker, reason, SPECIAL_TRANSITION);
9910  new_map->set_is_extensible(false);
9911  if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
9912  ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
9913  ? SLOW_STRING_WRAPPER_ELEMENTS
9914  : DICTIONARY_ELEMENTS;
9915  new_map->set_elements_kind(new_kind);
9916  }
9917  return new_map;
9918 }
9919 
9920 namespace {
9921 
9922 bool CanHoldValue(DescriptorArray* descriptors, int descriptor,
9923  PropertyConstness constness, Object* value) {
9924  PropertyDetails details = descriptors->GetDetails(descriptor);
9925  if (details.location() == kField) {
9926  if (details.kind() == kData) {
9927  return IsGeneralizableTo(constness, details.constness()) &&
9928  value->FitsRepresentation(details.representation()) &&
9929  descriptors->GetFieldType(descriptor)->NowContains(value);
9930  } else {
9931  DCHECK_EQ(kAccessor, details.kind());
9932  return false;
9933  }
9934 
9935  } else {
9936  DCHECK_EQ(kDescriptor, details.location());
9937  DCHECK_EQ(PropertyConstness::kConst, details.constness());
9938  if (details.kind() == kData) {
9939  DCHECK(!FLAG_track_constant_fields);
9940  DCHECK(descriptors->GetStrongValue(descriptor) != value ||
9941  value->FitsRepresentation(details.representation()));
9942  return descriptors->GetStrongValue(descriptor) == value;
9943  } else {
9944  DCHECK_EQ(kAccessor, details.kind());
9945  return false;
9946  }
9947  }
9948  UNREACHABLE();
9949 }
9950 
9951 Handle<Map> UpdateDescriptorForValue(Isolate* isolate, Handle<Map> map,
9952  int descriptor,
9953  PropertyConstness constness,
9954  Handle<Object> value) {
9955  if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
9956  *value)) {
9957  return map;
9958  }
9959 
9960  PropertyAttributes attributes =
9961  map->instance_descriptors()->GetDetails(descriptor).attributes();
9962  Representation representation = value->OptimalRepresentation();
9963  Handle<FieldType> type = value->OptimalType(isolate, representation);
9964 
9965  MapUpdater mu(isolate, map);
9966  return mu.ReconfigureToDataField(descriptor, attributes, constness,
9967  representation, type);
9968 }
9969 
9970 } // namespace
9971 
9972 // static
9973 Handle<Map> Map::PrepareForDataProperty(Isolate* isolate, Handle<Map> map,
9974  int descriptor,
9975  PropertyConstness constness,
9976  Handle<Object> value) {
9977  // Dictionaries can store any property value.
9978  DCHECK(!map->is_dictionary_map());
9979  // Update to the newest map before storing the property.
9980  return UpdateDescriptorForValue(isolate, Update(isolate, map), descriptor,
9981  constness, value);
9982 }
9983 
9984 Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
9985  Handle<Name> name,
9986  Handle<Object> value,
9987  PropertyAttributes attributes,
9988  PropertyConstness constness,
9989  StoreOrigin store_origin) {
9990  RuntimeCallTimerScope stats_scope(
9991  isolate, *map,
9992  map->is_prototype_map()
9993  ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
9994  : RuntimeCallCounterId::kMap_TransitionToDataProperty);
9995 
9996  DCHECK(name->IsUniqueName());
9997  DCHECK(!map->is_dictionary_map());
9998 
9999  // Migrate to the newest map before storing the property.
10000  map = Update(isolate, map);
10001 
10002  Map maybe_transition = TransitionsAccessor(isolate, map)
10003  .SearchTransition(*name, kData, attributes);
10004  if (!maybe_transition.is_null()) {
10005  Handle<Map> transition(maybe_transition, isolate);
10006  int descriptor = transition->LastAdded();
10007 
10008  DCHECK_EQ(attributes, transition->instance_descriptors()
10009  ->GetDetails(descriptor)
10010  .attributes());
10011 
10012  return UpdateDescriptorForValue(isolate, transition, descriptor, constness,
10013  value);
10014  }
10015 
10016  TransitionFlag flag = INSERT_TRANSITION;
10017  MaybeHandle<Map> maybe_map;
10018  if (!map->TooManyFastProperties(store_origin)) {
10019  if (!FLAG_track_constant_fields && value->IsJSFunction()) {
10020  maybe_map =
10021  Map::CopyWithConstant(isolate, map, name, value, attributes, flag);
10022  } else {
10023  Representation representation = value->OptimalRepresentation();
10024  Handle<FieldType> type = value->OptimalType(isolate, representation);
10025  maybe_map = Map::CopyWithField(isolate, map, name, type, attributes,
10026  constness, representation, flag);
10027  }
10028  }
10029 
10030  Handle<Map> result;
10031  if (!maybe_map.ToHandle(&result)) {
10032  const char* reason = "TooManyFastProperties";
10033 #if V8_TRACE_MAPS
10034  std::unique_ptr<ScopedVector<char>> buffer;
10035  if (FLAG_trace_maps) {
10036  ScopedVector<char> name_buffer(100);
10037  name->NameShortPrint(name_buffer);
10038  buffer.reset(new ScopedVector<char>(128));
10039  SNPrintF(*buffer, "TooManyFastProperties %s", name_buffer.start());
10040  reason = buffer->start();
10041  }
10042 #endif
10043  Handle<Object> maybe_constructor(map->GetConstructor(), isolate);
10044  if (FLAG_feedback_normalization && map->new_target_is_base() &&
10045  maybe_constructor->IsJSFunction() &&
10046  !JSFunction::cast(*maybe_constructor)->shared()->native()) {
10047  Handle<JSFunction> constructor =
10048  Handle<JSFunction>::cast(maybe_constructor);
10049  DCHECK_NE(*constructor,
10050  constructor->context()->native_context()->object_function());
10051  Handle<Map> initial_map(constructor->initial_map(), isolate);
10052  result = Map::Normalize(isolate, initial_map, CLEAR_INOBJECT_PROPERTIES,
10053  reason);
10054  initial_map->DeprecateTransitionTree(isolate);
10055  Handle<Object> prototype(result->prototype(), isolate);
10056  JSFunction::SetInitialMap(constructor, result, prototype);
10057 
10058  // Deoptimize all code that embeds the previous initial map.
10059  initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
10060  isolate, DependentCode::kInitialMapChangedGroup);
10061  if (!result->EquivalentToForNormalization(*map,
10062  CLEAR_INOBJECT_PROPERTIES)) {
10063  result =
10064  Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
10065  }
10066  } else {
10067  result = Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
10068  }
10069  }
10070 
10071  return result;
10072 }
10073 
10074 Handle<Map> Map::ReconfigureExistingProperty(Isolate* isolate, Handle<Map> map,
10075  int descriptor, PropertyKind kind,
10076  PropertyAttributes attributes) {
10077  // Dictionaries have to be reconfigured in-place.
10078  DCHECK(!map->is_dictionary_map());
10079 
10080  if (!map->GetBackPointer()->IsMap()) {
10081  // There is no benefit from reconstructing transition tree for maps without
10082  // back pointers.
10083  return CopyGeneralizeAllFields(isolate, map, map->elements_kind(),
10084  descriptor, kind, attributes,
10085  "GenAll_AttributesMismatchProtoMap");
10086  }
10087 
10088  if (FLAG_trace_generalization) {
10089  map->PrintReconfiguration(isolate, stdout, descriptor, kind, attributes);
10090  }
10091 
10092  MapUpdater mu(isolate, map);
10093  DCHECK_EQ(kData, kind); // Only kData case is supported so far.
10094  Handle<Map> new_map = mu.ReconfigureToDataField(
10095  descriptor, attributes, kDefaultFieldConstness, Representation::None(),
10096  FieldType::None(isolate));
10097  return new_map;
10098 }
10099 
10100 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
10101  Handle<Name> name, int descriptor,
10102  Handle<Object> getter,
10103  Handle<Object> setter,
10104  PropertyAttributes attributes) {
10105  RuntimeCallTimerScope stats_scope(
10106  isolate,
10107  map->is_prototype_map()
10108  ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
10109  : RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
10110 
10111  // At least one of the accessors needs to be a new value.
10112  DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
10113  DCHECK(name->IsUniqueName());
10114 
10115  // Dictionary maps can always have additional data properties.
10116  if (map->is_dictionary_map()) return map;
10117 
10118  // Migrate to the newest map before transitioning to the new property.
10119  map = Update(isolate, map);
10120 
10121  PropertyNormalizationMode mode = map->is_prototype_map()
10122  ? KEEP_INOBJECT_PROPERTIES
10123  : CLEAR_INOBJECT_PROPERTIES;
10124 
10125  Map maybe_transition = TransitionsAccessor(isolate, map)
10126  .SearchTransition(*name, kAccessor, attributes);
10127  if (!maybe_transition.is_null()) {
10128  Handle<Map> transition(maybe_transition, isolate);
10129  DescriptorArray* descriptors = transition->instance_descriptors();
10130  int descriptor = transition->LastAdded();
10131  DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
10132 
10133  DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
10134  DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
10135 
10136  Handle<Object> maybe_pair(descriptors->GetStrongValue(descriptor), isolate);
10137  if (!maybe_pair->IsAccessorPair()) {
10138  return Map::Normalize(isolate, map, mode,
10139  "TransitionToAccessorFromNonPair");
10140  }
10141 
10142  Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
10143  if (!pair->Equals(*getter, *setter)) {
10144  return Map::Normalize(isolate, map, mode,
10145  "TransitionToDifferentAccessor");
10146  }
10147 
10148  return transition;
10149  }
10150 
10151  Handle<AccessorPair> pair;
10152  DescriptorArray* old_descriptors = map->instance_descriptors();
10153  if (descriptor != DescriptorArray::kNotFound) {
10154  if (descriptor != map->LastAdded()) {
10155  return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonLast");
10156  }
10157  PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
10158  if (old_details.kind() != kAccessor) {
10159  return Map::Normalize(isolate, map, mode,
10160  "AccessorsOverwritingNonAccessors");
10161  }
10162 
10163  if (old_details.attributes() != attributes) {
10164  return Map::Normalize(isolate, map, mode, "AccessorsWithAttributes");
10165  }
10166 
10167  Handle<Object> maybe_pair(old_descriptors->GetStrongValue(descriptor),
10168  isolate);
10169  if (!maybe_pair->IsAccessorPair()) {
10170  return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonPair");
10171  }
10172 
10173  Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
10174  if (current_pair->Equals(*getter, *setter)) return map;
10175 
10176  bool overwriting_accessor = false;
10177  if (!getter->IsNull(isolate) &&
10178  !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
10179  current_pair->get(ACCESSOR_GETTER) != *getter) {
10180  overwriting_accessor = true;
10181  }
10182  if (!setter->IsNull(isolate) &&
10183  !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
10184  current_pair->get(ACCESSOR_SETTER) != *setter) {
10185  overwriting_accessor = true;
10186  }
10187  if (overwriting_accessor) {
10188  return Map::Normalize(isolate, map, mode,
10189  "AccessorsOverwritingAccessors");
10190  }
10191 
10192  pair = AccessorPair::Copy(isolate, Handle<AccessorPair>::cast(maybe_pair));
10193  } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
10194  map->TooManyFastProperties(StoreOrigin::kNamed)) {
10195  return Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES,
10196  "TooManyAccessors");
10197  } else {
10198  pair = isolate->factory()->NewAccessorPair();
10199  }
10200 
10201  pair->SetComponents(*getter, *setter);
10202 
10203  TransitionFlag flag = INSERT_TRANSITION;
10204  Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
10205  return Map::CopyInsertDescriptor(isolate, map, &d, flag);
10206 }
10207 
10208 Handle<Map> Map::CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
10209  Descriptor* descriptor,
10210  TransitionFlag flag) {
10211  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
10212 
10213  // Share descriptors only if map owns descriptors and it not an initial map.
10214  if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
10215  !map->GetBackPointer()->IsUndefined(isolate) &&
10216  TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
10217  return ShareDescriptor(isolate, map, descriptors, descriptor);
10218  }
10219 
10220  int nof = map->NumberOfOwnDescriptors();
10221  Handle<DescriptorArray> new_descriptors =
10222  DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
10223  new_descriptors->Append(descriptor);
10224 
10225  Handle<LayoutDescriptor> new_layout_descriptor =
10226  FLAG_unbox_double_fields
10227  ? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
10228  : handle(LayoutDescriptor::FastPointerLayout(), isolate);
10229 
10230  return CopyReplaceDescriptors(
10231  isolate, map, new_descriptors, new_layout_descriptor, flag,
10232  descriptor->GetKey(), "CopyAddDescriptor", SIMPLE_PROPERTY_TRANSITION);
10233 }
10234 
10235 Handle<Map> Map::CopyInsertDescriptor(Isolate* isolate, Handle<Map> map,
10236  Descriptor* descriptor,
10237  TransitionFlag flag) {
10238  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
10239 
10240  // We replace the key if it is already present.
10241  int index =
10242  old_descriptors->SearchWithCache(isolate, *descriptor->GetKey(), *map);
10243  if (index != DescriptorArray::kNotFound) {
10244  return CopyReplaceDescriptor(isolate, map, old_descriptors, descriptor,
10245  index, flag);
10246  }
10247  return CopyAddDescriptor(isolate, map, descriptor, flag);
10248 }
10249 
10250 Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
10251  Handle<DescriptorArray> desc,
10252  int enumeration_index,
10253  int slack) {
10254  return DescriptorArray::CopyUpToAddAttributes(isolate, desc,
10255  enumeration_index, NONE, slack);
10256 }
10257 
10258 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
10259  Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index,
10260  PropertyAttributes attributes, int slack) {
10261  if (enumeration_index + slack == 0) {
10262  return isolate->factory()->empty_descriptor_array();
10263  }
10264 
10265  int size = enumeration_index;
10266 
10267  Handle<DescriptorArray> descriptors =
10268  DescriptorArray::Allocate(isolate, size, slack);
10269 
10270  if (attributes != NONE) {
10271  for (int i = 0; i < size; ++i) {
10272  MaybeObject value_or_field_type = desc->GetValue(i);
10273  Name key = desc->GetKey(i);
10274  PropertyDetails details = desc->GetDetails(i);
10275  // Bulk attribute changes never affect private properties.
10276  if (!key->IsPrivate()) {
10277  int mask = DONT_DELETE | DONT_ENUM;
10278  // READ_ONLY is an invalid attribute for JS setters/getters.
10279  HeapObject* heap_object;
10280  if (details.kind() != kAccessor ||
10281  !(value_or_field_type->GetHeapObjectIfStrong(&heap_object) &&
10282  heap_object->IsAccessorPair())) {
10283  mask |= READ_ONLY;
10284  }
10285  details = details.CopyAddAttributes(
10286  static_cast<PropertyAttributes>(attributes & mask));
10287  }
10288  descriptors->Set(i, key, value_or_field_type, details);
10289  }
10290  } else {
10291  for (int i = 0; i < size; ++i) {
10292  descriptors->CopyFrom(i, *desc);
10293  }
10294  }
10295 
10296  if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
10297 
10298  return descriptors;
10299 }
10300 
10301 // Create a new descriptor array with only enumerable, configurable, writeable
10302 // data properties, but identical field locations.
10303 Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
10304  Isolate* isolate, Handle<DescriptorArray> src, int enumeration_index,
10305  int slack) {
10306  if (enumeration_index + slack == 0) {
10307  return isolate->factory()->empty_descriptor_array();
10308  }
10309 
10310  int size = enumeration_index;
10311  Handle<DescriptorArray> descriptors =
10312  DescriptorArray::Allocate(isolate, size, slack);
10313 
10314  for (int i = 0; i < size; ++i) {
10315  Name key = src->GetKey(i);
10316  PropertyDetails details = src->GetDetails(i);
10317 
10318  DCHECK(!key->IsPrivateName());
10319  DCHECK(details.IsEnumerable());
10320  DCHECK_EQ(details.kind(), kData);
10321 
10322  // Ensure the ObjectClone property details are NONE, and that all source
10323  // details did not contain DONT_ENUM.
10324  PropertyDetails new_details(kData, NONE, details.location(),
10325  details.constness(), details.representation(),
10326  details.field_index());
10327  // Do not propagate the field type of normal object fields from the
10328  // original descriptors since FieldType changes don't create new maps.
10329  MaybeObject type = src->GetValue(i);
10330  if (details.location() == PropertyLocation::kField) {
10331  type = MaybeObject::FromObject(FieldType::Any());
10332  }
10333  descriptors->Set(i, key, type, new_details);
10334  }
10335 
10336  descriptors->Sort();
10337 
10338  return descriptors;
10339 }
10340 
10341 bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
10342  for (int i = 0; i < nof_descriptors; i++) {
10343  if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
10344  return false;
10345  }
10346  PropertyDetails details = GetDetails(i);
10347  PropertyDetails other_details = desc->GetDetails(i);
10348  if (details.kind() != other_details.kind() ||
10349  details.location() != other_details.location() ||
10350  !details.representation().Equals(other_details.representation())) {
10351  return false;
10352  }
10353  }
10354  return true;
10355 }
10356 
10357 Handle<Map> Map::CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
10358  Handle<DescriptorArray> descriptors,
10359  Descriptor* descriptor,
10360  int insertion_index,
10361  TransitionFlag flag) {
10362  Handle<Name> key = descriptor->GetKey();
10363  DCHECK_EQ(*key, descriptors->GetKey(insertion_index));
10364  // This function does not support replacing property fields as
10365  // that would break property field counters.
10366  DCHECK_NE(kField, descriptor->GetDetails().location());
10367  DCHECK_NE(kField, descriptors->GetDetails(insertion_index).location());
10368 
10369  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
10370  isolate, descriptors, map->NumberOfOwnDescriptors());
10371 
10372  new_descriptors->Replace(insertion_index, descriptor);
10373  Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
10374  isolate, map, new_descriptors, new_descriptors->number_of_descriptors());
10375 
10376  SimpleTransitionFlag simple_flag =
10377  (insertion_index == descriptors->number_of_descriptors() - 1)
10378  ? SIMPLE_PROPERTY_TRANSITION
10379  : PROPERTY_TRANSITION;
10380  return CopyReplaceDescriptors(isolate, map, new_descriptors,
10381  new_layout_descriptor, flag, key,
10382  "CopyReplaceDescriptor", simple_flag);
10383 }
10384 
10385 Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
10386  Handle<FixedArray> array, int index,
10387  Handle<Object> value,
10388  PretenureFlag pretenure) {
10389  if (index < array->length()) {
10390  array->set(index, *value);
10391  return array;
10392  }
10393  int capacity = array->length();
10394  do {
10395  capacity = JSObject::NewElementsCapacity(capacity);
10396  } while (capacity <= index);
10397  Handle<FixedArray> new_array =
10398  isolate->factory()->NewUninitializedFixedArray(capacity, pretenure);
10399  array->CopyTo(0, *new_array, 0, array->length());
10400  new_array->FillWithHoles(array->length(), new_array->length());
10401  new_array->set(index, *value);
10402  return new_array;
10403 }
10404 
10405 bool FixedArray::ContainsSortedNumbers() {
10406  for (int i = 1; i < length(); ++i) {
10407  Object* a_obj = get(i - 1);
10408  Object* b_obj = get(i);
10409  if (!a_obj->IsNumber() || !b_obj->IsNumber()) return false;
10410 
10411  uint32_t a = NumberToUint32(a_obj);
10412  uint32_t b = NumberToUint32(b_obj);
10413 
10414  if (a > b) return false;
10415  }
10416  return true;
10417 }
10418 
10419 Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
10420  Handle<FixedArray> array,
10421  int new_length) {
10422  if (new_length == 0) {
10423  return array->GetReadOnlyRoots().empty_fixed_array_handle();
10424  } else {
10425  array->Shrink(isolate, new_length);
10426  return array;
10427  }
10428 }
10429 
10430 void FixedArray::Shrink(Isolate* isolate, int new_length) {
10431  DCHECK(0 < new_length && new_length <= length());
10432  if (new_length < length()) {
10433  isolate->heap()->RightTrimFixedArray(*this, length() - new_length);
10434  }
10435 }
10436 
10437 void FixedArray::CopyTo(int pos, FixedArray dest, int dest_pos, int len) const {
10438  DisallowHeapAllocation no_gc;
10439  // Return early if len == 0 so that we don't try to read the write barrier off
10440  // a canonical read-only empty fixed array.
10441  if (len == 0) return;
10442  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
10443  for (int index = 0; index < len; index++) {
10444  dest->set(dest_pos + index, get(pos + index), mode);
10445  }
10446 }
10447 
10448 void JSObject::PrototypeRegistryCompactionCallback(HeapObject* value,
10449  int old_index,
10450  int new_index) {
10451  DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
10452  Map map = Map::cast(value);
10453  DCHECK(map->prototype_info()->IsPrototypeInfo());
10454  PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
10455  DCHECK_EQ(old_index, proto_info->registry_slot());
10456  proto_info->set_registry_slot(new_index);
10457 }
10458 
10459 // static
10460 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
10461  Handle<Object> obj) {
10462  int length = array->Length();
10463  array = EnsureSpace(isolate, array, length + 1);
10464  // Check that GC didn't remove elements from the array.
10465  DCHECK_EQ(array->Length(), length);
10466  array->Set(length, *obj);
10467  array->SetLength(length + 1);
10468  return array;
10469 }
10470 
10471 // static
10472 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
10473  Handle<Object> obj1, Handle<Object> obj2) {
10474  int length = array->Length();
10475  array = EnsureSpace(isolate, array, length + 2);
10476  // Check that GC didn't remove elements from the array.
10477  DCHECK_EQ(array->Length(), length);
10478  array->Set(length, *obj1);
10479  array->Set(length + 1, *obj2);
10480  array->SetLength(length + 2);
10481  return array;
10482 }
10483 
10484 // static
10485 Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) {
10486  Handle<FixedArray> fixed_array =
10487  isolate->factory()->NewFixedArray(size + kFirstIndex);
10488  fixed_array->set_map_no_write_barrier(
10489  ReadOnlyRoots(isolate).array_list_map());
10490  Handle<ArrayList> result = Handle<ArrayList>::cast(fixed_array);
10491  result->SetLength(0);
10492  return result;
10493 }
10494 
10495 Handle<FixedArray> ArrayList::Elements(Isolate* isolate,
10496  Handle<ArrayList> array) {
10497  int length = array->Length();
10498  Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
10499  // Do not copy the first entry, i.e., the length.
10500  array->CopyTo(kFirstIndex, *result, 0, length);
10501  return result;
10502 }
10503 
10504 namespace {
10505 
10506 Handle<FixedArray> EnsureSpaceInFixedArray(Isolate* isolate,
10507  Handle<FixedArray> array,
10508  int length) {
10509  int capacity = array->length();
10510  if (capacity < length) {
10511  int new_capacity = length;
10512  new_capacity = new_capacity + Max(new_capacity / 2, 2);
10513  int grow_by = new_capacity - capacity;
10514  array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
10515  }
10516  return array;
10517 }
10518 
10519 } // namespace
10520 
10521 // static
10522 Handle<ArrayList> ArrayList::EnsureSpace(Isolate* isolate,
10523  Handle<ArrayList> array, int length) {
10524  const bool empty = (array->length() == 0);
10525  Handle<FixedArray> ret =
10526  EnsureSpaceInFixedArray(isolate, array, kFirstIndex + length);
10527  if (empty) {
10528  ret->set_map_no_write_barrier(array->GetReadOnlyRoots().array_list_map());
10529 
10530  Handle<ArrayList>::cast(ret)->SetLength(0);
10531  }
10532  return Handle<ArrayList>::cast(ret);
10533 }
10534 
10535 // static
10536 Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
10537  Handle<WeakArrayList> array,
10538  const MaybeObjectHandle& value) {
10539  int length = array->length();
10540  array = EnsureSpace(isolate, array, length + 1);
10541  // Reload length; GC might have removed elements from the array.
10542  length = array->length();
10543  array->Set(length, *value);
10544  array->set_length(length + 1);
10545  return array;
10546 }
10547 
10548 bool WeakArrayList::IsFull() { return length() == capacity(); }
10549 
10550 // static
10551 Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
10552  Handle<WeakArrayList> array,
10553  int length,
10554  PretenureFlag pretenure) {
10555  int capacity = array->capacity();
10556  if (capacity < length) {
10557  int new_capacity = length;
10558  new_capacity = new_capacity + Max(new_capacity / 2, 2);
10559  int grow_by = new_capacity - capacity;
10560  array =
10561  isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by, pretenure);
10562  }
10563  return array;
10564 }
10565 
10566 int WeakArrayList::CountLiveWeakReferences() const {
10567  int live_weak_references = 0;
10568  for (int i = 0; i < length(); i++) {
10569  if (Get(i)->IsWeak()) {
10570  ++live_weak_references;
10571  }
10572  }
10573  return live_weak_references;
10574 }
10575 
10576 bool WeakArrayList::RemoveOne(const MaybeObjectHandle& value) {
10577  if (length() == 0) return false;
10578  // Optimize for the most recently added element to be removed again.
10579  MaybeObject cleared_weak_ref =
10580  HeapObjectReference::ClearedValue(GetIsolate());
10581  int last_index = length() - 1;
10582  for (int i = last_index; i >= 0; --i) {
10583  if (Get(i) == *value) {
10584  // Move the last element into the this slot (or no-op, if this is the
10585  // last slot).
10586  Set(i, Get(last_index));
10587  Set(last_index, cleared_weak_ref);
10588  set_length(last_index);
10589  return true;
10590  }
10591  }
10592  return false;
10593 }
10594 
10595 // static
10596 Handle<WeakArrayList> PrototypeUsers::Add(Isolate* isolate,
10597  Handle<WeakArrayList> array,
10598  Handle<Map> value,
10599  int* assigned_index) {
10600  int length = array->length();
10601  if (length == 0) {
10602  // Uninitialized WeakArrayList; need to initialize empty_slot_index.
10603  array = WeakArrayList::EnsureSpace(isolate, array, kFirstIndex + 1);
10604  set_empty_slot_index(*array, kNoEmptySlotsMarker);
10605  array->Set(kFirstIndex, HeapObjectReference::Weak(*value));
10606  array->set_length(kFirstIndex + 1);
10607  if (assigned_index != nullptr) *assigned_index = kFirstIndex;
10608  return array;
10609  }
10610 
10611  // If the array has unfilled space at the end, use it.
10612  if (!array->IsFull()) {
10613  array->Set(length, HeapObjectReference::Weak(*value));
10614  array->set_length(length + 1);
10615  if (assigned_index != nullptr) *assigned_index = length;
10616  return array;
10617  }
10618 
10619  // If there are empty slots, use one of them.
10620  int empty_slot = Smi::ToInt(empty_slot_index(*array));
10621  if (empty_slot != kNoEmptySlotsMarker) {
10622  DCHECK_GE(empty_slot, kFirstIndex);
10623  CHECK_LT(empty_slot, array->length());
10624  int next_empty_slot = array->Get(empty_slot).ToSmi().value();
10625 
10626  array->Set(empty_slot, HeapObjectReference::Weak(*value));
10627  if (assigned_index != nullptr) *assigned_index = empty_slot;
10628 
10629  set_empty_slot_index(*array, next_empty_slot);
10630  return array;
10631  } else {
10632  DCHECK_EQ(empty_slot, kNoEmptySlotsMarker);
10633  }
10634 
10635  // Array full and no empty slots. Grow the array.
10636  array = WeakArrayList::EnsureSpace(isolate, array, length + 1);
10637  array->Set(length, HeapObjectReference::Weak(*value));
10638  array->set_length(length + 1);
10639  if (assigned_index != nullptr) *assigned_index = length;
10640  return array;
10641 }
10642 
10643 WeakArrayList* PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
10644  CompactionCallback callback,
10645  PretenureFlag pretenure) {
10646  if (array->length() == 0) {
10647  return *array;
10648  }
10649  int new_length = kFirstIndex + array->CountLiveWeakReferences();
10650  if (new_length == array->length()) {
10651  return *array;
10652  }
10653 
10654  Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
10655  heap->isolate(),
10656  handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
10657  new_length, pretenure);
10658  // Allocation might have caused GC and turned some of the elements into
10659  // cleared weak heap objects. Count the number of live objects again.
10660  int copy_to = kFirstIndex;
10661  for (int i = kFirstIndex; i < array->length(); i++) {
10662  MaybeObject element = array->Get(i);
10663  HeapObject* value;
10664  if (element->GetHeapObjectIfWeak(&value)) {
10665  callback(value, i, copy_to);
10666  new_array->Set(copy_to++, element);
10667  } else {
10668  DCHECK(element->IsCleared() || element->IsSmi());
10669  }
10670  }
10671  new_array->set_length(copy_to);
10672  set_empty_slot_index(*new_array, kNoEmptySlotsMarker);
10673  return *new_array;
10674 }
10675 
10676 Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
10677  Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture_count) {
10678  DCHECK_GE(match_info->length(), kLastMatchOverhead);
10679  const int required_length = kFirstCaptureIndex + capture_count;
10680  return Handle<RegExpMatchInfo>::cast(
10681  EnsureSpaceInFixedArray(isolate, match_info, required_length));
10682 }
10683 
10684 // static
10685 Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
10686  Handle<Object> receiver,
10687  Handle<JSFunction> function,
10688  Handle<AbstractCode> code,
10689  int offset, int flags) {
10690  const int frame_count = in->FrameCount();
10691  const int new_length = LengthFor(frame_count + 1);
10692  Handle<FrameArray> array =
10693  EnsureSpace(function->GetIsolate(), in, new_length);
10694  array->SetReceiver(frame_count, *receiver);
10695  array->SetFunction(frame_count, *function);
10696  array->SetCode(frame_count, *code);
10697  array->SetOffset(frame_count, Smi::FromInt(offset));
10698  array->SetFlags(frame_count, Smi::FromInt(flags));
10699  array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
10700  return array;
10701 }
10702 
10703 // static
10704 Handle<FrameArray> FrameArray::AppendWasmFrame(
10705  Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
10706  int wasm_function_index, wasm::WasmCode* code, int offset, int flags) {
10707  Isolate* isolate = wasm_instance->GetIsolate();
10708  const int frame_count = in->FrameCount();
10709  const int new_length = LengthFor(frame_count + 1);
10710  Handle<FrameArray> array = EnsureSpace(isolate, in, new_length);
10711  // The {code} will be {nullptr} for interpreted wasm frames.
10712  Handle<Foreign> code_foreign =
10713  isolate->factory()->NewForeign(reinterpret_cast<Address>(code));
10714  array->SetWasmInstance(frame_count, *wasm_instance);
10715  array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
10716  array->SetWasmCodeObject(frame_count, *code_foreign);
10717  array->SetOffset(frame_count, Smi::FromInt(offset));
10718  array->SetFlags(frame_count, Smi::FromInt(flags));
10719  array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
10720  return array;
10721 }
10722 
10723 void FrameArray::ShrinkToFit(Isolate* isolate) {
10724  Shrink(isolate, LengthFor(FrameCount()));
10725 }
10726 
10727 // static
10728 Handle<FrameArray> FrameArray::EnsureSpace(Isolate* isolate,
10729  Handle<FrameArray> array,
10730  int length) {
10731  return Handle<FrameArray>::cast(
10732  EnsureSpaceInFixedArray(isolate, array, length));
10733 }
10734 
10735 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
10736  int nof_descriptors,
10737  int slack) {
10738  return nof_descriptors + slack == 0
10739  ? isolate->factory()->empty_descriptor_array()
10740  : isolate->factory()->NewDescriptorArray(nof_descriptors, slack);
10741 }
10742 
10743 void DescriptorArray::Initialize(EnumCache* enum_cache,
10744  HeapObject* undefined_value,
10745  int nof_descriptors, int slack) {
10746  DCHECK_GE(nof_descriptors, 0);
10747  DCHECK_GE(slack, 0);
10748  DCHECK_LE(nof_descriptors + slack, kMaxNumberOfDescriptors);
10749  set_number_of_all_descriptors(nof_descriptors + slack);
10750  set_number_of_descriptors(nof_descriptors);
10751  set_number_of_marked_descriptors(0);
10752  set_filler16bits(0);
10753  set_enum_cache(enum_cache);
10754  MemsetPointer(GetDescriptorSlot(0), undefined_value,
10755  number_of_all_descriptors() * kEntrySize);
10756 }
10757 
10758 void DescriptorArray::ClearEnumCache() {
10759  set_enum_cache(GetReadOnlyRoots().empty_enum_cache());
10760 }
10761 
10762 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
10763  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
10764  Set(index, descriptor);
10765 }
10766 
10767 // static
10768 void DescriptorArray::InitializeOrChangeEnumCache(
10769  Handle<DescriptorArray> descriptors, Isolate* isolate,
10770  Handle<FixedArray> keys, Handle<FixedArray> indices) {
10771  EnumCache* enum_cache = descriptors->enum_cache();
10772  if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
10773  enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
10774  descriptors->set_enum_cache(enum_cache);
10775  } else {
10776  enum_cache->set_keys(*keys);
10777  enum_cache->set_indices(*indices);
10778  }
10779 }
10780 
10781 void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
10782  PropertyDetails details = src->GetDetails(index);
10783  Set(index, src->GetKey(index), src->GetValue(index), details);
10784 }
10785 
10786 void DescriptorArray::Sort() {
10787  // In-place heap sort.
10788  int len = number_of_descriptors();
10789  // Reset sorting since the descriptor array might contain invalid pointers.
10790  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
10791  // Bottom-up max-heap construction.
10792  // Index of the last node with children
10793  const int max_parent_index = (len / 2) - 1;
10794  for (int i = max_parent_index; i >= 0; --i) {
10795  int parent_index = i;
10796  const uint32_t parent_hash = GetSortedKey(i)->Hash();
10797  while (parent_index <= max_parent_index) {
10798  int child_index = 2 * parent_index + 1;
10799  uint32_t child_hash = GetSortedKey(child_index)->Hash();
10800  if (child_index + 1 < len) {
10801  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10802  if (right_child_hash > child_hash) {
10803  child_index++;
10804  child_hash = right_child_hash;
10805  }
10806  }
10807  if (child_hash <= parent_hash) break;
10808  SwapSortedKeys(parent_index, child_index);
10809  // Now element at child_index could be < its children.
10810  parent_index = child_index; // parent_hash remains correct.
10811  }
10812  }
10813 
10814  // Extract elements and create sorted array.
10815  for (int i = len - 1; i > 0; --i) {
10816  // Put max element at the back of the array.
10817  SwapSortedKeys(0, i);
10818  // Shift down the new top element.
10819  int parent_index = 0;
10820  const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
10821  const int max_parent_index = (i / 2) - 1;
10822  while (parent_index <= max_parent_index) {
10823  int child_index = parent_index * 2 + 1;
10824  uint32_t child_hash = GetSortedKey(child_index)->Hash();
10825  if (child_index + 1 < i) {
10826  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10827  if (right_child_hash > child_hash) {
10828  child_index++;
10829  child_hash = right_child_hash;
10830  }
10831  }
10832  if (child_hash <= parent_hash) break;
10833  SwapSortedKeys(parent_index, child_index);
10834  parent_index = child_index;
10835  }
10836  }
10837  DCHECK(IsSortedNoDuplicates());
10838 }
10839 
10840 Handle<AccessorPair> AccessorPair::Copy(Isolate* isolate,
10841  Handle<AccessorPair> pair) {
10842  Handle<AccessorPair> copy = isolate->factory()->NewAccessorPair();
10843  copy->set_getter(pair->getter());
10844  copy->set_setter(pair->setter());
10845  return copy;
10846 }
10847 
10848 Handle<Object> AccessorPair::GetComponent(Isolate* isolate,
10849  Handle<AccessorPair> accessor_pair,
10850  AccessorComponent component) {
10851  Object* accessor = accessor_pair->get(component);
10852  if (accessor->IsFunctionTemplateInfo()) {
10853  return ApiNatives::InstantiateFunction(
10854  handle(FunctionTemplateInfo::cast(accessor), isolate))
10855  .ToHandleChecked();
10856  }
10857  if (accessor->IsNull(isolate)) {
10858  return isolate->factory()->undefined_value();
10859  }
10860  return handle(accessor, isolate);
10861 }
10862 
10863 Handle<DeoptimizationData> DeoptimizationData::New(Isolate* isolate,
10864  int deopt_entry_count,
10865  PretenureFlag pretenure) {
10866  return Handle<DeoptimizationData>::cast(isolate->factory()->NewFixedArray(
10867  LengthFor(deopt_entry_count), pretenure));
10868 }
10869 
10870 Handle<DeoptimizationData> DeoptimizationData::Empty(Isolate* isolate) {
10871  return Handle<DeoptimizationData>::cast(
10872  isolate->factory()->empty_fixed_array());
10873 }
10874 
10875 SharedFunctionInfo* DeoptimizationData::GetInlinedFunction(int index) {
10876  if (index == -1) {
10877  return SharedFunctionInfo::cast(SharedFunctionInfo());
10878  } else {
10879  return SharedFunctionInfo::cast(LiteralArray()->get(index));
10880  }
10881 }
10882 
10883 #ifdef DEBUG
10884 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
10885  if (number_of_all_descriptors() != other->number_of_all_descriptors())
10886  return false;
10887  for (int i = 0; i < number_of_all_descriptors(); ++i) {
10888  if (get(i) != other->get(i)) return false;
10889  }
10890  return true;
10891 }
10892 #endif
10893 
10894 // static
10895 Handle<String> String::Trim(Isolate* isolate, Handle<String> string,
10896  TrimMode mode) {
10897  string = String::Flatten(isolate, string);
10898  int const length = string->length();
10899 
10900  // Perform left trimming if requested.
10901  int left = 0;
10902  if (mode == kTrim || mode == kTrimStart) {
10903  while (left < length && IsWhiteSpaceOrLineTerminator(string->Get(left))) {
10904  left++;
10905  }
10906  }
10907 
10908  // Perform right trimming if requested.
10909  int right = length;
10910  if (mode == kTrim || mode == kTrimEnd) {
10911  while (right > left &&
10912  IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
10913  right--;
10914  }
10915  }
10916 
10917  return isolate->factory()->NewSubString(string, left, right);
10918 }
10919 
10920 bool String::LooksValid() {
10921  // TODO(leszeks): Maybe remove this check entirely, Heap::Contains uses
10922  // basically the same logic as the way we access the heap in the first place.
10923  MemoryChunk* chunk = MemoryChunk::FromHeapObject(*this);
10924  // RO_SPACE objects should always be valid.
10925  if (chunk->owner()->identity() == RO_SPACE) return true;
10926  if (chunk->heap() == nullptr) return false;
10927  return chunk->heap()->Contains(*this);
10928 }
10929 
10930 // static
10931 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
10932  if (name->IsString()) return Handle<String>::cast(name);
10933  // ES6 section 9.2.11 SetFunctionName, step 4.
10934  Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
10935  if (description->IsUndefined(isolate)) {
10936  return isolate->factory()->empty_string();
10937  }
10938  IncrementalStringBuilder builder(isolate);
10939  builder.AppendCharacter('[');
10940  builder.AppendString(Handle<String>::cast(description));
10941  builder.AppendCharacter(']');
10942  return builder.Finish();
10943 }
10944 
10945 // static
10946 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name,
10947  Handle<String> prefix) {
10948  Handle<String> name_string;
10949  ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string,
10950  ToFunctionName(isolate, name), String);
10951  IncrementalStringBuilder builder(isolate);
10952  builder.AppendString(prefix);
10953  builder.AppendCharacter(' ');
10954  builder.AppendString(name_string);
10955  return builder.Finish();
10956 }
10957 
10958 namespace {
10959 
10960 bool AreDigits(const uint8_t* s, int from, int to) {
10961  for (int i = from; i < to; i++) {
10962  if (s[i] < '0' || s[i] > '9') return false;
10963  }
10964 
10965  return true;
10966 }
10967 
10968 
10969 int ParseDecimalInteger(const uint8_t* s, int from, int to) {
10970  DCHECK_LT(to - from, 10); // Overflow is not possible.
10971  DCHECK(from < to);
10972  int d = s[from] - '0';
10973 
10974  for (int i = from + 1; i < to; i++) {
10975  d = 10 * d + (s[i] - '0');
10976  }
10977 
10978  return d;
10979 }
10980 
10981 } // namespace
10982 
10983 // static
10984 Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) {
10985  // Flatten {subject} string first.
10986  subject = String::Flatten(isolate, subject);
10987 
10988  // Fast array index case.
10989  uint32_t index;
10990  if (subject->AsArrayIndex(&index)) {
10991  return isolate->factory()->NewNumberFromUint(index);
10992  }
10993 
10994  // Fast case: short integer or some sorts of junk values.
10995  if (subject->IsSeqOneByteString()) {
10996  int len = subject->length();
10997  if (len == 0) return handle(Smi::kZero, isolate);
10998 
10999  DisallowHeapAllocation no_gc;
11000  uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
11001  bool minus = (data[0] == '-');
11002  int start_pos = (minus ? 1 : 0);
11003 
11004  if (start_pos == len) {
11005  return isolate->factory()->nan_value();
11006  } else if (data[start_pos] > '9') {
11007  // Fast check for a junk value. A valid string may start from a
11008  // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
11009  // or the 'I' character ('Infinity'). All of that have codes not greater
11010  // than '9' except 'I' and &nbsp;.
11011  if (data[start_pos] != 'I' && data[start_pos] != 0xA0) {
11012  return isolate->factory()->nan_value();
11013  }
11014  } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
11015  // The maximal/minimal smi has 10 digits. If the string has less digits
11016  // we know it will fit into the smi-data type.
11017  int d = ParseDecimalInteger(data, start_pos, len);
11018  if (minus) {
11019  if (d == 0) return isolate->factory()->minus_zero_value();
11020  d = -d;
11021  } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
11022  (len == 1 || data[0] != '0')) {
11023  // String hash is not calculated yet but all the data are present.
11024  // Update the hash field to speed up sequential convertions.
11025  uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
11026 #ifdef DEBUG
11027  subject->Hash(); // Force hash calculation.
11028  DCHECK_EQ(static_cast<int>(subject->hash_field()),
11029  static_cast<int>(hash));
11030 #endif
11031  subject->set_hash_field(hash);
11032  }
11033  return handle(Smi::FromInt(d), isolate);
11034  }
11035  }
11036 
11037  // Slower case.
11038  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
11039  return isolate->factory()->NewNumber(StringToDouble(isolate, subject, flags));
11040 }
11041 
11042 
11043 String::FlatContent String::GetFlatContent() {
11044  DCHECK(!AllowHeapAllocation::IsAllowed());
11045  int length = this->length();
11046  StringShape shape(*this);
11047  String string = *this;
11048  int offset = 0;
11049  if (shape.representation_tag() == kConsStringTag) {
11050  ConsString cons = ConsString::cast(string);
11051  if (cons->second()->length() != 0) {
11052  return FlatContent();
11053  }
11054  string = cons->first();
11055  shape = StringShape(string);
11056  } else if (shape.representation_tag() == kSlicedStringTag) {
11057  SlicedString slice = SlicedString::cast(string);
11058  offset = slice->offset();
11059  string = slice->parent();
11060  shape = StringShape(string);
11061  DCHECK(shape.representation_tag() != kConsStringTag &&
11062  shape.representation_tag() != kSlicedStringTag);
11063  }
11064  if (shape.representation_tag() == kThinStringTag) {
11065  ThinString thin = ThinString::cast(string);
11066  string = thin->actual();
11067  shape = StringShape(string);
11068  DCHECK(!shape.IsCons());
11069  DCHECK(!shape.IsSliced());
11070  }
11071  if (shape.encoding_tag() == kOneByteStringTag) {
11072  const uint8_t* start;
11073  if (shape.representation_tag() == kSeqStringTag) {
11074  start = SeqOneByteString::cast(string)->GetChars();
11075  } else {
11076  start = ExternalOneByteString::cast(string)->GetChars();
11077  }
11078  return FlatContent(start + offset, length);
11079  } else {
11080  DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag);
11081  const uc16* start;
11082  if (shape.representation_tag() == kSeqStringTag) {
11083  start = SeqTwoByteString::cast(string)->GetChars();
11084  } else {
11085  start = ExternalTwoByteString::cast(string)->GetChars();
11086  }
11087  return FlatContent(start + offset, length);
11088  }
11089 }
11090 
11091 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
11092  RobustnessFlag robust_flag,
11093  int offset, int length,
11094  int* length_return) {
11095  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
11096  return std::unique_ptr<char[]>();
11097  }
11098  // Negative length means the to the end of the string.
11099  if (length < 0) length = kMaxInt - offset;
11100 
11101  // Compute the size of the UTF-8 string. Start at the specified offset.
11102  StringCharacterStream stream(*this, offset);
11103  int character_position = offset;
11104  int utf8_bytes = 0;
11105  int last = unibrow::Utf16::kNoPreviousCharacter;
11106  while (stream.HasMore() && character_position++ < offset + length) {
11107  uint16_t character = stream.GetNext();
11108  utf8_bytes += unibrow::Utf8::Length(character, last);
11109  last = character;
11110  }
11111 
11112  if (length_return) {
11113  *length_return = utf8_bytes;
11114  }
11115 
11116  char* result = NewArray<char>(utf8_bytes + 1);
11117 
11118  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
11119  stream.Reset(*this, offset);
11120  character_position = offset;
11121  int utf8_byte_position = 0;
11122  last = unibrow::Utf16::kNoPreviousCharacter;
11123  while (stream.HasMore() && character_position++ < offset + length) {
11124  uint16_t character = stream.GetNext();
11125  if (allow_nulls == DISALLOW_NULLS && character == 0) {
11126  character = ' ';
11127  }
11128  utf8_byte_position +=
11129  unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
11130  last = character;
11131  }
11132  result[utf8_byte_position] = 0;
11133  return std::unique_ptr<char[]>(result);
11134 }
11135 
11136 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
11137  RobustnessFlag robust_flag,
11138  int* length_return) {
11139  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
11140 }
11141 
11142 
11143 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
11144  Relocatable* current = isolate->relocatable_top();
11145  while (current != nullptr) {
11146  current->PostGarbageCollection();
11147  current = current->prev_;
11148  }
11149 }
11150 
11151 
11152 // Reserve space for statics needing saving and restoring.
11153 int Relocatable::ArchiveSpacePerThread() {
11154  return sizeof(Relocatable*); // NOLINT
11155 }
11156 
11157 
11158 // Archive statics that are thread-local.
11159 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
11160  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
11161  isolate->set_relocatable_top(nullptr);
11162  return to + ArchiveSpacePerThread();
11163 }
11164 
11165 
11166 // Restore statics that are thread-local.
11167 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
11168  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
11169  return from + ArchiveSpacePerThread();
11170 }
11171 
11172 char* Relocatable::Iterate(RootVisitor* v, char* thread_storage) {
11173  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
11174  Iterate(v, top);
11175  return thread_storage + ArchiveSpacePerThread();
11176 }
11177 
11178 void Relocatable::Iterate(Isolate* isolate, RootVisitor* v) {
11179  Iterate(v, isolate->relocatable_top());
11180 }
11181 
11182 void Relocatable::Iterate(RootVisitor* v, Relocatable* top) {
11183  Relocatable* current = top;
11184  while (current != nullptr) {
11185  current->IterateInstance(v);
11186  current = current->prev_;
11187  }
11188 }
11189 
11190 
11191 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
11192  : Relocatable(isolate),
11193  str_(str.location()),
11194  length_(str->length()) {
11195  PostGarbageCollection();
11196 }
11197 
11198 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
11199  : Relocatable(isolate),
11200  str_(nullptr),
11201  is_one_byte_(true),
11202  length_(input.length()),
11203  start_(input.start()) {}
11204 
11205 void FlatStringReader::PostGarbageCollection() {
11206  if (str_ == nullptr) return;
11207  Handle<String> str(str_);
11208  DCHECK(str->IsFlat());
11209  DisallowHeapAllocation no_gc;
11210  // This does not actually prevent the vector from being relocated later.
11211  String::FlatContent content = str->GetFlatContent();
11212  DCHECK(content.IsFlat());
11213  is_one_byte_ = content.IsOneByte();
11214  if (is_one_byte_) {
11215  start_ = content.ToOneByteVector().start();
11216  } else {
11217  start_ = content.ToUC16Vector().start();
11218  }
11219 }
11220 
11221 void ConsStringIterator::Initialize(ConsString cons_string, int offset) {
11222  DCHECK(!cons_string.is_null());
11223  root_ = cons_string;
11224  consumed_ = offset;
11225  // Force stack blown condition to trigger restart.
11226  depth_ = 1;
11227  maximum_depth_ = kStackSize + depth_;
11228  DCHECK(StackBlown());
11229 }
11230 
11231 String ConsStringIterator::Continue(int* offset_out) {
11232  DCHECK_NE(depth_, 0);
11233  DCHECK_EQ(0, *offset_out);
11234  bool blew_stack = StackBlown();
11235  String string;
11236  // Get the next leaf if there is one.
11237  if (!blew_stack) string = NextLeaf(&blew_stack);
11238  // Restart search from root.
11239  if (blew_stack) {
11240  DCHECK(string.is_null());
11241  string = Search(offset_out);
11242  }
11243  // Ensure future calls return null immediately.
11244  if (string.is_null()) Reset(ConsString());
11245  return string;
11246 }
11247 
11248 String ConsStringIterator::Search(int* offset_out) {
11249  ConsString cons_string = root_;
11250  // Reset the stack, pushing the root string.
11251  depth_ = 1;
11252  maximum_depth_ = 1;
11253  frames_[0] = cons_string;
11254  const int consumed = consumed_;
11255  int offset = 0;
11256  while (true) {
11257  // Loop until the string is found which contains the target offset.
11258  String string = cons_string->first();
11259  int length = string->length();
11260  int32_t type;
11261  if (consumed < offset + length) {
11262  // Target offset is in the left branch.
11263  // Keep going if we're still in a ConString.
11264  type = string->map()->instance_type();
11265  if ((type & kStringRepresentationMask) == kConsStringTag) {
11266  cons_string = ConsString::cast(string);
11267  PushLeft(cons_string);
11268  continue;
11269  }
11270  // Tell the stack we're done descending.
11271  AdjustMaximumDepth();
11272  } else {
11273  // Descend right.
11274  // Update progress through the string.
11275  offset += length;
11276  // Keep going if we're still in a ConString.
11277  string = cons_string->second();
11278  type = string->map()->instance_type();
11279  if ((type & kStringRepresentationMask) == kConsStringTag) {
11280  cons_string = ConsString::cast(string);
11281  PushRight(cons_string);
11282  continue;
11283  }
11284  // Need this to be updated for the current string.
11285  length = string->length();
11286  // Account for the possibility of an empty right leaf.
11287  // This happens only if we have asked for an offset outside the string.
11288  if (length == 0) {
11289  // Reset so future operations will return null immediately.
11290  Reset(ConsString());
11291  return String();
11292  }
11293  // Tell the stack we're done descending.
11294  AdjustMaximumDepth();
11295  // Pop stack so next iteration is in correct place.
11296  Pop();
11297  }
11298  DCHECK_NE(length, 0);
11299  // Adjust return values and exit.
11300  consumed_ = offset + length;
11301  *offset_out = consumed - offset;
11302  return string;
11303  }
11304  UNREACHABLE();
11305 }
11306 
11307 String ConsStringIterator::NextLeaf(bool* blew_stack) {
11308  while (true) {
11309  // Tree traversal complete.
11310  if (depth_ == 0) {
11311  *blew_stack = false;
11312  return String();
11313  }
11314  // We've lost track of higher nodes.
11315  if (StackBlown()) {
11316  *blew_stack = true;
11317  return String();
11318  }
11319  // Go right.
11320  ConsString cons_string = frames_[OffsetForDepth(depth_ - 1)];
11321  String string = cons_string->second();
11322  int32_t type = string->map()->instance_type();
11323  if ((type & kStringRepresentationMask) != kConsStringTag) {
11324  // Pop stack so next iteration is in correct place.
11325  Pop();
11326  int length = string->length();
11327  // Could be a flattened ConsString.
11328  if (length == 0) continue;
11329  consumed_ += length;
11330  return string;
11331  }
11332  cons_string = ConsString::cast(string);
11333  PushRight(cons_string);
11334  // Need to traverse all the way left.
11335  while (true) {
11336  // Continue left.
11337  string = cons_string->first();
11338  type = string->map()->instance_type();
11339  if ((type & kStringRepresentationMask) != kConsStringTag) {
11340  AdjustMaximumDepth();
11341  int length = string->length();
11342  if (length == 0) break; // Skip empty left-hand sides of ConsStrings.
11343  consumed_ += length;
11344  return string;
11345  }
11346  cons_string = ConsString::cast(string);
11347  PushLeft(cons_string);
11348  }
11349  }
11350  UNREACHABLE();
11351 }
11352 
11353 uint16_t ConsString::ConsStringGet(int index) {
11354  DCHECK(index >= 0 && index < this->length());
11355 
11356  // Check for a flattened cons string
11357  if (second()->length() == 0) {
11358  String left = first();
11359  return left->Get(index);
11360  }
11361 
11362  String string = String::cast(*this);
11363 
11364  while (true) {
11365  if (StringShape(string).IsCons()) {
11366  ConsString cons_string = ConsString::cast(string);
11367  String left = cons_string->first();
11368  if (left->length() > index) {
11369  string = left;
11370  } else {
11371  index -= left->length();
11372  string = cons_string->second();
11373  }
11374  } else {
11375  return string->Get(index);
11376  }
11377  }
11378 
11379  UNREACHABLE();
11380 }
11381 
11382 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
11383 
11384 uint16_t SlicedString::SlicedStringGet(int index) {
11385  return parent()->Get(offset() + index);
11386 }
11387 
11388 template <typename sinkchar>
11389 void String::WriteToFlat(String src, sinkchar* sink, int f, int t) {
11390  DisallowHeapAllocation no_gc;
11391  String source = src;
11392  int from = f;
11393  int to = t;
11394  while (true) {
11395  DCHECK(0 <= from && from <= to && to <= source->length());
11396  switch (StringShape(source).full_representation_tag()) {
11397  case kOneByteStringTag | kExternalStringTag: {
11398  CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
11399  to - from);
11400  return;
11401  }
11402  case kTwoByteStringTag | kExternalStringTag: {
11403  const uc16* data =
11404  ExternalTwoByteString::cast(source)->GetChars();
11405  CopyChars(sink,
11406  data + from,
11407  to - from);
11408  return;
11409  }
11410  case kOneByteStringTag | kSeqStringTag: {
11411  CopyChars(sink,
11412  SeqOneByteString::cast(source)->GetChars() + from,
11413  to - from);
11414  return;
11415  }
11416  case kTwoByteStringTag | kSeqStringTag: {
11417  CopyChars(sink,
11418  SeqTwoByteString::cast(source)->GetChars() + from,
11419  to - from);
11420  return;
11421  }
11422  case kOneByteStringTag | kConsStringTag:
11423  case kTwoByteStringTag | kConsStringTag: {
11424  ConsString cons_string = ConsString::cast(source);
11425  String first = cons_string->first();
11426  int boundary = first->length();
11427  if (to - boundary >= boundary - from) {
11428  // Right hand side is longer. Recurse over left.
11429  if (from < boundary) {
11430  WriteToFlat(first, sink, from, boundary);
11431  if (from == 0 && cons_string->second() == first) {
11432  CopyChars(sink + boundary, sink, boundary);
11433  return;
11434  }
11435  sink += boundary - from;
11436  from = 0;
11437  } else {
11438  from -= boundary;
11439  }
11440  to -= boundary;
11441  source = cons_string->second();
11442  } else {
11443  // Left hand side is longer. Recurse over right.
11444  if (to > boundary) {
11445  String second = cons_string->second();
11446  // When repeatedly appending to a string, we get a cons string that
11447  // is unbalanced to the left, a list, essentially. We inline the
11448  // common case of sequential one-byte right child.
11449  if (to - boundary == 1) {
11450  sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
11451  } else if (second->IsSeqOneByteString()) {
11452  CopyChars(sink + boundary - from,
11453  SeqOneByteString::cast(second)->GetChars(),
11454  to - boundary);
11455  } else {
11456  WriteToFlat(second,
11457  sink + boundary - from,
11458  0,
11459  to - boundary);
11460  }
11461  to = boundary;
11462  }
11463  source = first;
11464  }
11465  break;
11466  }
11467  case kOneByteStringTag | kSlicedStringTag:
11468  case kTwoByteStringTag | kSlicedStringTag: {
11469  SlicedString slice = SlicedString::cast(source);
11470  unsigned offset = slice->offset();
11471  WriteToFlat(slice->parent(), sink, from + offset, to + offset);
11472  return;
11473  }
11474  case kOneByteStringTag | kThinStringTag:
11475  case kTwoByteStringTag | kThinStringTag:
11476  source = ThinString::cast(source)->actual();
11477  break;
11478  }
11479  }
11480 }
11481 
11482 template <typename SourceChar>
11483 static void CalculateLineEndsImpl(Isolate* isolate, std::vector<int>* line_ends,
11484  Vector<const SourceChar> src,
11485  bool include_ending_line) {
11486  const int src_len = src.length();
11487  for (int i = 0; i < src_len - 1; i++) {
11488  SourceChar current = src[i];
11489  SourceChar next = src[i + 1];
11490  if (IsLineTerminatorSequence(current, next)) line_ends->push_back(i);
11491  }
11492 
11493  if (src_len > 0 && IsLineTerminatorSequence(src[src_len - 1], 0)) {
11494  line_ends->push_back(src_len - 1);
11495  }
11496  if (include_ending_line) {
11497  // Include one character beyond the end of script. The rewriter uses that
11498  // position for the implicit return statement.
11499  line_ends->push_back(src_len);
11500  }
11501 }
11502 
11503 Handle<FixedArray> String::CalculateLineEnds(Isolate* isolate,
11504  Handle<String> src,
11505  bool include_ending_line) {
11506  src = Flatten(isolate, src);
11507  // Rough estimate of line count based on a roughly estimated average
11508  // length of (unpacked) code.
11509  int line_count_estimate = src->length() >> 4;
11510  std::vector<int> line_ends;
11511  line_ends.reserve(line_count_estimate);
11512  { DisallowHeapAllocation no_allocation; // ensure vectors stay valid.
11513  // Dispatch on type of strings.
11514  String::FlatContent content = src->GetFlatContent();
11515  DCHECK(content.IsFlat());
11516  if (content.IsOneByte()) {
11517  CalculateLineEndsImpl(isolate,
11518  &line_ends,
11519  content.ToOneByteVector(),
11520  include_ending_line);
11521  } else {
11522  CalculateLineEndsImpl(isolate,
11523  &line_ends,
11524  content.ToUC16Vector(),
11525  include_ending_line);
11526  }
11527  }
11528  int line_count = static_cast<int>(line_ends.size());
11529  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
11530  for (int i = 0; i < line_count; i++) {
11531  array->set(i, Smi::FromInt(line_ends[i]));
11532  }
11533  return array;
11534 }
11535 
11536 namespace {
11537 
11538 template <typename sinkchar>
11539 void WriteFixedArrayToFlat(FixedArray fixed_array, int length, String separator,
11540  sinkchar* sink, int sink_length) {
11541  DisallowHeapAllocation no_allocation;
11542  CHECK_GT(length, 0);
11543  CHECK_LE(length, fixed_array->length());
11544 #ifdef DEBUG
11545  sinkchar* sink_end = sink + sink_length;
11546 #endif
11547 
11548  const int separator_length = separator->length();
11549  const bool use_one_byte_separator_fast_path =
11550  separator_length == 1 && sizeof(sinkchar) == 1 &&
11551  StringShape(separator).IsSequentialOneByte();
11552  uint8_t separator_one_char;
11553  if (use_one_byte_separator_fast_path) {
11554  CHECK(StringShape(separator).IsSequentialOneByte());
11555  CHECK_EQ(separator->length(), 1);
11556  separator_one_char = SeqOneByteString::cast(separator)->GetChars()[0];
11557  }
11558 
11559  uint32_t num_separators = 0;
11560  for (int i = 0; i < length; i++) {
11561  Object* element = fixed_array->get(i);
11562  const bool element_is_separator_sequence = element->IsSmi();
11563 
11564  // If element is a Smi, it represents the number of separators to write.
11565  if (V8_UNLIKELY(element_is_separator_sequence)) {
11566  CHECK(element->ToUint32(&num_separators));
11567  // Verify that Smis (number of separators) only occur when necessary:
11568  // 1) at the beginning
11569  // 2) at the end
11570  // 3) when the number of separators > 1
11571  // - It is assumed that consecutive Strings will have one separator,
11572  // so there is no need for a Smi.
11573  DCHECK(i == 0 || i == length - 1 || num_separators > 1);
11574  }
11575 
11576  // Write separator(s) if necessary.
11577  if (num_separators > 0 && separator_length > 0) {
11578  // TODO(pwong): Consider doubling strategy employed by runtime-strings.cc
11579  // WriteRepeatToFlat().
11580  // Fast path for single character, single byte separators.
11581  if (use_one_byte_separator_fast_path) {
11582  DCHECK_LE(sink + num_separators, sink_end);
11583  memset(sink, separator_one_char, num_separators);
11584  DCHECK_EQ(separator_length, 1);
11585  sink += num_separators;
11586  } else {
11587  for (uint32_t j = 0; j < num_separators; j++) {
11588  DCHECK_LE(sink + separator_length, sink_end);
11589  String::WriteToFlat(separator, sink, 0, separator_length);
11590  sink += separator_length;
11591  }
11592  }
11593  }
11594 
11595  if (V8_UNLIKELY(element_is_separator_sequence)) {
11596  num_separators = 0;
11597  } else {
11598  DCHECK(element->IsString());
11599  String string = String::cast(element);
11600  const int string_length = string->length();
11601 
11602  DCHECK(string_length == 0 || sink < sink_end);
11603  String::WriteToFlat(string, sink, 0, string_length);
11604  sink += string_length;
11605 
11606  // Next string element, needs at least one separator preceding it.
11607  num_separators = 1;
11608  }
11609  }
11610 
11611  // Verify we have written to the end of the sink.
11612  DCHECK_EQ(sink, sink_end);
11613 }
11614 
11615 } // namespace
11616 
11617 // static
11618 Address JSArray::ArrayJoinConcatToSequentialString(Isolate* isolate,
11619  Address raw_fixed_array,
11620  intptr_t length,
11621  Address raw_separator,
11622  Address raw_dest) {
11623  DisallowHeapAllocation no_allocation;
11624  DisallowJavascriptExecution no_js(isolate);
11625  FixedArray fixed_array = FixedArray::cast(ObjectPtr(raw_fixed_array));
11626  String separator = String::cast(ObjectPtr(raw_separator));
11627  String dest = String::cast(ObjectPtr(raw_dest));
11628  DCHECK(fixed_array->IsFixedArray());
11629  DCHECK(StringShape(dest).IsSequentialOneByte() ||
11630  StringShape(dest).IsSequentialTwoByte());
11631 
11632  if (StringShape(dest).IsSequentialOneByte()) {
11633  WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
11634  SeqOneByteString::cast(dest)->GetChars(),
11635  dest->length());
11636  } else {
11637  DCHECK(StringShape(dest).IsSequentialTwoByte());
11638  WriteFixedArrayToFlat(fixed_array, static_cast<int>(length), separator,
11639  SeqTwoByteString::cast(dest)->GetChars(),
11640  dest->length());
11641  }
11642  return dest->ptr();
11643 }
11644 
11645 // Compares the contents of two strings by reading and comparing
11646 // int-sized blocks of characters.
11647 template <typename Char>
11648 static inline bool CompareRawStringContents(const Char* const a,
11649  const Char* const b,
11650  int length) {
11651  return CompareChars(a, b, length) == 0;
11652 }
11653 
11654 
11655 template<typename Chars1, typename Chars2>
11657  public:
11658  static inline bool compare(const Chars1* a, const Chars2* b, int len) {
11659  DCHECK(sizeof(Chars1) != sizeof(Chars2));
11660  for (int i = 0; i < len; i++) {
11661  if (a[i] != b[i]) {
11662  return false;
11663  }
11664  }
11665  return true;
11666  }
11667 };
11668 
11669 
11670 template<>
11671 class RawStringComparator<uint16_t, uint16_t> {
11672  public:
11673  static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
11674  return CompareRawStringContents(a, b, len);
11675  }
11676 };
11677 
11678 
11679 template<>
11680 class RawStringComparator<uint8_t, uint8_t> {
11681  public:
11682  static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
11683  return CompareRawStringContents(a, b, len);
11684  }
11685 };
11686 
11687 
11689  class State {
11690  public:
11691  State() : is_one_byte_(true), length_(0), buffer8_(nullptr) {}
11692 
11693  void Init(String string) {
11694  ConsString cons_string = String::VisitFlat(this, string);
11695  iter_.Reset(cons_string);
11696  if (!cons_string.is_null()) {
11697  int offset;
11698  string = iter_.Next(&offset);
11699  String::VisitFlat(this, string, offset);
11700  }
11701  }
11702 
11703  inline void VisitOneByteString(const uint8_t* chars, int length) {
11704  is_one_byte_ = true;
11705  buffer8_ = chars;
11706  length_ = length;
11707  }
11708 
11709  inline void VisitTwoByteString(const uint16_t* chars, int length) {
11710  is_one_byte_ = false;
11711  buffer16_ = chars;
11712  length_ = length;
11713  }
11714 
11715  void Advance(int consumed) {
11716  DCHECK(consumed <= length_);
11717  // Still in buffer.
11718  if (length_ != consumed) {
11719  if (is_one_byte_) {
11720  buffer8_ += consumed;
11721  } else {
11722  buffer16_ += consumed;
11723  }
11724  length_ -= consumed;
11725  return;
11726  }
11727  // Advance state.
11728  int offset;
11729  String next = iter_.Next(&offset);
11730  DCHECK_EQ(0, offset);
11731  DCHECK(!next.is_null());
11732  String::VisitFlat(this, next);
11733  }
11734 
11735  ConsStringIterator iter_;
11736  bool is_one_byte_;
11737  int length_;
11738  union {
11739  const uint8_t* buffer8_;
11740  const uint16_t* buffer16_;
11741  };
11742 
11743  private:
11744  DISALLOW_COPY_AND_ASSIGN(State);
11745  };
11746 
11747  public:
11748  inline StringComparator() = default;
11749 
11750  template<typename Chars1, typename Chars2>
11751  static inline bool Equals(State* state_1, State* state_2, int to_check) {
11752  const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
11753  const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
11754  return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
11755  }
11756 
11757  bool Equals(String string_1, String string_2) {
11758  int length = string_1->length();
11759  state_1_.Init(string_1);
11760  state_2_.Init(string_2);
11761  while (true) {
11762  int to_check = Min(state_1_.length_, state_2_.length_);
11763  DCHECK(to_check > 0 && to_check <= length);
11764  bool is_equal;
11765  if (state_1_.is_one_byte_) {
11766  if (state_2_.is_one_byte_) {
11767  is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
11768  } else {
11769  is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
11770  }
11771  } else {
11772  if (state_2_.is_one_byte_) {
11773  is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
11774  } else {
11775  is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
11776  }
11777  }
11778  // Looping done.
11779  if (!is_equal) return false;
11780  length -= to_check;
11781  // Exit condition. Strings are equal.
11782  if (length == 0) return true;
11783  state_1_.Advance(to_check);
11784  state_2_.Advance(to_check);
11785  }
11786  }
11787 
11788  private:
11789  State state_1_;
11790  State state_2_;
11791 
11792  DISALLOW_COPY_AND_ASSIGN(StringComparator);
11793 };
11794 
11795 bool String::SlowEquals(String other) {
11796  DisallowHeapAllocation no_gc;
11797  // Fast check: negative check with lengths.
11798  int len = length();
11799  if (len != other->length()) return false;
11800  if (len == 0) return true;
11801 
11802  // Fast check: if at least one ThinString is involved, dereference it/them
11803  // and restart.
11804  if (this->IsThinString() || other->IsThinString()) {
11805  if (other->IsThinString()) other = ThinString::cast(other)->actual();
11806  if (this->IsThinString()) {
11807  return ThinString::cast(*this)->actual()->Equals(other);
11808  } else {
11809  return this->Equals(other);
11810  }
11811  }
11812 
11813  // Fast check: if hash code is computed for both strings
11814  // a fast negative check can be performed.
11815  if (HasHashCode() && other->HasHashCode()) {
11816 #ifdef ENABLE_SLOW_DCHECKS
11817  if (FLAG_enable_slow_asserts) {
11818  if (Hash() != other->Hash()) {
11819  bool found_difference = false;
11820  for (int i = 0; i < len; i++) {
11821  if (Get(i) != other->Get(i)) {
11822  found_difference = true;
11823  break;
11824  }
11825  }
11826  DCHECK(found_difference);
11827  }
11828  }
11829 #endif
11830  if (Hash() != other->Hash()) return false;
11831  }
11832 
11833  // We know the strings are both non-empty. Compare the first chars
11834  // before we try to flatten the strings.
11835  if (this->Get(0) != other->Get(0)) return false;
11836 
11837  if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
11838  const uint8_t* str1 = SeqOneByteString::cast(*this)->GetChars();
11839  const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
11840  return CompareRawStringContents(str1, str2, len);
11841  }
11842 
11843  StringComparator comparator;
11844  return comparator.Equals(*this, other);
11845 }
11846 
11847 bool String::SlowEquals(Isolate* isolate, Handle<String> one,
11848  Handle<String> two) {
11849  // Fast check: negative check with lengths.
11850  int one_length = one->length();
11851  if (one_length != two->length()) return false;
11852  if (one_length == 0) return true;
11853 
11854  // Fast check: if at least one ThinString is involved, dereference it/them
11855  // and restart.
11856  if (one->IsThinString() || two->IsThinString()) {
11857  if (one->IsThinString())
11858  one = handle(ThinString::cast(*one)->actual(), isolate);
11859  if (two->IsThinString())
11860  two = handle(ThinString::cast(*two)->actual(), isolate);
11861  return String::Equals(isolate, one, two);
11862  }
11863 
11864  // Fast check: if hash code is computed for both strings
11865  // a fast negative check can be performed.
11866  if (one->HasHashCode() && two->HasHashCode()) {
11867 #ifdef ENABLE_SLOW_DCHECKS
11868  if (FLAG_enable_slow_asserts) {
11869  if (one->Hash() != two->Hash()) {
11870  bool found_difference = false;
11871  for (int i = 0; i < one_length; i++) {
11872  if (one->Get(i) != two->Get(i)) {
11873  found_difference = true;
11874  break;
11875  }
11876  }
11877  DCHECK(found_difference);
11878  }
11879  }
11880 #endif
11881  if (one->Hash() != two->Hash()) return false;
11882  }
11883 
11884  // We know the strings are both non-empty. Compare the first chars
11885  // before we try to flatten the strings.
11886  if (one->Get(0) != two->Get(0)) return false;
11887 
11888  one = String::Flatten(isolate, one);
11889  two = String::Flatten(isolate, two);
11890 
11891  DisallowHeapAllocation no_gc;
11892  String::FlatContent flat1 = one->GetFlatContent();
11893  String::FlatContent flat2 = two->GetFlatContent();
11894 
11895  if (flat1.IsOneByte() && flat2.IsOneByte()) {
11896  return CompareRawStringContents(flat1.ToOneByteVector().start(),
11897  flat2.ToOneByteVector().start(),
11898  one_length);
11899  } else {
11900  for (int i = 0; i < one_length; i++) {
11901  if (flat1.Get(i) != flat2.Get(i)) return false;
11902  }
11903  return true;
11904  }
11905 }
11906 
11907 
11908 // static
11909 ComparisonResult String::Compare(Isolate* isolate, Handle<String> x,
11910  Handle<String> y) {
11911  // A few fast case tests before we flatten.
11912  if (x.is_identical_to(y)) {
11913  return ComparisonResult::kEqual;
11914  } else if (y->length() == 0) {
11915  return x->length() == 0 ? ComparisonResult::kEqual
11916  : ComparisonResult::kGreaterThan;
11917  } else if (x->length() == 0) {
11918  return ComparisonResult::kLessThan;
11919  }
11920 
11921  int const d = x->Get(0) - y->Get(0);
11922  if (d < 0) {
11923  return ComparisonResult::kLessThan;
11924  } else if (d > 0) {
11925  return ComparisonResult::kGreaterThan;
11926  }
11927 
11928  // Slow case.
11929  x = String::Flatten(isolate, x);
11930  y = String::Flatten(isolate, y);
11931 
11932  DisallowHeapAllocation no_gc;
11933  ComparisonResult result = ComparisonResult::kEqual;
11934  int prefix_length = x->length();
11935  if (y->length() < prefix_length) {
11936  prefix_length = y->length();
11937  result = ComparisonResult::kGreaterThan;
11938  } else if (y->length() > prefix_length) {
11939  result = ComparisonResult::kLessThan;
11940  }
11941  int r;
11942  String::FlatContent x_content = x->GetFlatContent();
11943  String::FlatContent y_content = y->GetFlatContent();
11944  if (x_content.IsOneByte()) {
11945  Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
11946  if (y_content.IsOneByte()) {
11947  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11948  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11949  } else {
11950  Vector<const uc16> y_chars = y_content.ToUC16Vector();
11951  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11952  }
11953  } else {
11954  Vector<const uc16> x_chars = x_content.ToUC16Vector();
11955  if (y_content.IsOneByte()) {
11956  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11957  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11958  } else {
11959  Vector<const uc16> y_chars = y_content.ToUC16Vector();
11960  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11961  }
11962  }
11963  if (r < 0) {
11964  result = ComparisonResult::kLessThan;
11965  } else if (r > 0) {
11966  result = ComparisonResult::kGreaterThan;
11967  }
11968  return result;
11969 }
11970 
11971 Object* String::IndexOf(Isolate* isolate, Handle<Object> receiver,
11972  Handle<Object> search, Handle<Object> position) {
11973  if (receiver->IsNullOrUndefined(isolate)) {
11974  THROW_NEW_ERROR_RETURN_FAILURE(
11975  isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
11976  isolate->factory()->NewStringFromAsciiChecked(
11977  "String.prototype.indexOf")));
11978  }
11979  Handle<String> receiver_string;
11980  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
11981  Object::ToString(isolate, receiver));
11982 
11983  Handle<String> search_string;
11984  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
11985  Object::ToString(isolate, search));
11986 
11987  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
11988  Object::ToInteger(isolate, position));
11989 
11990  uint32_t index = receiver_string->ToValidIndex(*position);
11991  return Smi::FromInt(
11992  String::IndexOf(isolate, receiver_string, search_string, index));
11993 }
11994 
11995 namespace {
11996 
11997 template <typename T>
11998 int SearchString(Isolate* isolate, String::FlatContent receiver_content,
11999  Vector<T> pat_vector, int start_index) {
12000  if (receiver_content.IsOneByte()) {
12001  return SearchString(isolate, receiver_content.ToOneByteVector(), pat_vector,
12002  start_index);
12003  }
12004  return SearchString(isolate, receiver_content.ToUC16Vector(), pat_vector,
12005  start_index);
12006 }
12007 
12008 } // namespace
12009 
12010 int String::IndexOf(Isolate* isolate, Handle<String> receiver,
12011  Handle<String> search, int start_index) {
12012  DCHECK_LE(0, start_index);
12013  DCHECK(start_index <= receiver->length());
12014 
12015  uint32_t search_length = search->length();
12016  if (search_length == 0) return start_index;
12017 
12018  uint32_t receiver_length = receiver->length();
12019  if (start_index + search_length > receiver_length) return -1;
12020 
12021  receiver = String::Flatten(isolate, receiver);
12022  search = String::Flatten(isolate, search);
12023 
12024  DisallowHeapAllocation no_gc; // ensure vectors stay valid
12025  // Extract flattened substrings of cons strings before getting encoding.
12026  String::FlatContent receiver_content = receiver->GetFlatContent();
12027  String::FlatContent search_content = search->GetFlatContent();
12028 
12029  // dispatch on type of strings
12030  if (search_content.IsOneByte()) {
12031  Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
12032  return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
12033  start_index);
12034  }
12035  Vector<const uc16> pat_vector = search_content.ToUC16Vector();
12036  return SearchString<const uc16>(isolate, receiver_content, pat_vector,
12037  start_index);
12038 }
12039 
12040 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
12041  Handle<String> replacement,
12042  int start_index) {
12043  DCHECK_GE(start_index, 0);
12044 
12045  Factory* factory = isolate->factory();
12046 
12047  const int replacement_length = replacement->length();
12048  const int captures_length = match->CaptureCount();
12049 
12050  replacement = String::Flatten(isolate, replacement);
12051 
12052  Handle<String> dollar_string =
12053  factory->LookupSingleCharacterStringFromCode('$');
12054  int next_dollar_ix =
12055  String::IndexOf(isolate, replacement, dollar_string, start_index);
12056  if (next_dollar_ix < 0) {
12057  return replacement;
12058  }
12059 
12060  IncrementalStringBuilder builder(isolate);
12061 
12062  if (next_dollar_ix > 0) {
12063  builder.AppendString(factory->NewSubString(replacement, 0, next_dollar_ix));
12064  }
12065 
12066  while (true) {
12067  const int peek_ix = next_dollar_ix + 1;
12068  if (peek_ix >= replacement_length) {
12069  builder.AppendCharacter('$');
12070  return builder.Finish();
12071  }
12072 
12073  int continue_from_ix = -1;
12074  const uint16_t peek = replacement->Get(peek_ix);
12075  switch (peek) {
12076  case '$': // $$
12077  builder.AppendCharacter('$');
12078  continue_from_ix = peek_ix + 1;
12079  break;
12080  case '&': // $& - match
12081  builder.AppendString(match->GetMatch());
12082  continue_from_ix = peek_ix + 1;
12083  break;
12084  case '`': // $` - prefix
12085  builder.AppendString(match->GetPrefix());
12086  continue_from_ix = peek_ix + 1;
12087  break;
12088  case '\'': // $' - suffix
12089  builder.AppendString(match->GetSuffix());
12090  continue_from_ix = peek_ix + 1;
12091  break;
12092  case '0':
12093  case '1':
12094  case '2':
12095  case '3':
12096  case '4':
12097  case '5':
12098  case '6':
12099  case '7':
12100  case '8':
12101  case '9': {
12102  // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
12103  int scaled_index = (peek - '0');
12104  int advance = 1;
12105 
12106  if (peek_ix + 1 < replacement_length) {
12107  const uint16_t next_peek = replacement->Get(peek_ix + 1);
12108  if (next_peek >= '0' && next_peek <= '9') {
12109  const int new_scaled_index = scaled_index * 10 + (next_peek - '0');
12110  if (new_scaled_index < captures_length) {
12111  scaled_index = new_scaled_index;
12112  advance = 2;
12113  }
12114  }
12115  }
12116 
12117  if (scaled_index == 0 || scaled_index >= captures_length) {
12118  builder.AppendCharacter('$');
12119  continue_from_ix = peek_ix;
12120  break;
12121  }
12122 
12123  bool capture_exists;
12124  Handle<String> capture;
12125  ASSIGN_RETURN_ON_EXCEPTION(
12126  isolate, capture, match->GetCapture(scaled_index, &capture_exists),
12127  String);
12128  if (capture_exists) builder.AppendString(capture);
12129  continue_from_ix = peek_ix + advance;
12130  break;
12131  }
12132  case '<': { // $<name> - named capture
12133  typedef String::Match::CaptureState CaptureState;
12134 
12135  if (!match->HasNamedCaptures()) {
12136  builder.AppendCharacter('$');
12137  continue_from_ix = peek_ix;
12138  break;
12139  }
12140 
12141  Handle<String> bracket_string =
12142  factory->LookupSingleCharacterStringFromCode('>');
12143  const int closing_bracket_ix =
12144  String::IndexOf(isolate, replacement, bracket_string, peek_ix + 1);
12145 
12146  if (closing_bracket_ix == -1) {
12147  // No closing bracket was found, treat '$<' as a string literal.
12148  builder.AppendCharacter('$');
12149  continue_from_ix = peek_ix;
12150  break;
12151  }
12152 
12153  Handle<String> capture_name =
12154  factory->NewSubString(replacement, peek_ix + 1, closing_bracket_ix);
12155  Handle<String> capture;
12156  CaptureState capture_state;
12157  ASSIGN_RETURN_ON_EXCEPTION(
12158  isolate, capture,
12159  match->GetNamedCapture(capture_name, &capture_state), String);
12160 
12161  switch (capture_state) {
12162  case CaptureState::INVALID:
12163  case CaptureState::UNMATCHED:
12164  break;
12165  case CaptureState::MATCHED:
12166  builder.AppendString(capture);
12167  break;
12168  }
12169 
12170  continue_from_ix = closing_bracket_ix + 1;
12171  break;
12172  }
12173  default:
12174  builder.AppendCharacter('$');
12175  continue_from_ix = peek_ix;
12176  break;
12177  }
12178 
12179  // Go the the next $ in the replacement.
12180  // TODO(jgruber): Single-char lookups could be much more efficient.
12181  DCHECK_NE(continue_from_ix, -1);
12182  next_dollar_ix =
12183  String::IndexOf(isolate, replacement, dollar_string, continue_from_ix);
12184 
12185  // Return if there are no more $ characters in the replacement. If we
12186  // haven't reached the end, we need to append the suffix.
12187  if (next_dollar_ix < 0) {
12188  if (continue_from_ix < replacement_length) {
12189  builder.AppendString(factory->NewSubString(
12190  replacement, continue_from_ix, replacement_length));
12191  }
12192  return builder.Finish();
12193  }
12194 
12195  // Append substring between the previous and the next $ character.
12196  if (next_dollar_ix > continue_from_ix) {
12197  builder.AppendString(
12198  factory->NewSubString(replacement, continue_from_ix, next_dollar_ix));
12199  }
12200  }
12201 
12202  UNREACHABLE();
12203 }
12204 
12205 namespace { // for String.Prototype.lastIndexOf
12206 
12207 template <typename schar, typename pchar>
12208 int StringMatchBackwards(Vector<const schar> subject,
12209  Vector<const pchar> pattern, int idx) {
12210  int pattern_length = pattern.length();
12211  DCHECK_GE(pattern_length, 1);
12212  DCHECK(idx + pattern_length <= subject.length());
12213 
12214  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
12215  for (int i = 0; i < pattern_length; i++) {
12216  uc16 c = pattern[i];
12217  if (c > String::kMaxOneByteCharCode) {
12218  return -1;
12219  }
12220  }
12221  }
12222 
12223  pchar pattern_first_char = pattern[0];
12224  for (int i = idx; i >= 0; i--) {
12225  if (subject[i] != pattern_first_char) continue;
12226  int j = 1;
12227  while (j < pattern_length) {
12228  if (pattern[j] != subject[i + j]) {
12229  break;
12230  }
12231  j++;
12232  }
12233  if (j == pattern_length) {
12234  return i;
12235  }
12236  }
12237  return -1;
12238 }
12239 
12240 } // namespace
12241 
12242 Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
12243  Handle<Object> search, Handle<Object> position) {
12244  if (receiver->IsNullOrUndefined(isolate)) {
12245  THROW_NEW_ERROR_RETURN_FAILURE(
12246  isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
12247  isolate->factory()->NewStringFromAsciiChecked(
12248  "String.prototype.lastIndexOf")));
12249  }
12250  Handle<String> receiver_string;
12251  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
12252  Object::ToString(isolate, receiver));
12253 
12254  Handle<String> search_string;
12255  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
12256  Object::ToString(isolate, search));
12257 
12258  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
12259  Object::ToNumber(isolate, position));
12260 
12261  uint32_t start_index;
12262 
12263  if (position->IsNaN()) {
12264  start_index = receiver_string->length();
12265  } else {
12266  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
12267  Object::ToInteger(isolate, position));
12268  start_index = receiver_string->ToValidIndex(*position);
12269  }
12270 
12271  uint32_t pattern_length = search_string->length();
12272  uint32_t receiver_length = receiver_string->length();
12273 
12274  if (start_index + pattern_length > receiver_length) {
12275  start_index = receiver_length - pattern_length;
12276  }
12277 
12278  if (pattern_length == 0) {
12279  return Smi::FromInt(start_index);
12280  }
12281 
12282  receiver_string = String::Flatten(isolate, receiver_string);
12283  search_string = String::Flatten(isolate, search_string);
12284 
12285  int last_index = -1;
12286  DisallowHeapAllocation no_gc; // ensure vectors stay valid
12287 
12288  String::FlatContent receiver_content = receiver_string->GetFlatContent();
12289  String::FlatContent search_content = search_string->GetFlatContent();
12290 
12291  if (search_content.IsOneByte()) {
12292  Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
12293  if (receiver_content.IsOneByte()) {
12294  last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
12295  pat_vector, start_index);
12296  } else {
12297  last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
12298  pat_vector, start_index);
12299  }
12300  } else {
12301  Vector<const uc16> pat_vector = search_content.ToUC16Vector();
12302  if (receiver_content.IsOneByte()) {
12303  last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
12304  pat_vector, start_index);
12305  } else {
12306  last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
12307  pat_vector, start_index);
12308  }
12309  }
12310  return Smi::FromInt(last_index);
12311 }
12312 
12313 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
12314  int slen = length();
12315  // Can't check exact length equality, but we can check bounds.
12316  int str_len = str.length();
12317  if (!allow_prefix_match &&
12318  (str_len < slen ||
12319  str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
12320  return false;
12321  }
12322 
12323  int i = 0;
12325  while (i < slen && !it.Done()) {
12326  if (Get(i++) != *it) return false;
12327  ++it;
12328  }
12329 
12330  return (allow_prefix_match || i == slen) && it.Done();
12331 }
12332 
12333 template <>
12334 bool String::IsEqualTo(Vector<const uint8_t> str) {
12335  return IsOneByteEqualTo(str);
12336 }
12337 
12338 template <>
12339 bool String::IsEqualTo(Vector<const uc16> str) {
12340  return IsTwoByteEqualTo(str);
12341 }
12342 
12343 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
12344  int slen = length();
12345  if (str.length() != slen) return false;
12346  DisallowHeapAllocation no_gc;
12347  FlatContent content = GetFlatContent();
12348  if (content.IsOneByte()) {
12349  return CompareChars(content.ToOneByteVector().start(),
12350  str.start(), slen) == 0;
12351  }
12352  return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
12353 }
12354 
12355 
12356 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
12357  int slen = length();
12358  if (str.length() != slen) return false;
12359  DisallowHeapAllocation no_gc;
12360  FlatContent content = GetFlatContent();
12361  if (content.IsOneByte()) {
12362  return CompareChars(content.ToOneByteVector().start(), str.start(), slen) ==
12363  0;
12364  }
12365  return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
12366 }
12367 
12368 uint32_t String::ComputeAndSetHash(Isolate* isolate) {
12369  DisallowHeapAllocation no_gc;
12370  // Should only be called if hash code has not yet been computed.
12371  DCHECK(!HasHashCode());
12372 
12373  // Store the hash code in the object.
12374  uint32_t field =
12375  IteratingStringHasher::Hash(*this, isolate->heap()->HashSeed());
12376  set_hash_field(field);
12377 
12378  // Check the hash code is there.
12379  DCHECK(HasHashCode());
12380  uint32_t result = field >> kHashShift;
12381  DCHECK_NE(result, 0); // Ensure that the hash value of 0 is never computed.
12382  return result;
12383 }
12384 
12385 
12386 bool String::ComputeArrayIndex(uint32_t* index) {
12387  int length = this->length();
12388  if (length == 0 || length > kMaxArrayIndexSize) return false;
12389  StringCharacterStream stream(*this);
12390  return StringToArrayIndex(&stream, index);
12391 }
12392 
12393 
12394 bool String::SlowAsArrayIndex(uint32_t* index) {
12395  DisallowHeapAllocation no_gc;
12396  if (length() <= kMaxCachedArrayIndexLength) {
12397  Hash(); // force computation of hash code
12398  uint32_t field = hash_field();
12399  if ((field & kIsNotArrayIndexMask) != 0) return false;
12400  // Isolate the array index form the full hash field.
12401  *index = ArrayIndexValueBits::decode(field);
12402  return true;
12403  } else {
12404  return ComputeArrayIndex(index);
12405  }
12406 }
12407 
12408 
12409 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
12410  if (new_length == 0) return string->GetReadOnlyRoots().empty_string_handle();
12411 
12412  int new_size, old_size;
12413  int old_length = string->length();
12414  if (old_length <= new_length) return string;
12415 
12416  if (string->IsSeqOneByteString()) {
12417  old_size = SeqOneByteString::SizeFor(old_length);
12418  new_size = SeqOneByteString::SizeFor(new_length);
12419  } else {
12420  DCHECK(string->IsSeqTwoByteString());
12421  old_size = SeqTwoByteString::SizeFor(old_length);
12422  new_size = SeqTwoByteString::SizeFor(new_length);
12423  }
12424 
12425  int delta = old_size - new_size;
12426 
12427  Address start_of_string = string->address();
12428  DCHECK_OBJECT_ALIGNED(start_of_string);
12429  DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
12430 
12431  Heap* heap = Heap::FromWritableHeapObject(*string);
12432  // Sizes are pointer size aligned, so that we can use filler objects
12433  // that are a multiple of pointer size.
12434  heap->CreateFillerObjectAt(start_of_string + new_size, delta,
12435  ClearRecordedSlots::kNo);
12436  // We are storing the new length using release store after creating a filler
12437  // for the left-over space to avoid races with the sweeper thread.
12438  string->synchronized_set_length(new_length);
12439 
12440  return string;
12441 }
12442 
12443 void SeqOneByteString::clear_padding() {
12444  int data_size = SeqString::kHeaderSize + length() * kOneByteSize;
12445  memset(reinterpret_cast<void*>(address() + data_size), 0,
12446  SizeFor(length()) - data_size);
12447 }
12448 
12449 void SeqTwoByteString::clear_padding() {
12450  int data_size = SeqString::kHeaderSize + length() * kUC16Size;
12451  memset(reinterpret_cast<void*>(address() + data_size), 0,
12452  SizeFor(length()) - data_size);
12453 }
12454 
12455 int ExternalString::ExternalPayloadSize() const {
12456  int length_multiplier = IsTwoByteRepresentation() ? i::kShortSize : kCharSize;
12457  return length() * length_multiplier;
12458 }
12459 
12460 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
12461  // For array indexes mix the length into the hash as an array index could
12462  // be zero.
12463  DCHECK_GT(length, 0);
12464  DCHECK_LE(length, String::kMaxArrayIndexSize);
12465  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
12466  (1 << String::kArrayIndexValueBits));
12467 
12468  value <<= String::ArrayIndexValueBits::kShift;
12469  value |= length << String::ArrayIndexLengthBits::kShift;
12470 
12471  DCHECK_EQ(value & String::kIsNotArrayIndexMask, 0);
12472  DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
12473  Name::ContainsCachedArrayIndex(value));
12474  return value;
12475 }
12476 
12477 
12478 uint32_t StringHasher::GetHashField() {
12479  if (length_ <= String::kMaxHashCalcLength) {
12480  if (is_array_index_) {
12481  return MakeArrayIndexHash(array_index_, length_);
12482  }
12483  return (GetHashCore(raw_running_hash_) << String::kHashShift) |
12484  String::kIsNotArrayIndexMask;
12485  } else {
12486  return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
12487  }
12488 }
12489 
12490 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
12491  int* utf16_length_out) {
12492  int vector_length = chars.length();
12493  // Handle some edge cases
12494  if (vector_length <= 1) {
12495  DCHECK(vector_length == 0 ||
12496  static_cast<uint8_t>(chars.start()[0]) <=
12497  unibrow::Utf8::kMaxOneByteChar);
12498  *utf16_length_out = vector_length;
12499  return HashSequentialString(chars.start(), vector_length, seed);
12500  }
12501 
12502  // Start with a fake length which won't affect computation.
12503  // It will be updated later.
12504  StringHasher hasher(String::kMaxArrayIndexSize, seed);
12505  DCHECK(hasher.is_array_index_);
12506 
12508  int utf16_length = 0;
12509  bool is_index = true;
12510 
12511  while (utf16_length < String::kMaxHashCalcLength && !it.Done()) {
12512  utf16_length++;
12513  uint16_t c = *it;
12514  ++it;
12515  hasher.AddCharacter(c);
12516  if (is_index) is_index = hasher.UpdateIndex(c);
12517  }
12518 
12519  // Now that hashing is done, we just need to calculate utf16_length
12520  while (!it.Done()) {
12521  ++it;
12522  utf16_length++;
12523  }
12524 
12525  *utf16_length_out = utf16_length;
12526  // Must set length here so that hash computation is correct.
12527  hasher.length_ = utf16_length;
12528  return hasher.GetHashField();
12529 }
12530 
12531 void IteratingStringHasher::VisitConsString(ConsString cons_string) {
12532  // Run small ConsStrings through ConsStringIterator.
12533  if (cons_string->length() < 64) {
12534  ConsStringIterator iter(cons_string);
12535  int offset;
12536  for (String string = iter.Next(&offset); !string.is_null();
12537  string = iter.Next(&offset)) {
12538  DCHECK_EQ(0, offset);
12539  String::VisitFlat(this, string, 0);
12540  }
12541  return;
12542  }
12543  // Slow case.
12544  const int max_length = String::kMaxHashCalcLength;
12545  int length = std::min(cons_string->length(), max_length);
12546  if (cons_string->HasOnlyOneByteChars()) {
12547  uint8_t* buffer = new uint8_t[length];
12548  String::WriteToFlat(cons_string, buffer, 0, length);
12549  AddCharacters(buffer, length);
12550  delete[] buffer;
12551  } else {
12552  uint16_t* buffer = new uint16_t[length];
12553  String::WriteToFlat(cons_string, buffer, 0, length);
12554  AddCharacters(buffer, length);
12555  delete[] buffer;
12556  }
12557 }
12558 
12559 void String::PrintOn(FILE* file) {
12560  int length = this->length();
12561  for (int i = 0; i < length; i++) {
12562  PrintF(file, "%c", Get(i));
12563  }
12564 }
12565 
12566 
12567 int Map::Hash() {
12568  // For performance reasons we only hash the 3 most variable fields of a map:
12569  // constructor, prototype and bit_field2. For predictability reasons we
12570  // use objects' offsets in respective pages for hashing instead of raw
12571  // addresses.
12572 
12573  // Shift away the tag.
12574  int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
12575 
12576  // XOR-ing the prototype and constructor directly yields too many zero bits
12577  // when the two pointers are close (which is fairly common).
12578  // To avoid this we shift the prototype bits relatively to the constructor.
12579  hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
12580 
12581  return hash ^ (hash >> 16) ^ bit_field2();
12582 }
12583 
12584 
12585 namespace {
12586 
12587 bool CheckEquivalent(const Map first, const Map second) {
12588  return first->GetConstructor() == second->GetConstructor() &&
12589  first->prototype() == second->prototype() &&
12590  first->instance_type() == second->instance_type() &&
12591  first->bit_field() == second->bit_field() &&
12592  first->is_extensible() == second->is_extensible() &&
12593  first->new_target_is_base() == second->new_target_is_base() &&
12594  first->has_hidden_prototype() == second->has_hidden_prototype();
12595 }
12596 
12597 } // namespace
12598 
12599 bool Map::EquivalentToForTransition(const Map other) const {
12600  if (!CheckEquivalent(*this, other)) return false;
12601  if (instance_type() == JS_FUNCTION_TYPE) {
12602  // JSFunctions require more checks to ensure that sloppy function is
12603  // not equivalent to strict function.
12604  int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
12605  return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
12606  nof);
12607  }
12608  return true;
12609 }
12610 
12611 bool Map::EquivalentToForElementsKindTransition(const Map other) const {
12612  if (!EquivalentToForTransition(other)) return false;
12613 #ifdef DEBUG
12614  // Ensure that we don't try to generate elements kind transitions from maps
12615  // with fields that may be generalized in-place. This must already be handled
12616  // during addition of a new field.
12617  DescriptorArray* descriptors = instance_descriptors();
12618  int nof = NumberOfOwnDescriptors();
12619  for (int i = 0; i < nof; i++) {
12620  PropertyDetails details = descriptors->GetDetails(i);
12621  if (details.location() == kField) {
12622  DCHECK(!IsInplaceGeneralizableField(details.constness(),
12623  details.representation(),
12624  descriptors->GetFieldType(i)));
12625  }
12626  }
12627 #endif
12628  return true;
12629 }
12630 
12631 bool Map::EquivalentToForNormalization(const Map other,
12632  PropertyNormalizationMode mode) const {
12633  int properties =
12634  mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
12635  return CheckEquivalent(*this, other) && bit_field2() == other->bit_field2() &&
12636  GetInObjectProperties() == properties &&
12637  JSObject::GetEmbedderFieldCount(*this) ==
12638  JSObject::GetEmbedderFieldCount(other);
12639 }
12640 
12641 
12642 void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
12643  Isolate* isolate = GetIsolate();
12644  if (!isolate->concurrent_recompilation_enabled() ||
12645  isolate->bootstrapper()->IsActive()) {
12646  mode = ConcurrencyMode::kNotConcurrent;
12647  }
12648 
12649  DCHECK(!is_compiled() || IsInterpreted());
12650  DCHECK(shared()->IsInterpreted());
12651  DCHECK(!IsOptimized());
12652  DCHECK(!HasOptimizedCode());
12653  DCHECK(shared()->allows_lazy_compilation() ||
12654  !shared()->optimization_disabled());
12655 
12656  if (mode == ConcurrencyMode::kConcurrent) {
12657  if (IsInOptimizationQueue()) {
12658  if (FLAG_trace_concurrent_recompilation) {
12659  PrintF(" ** Not marking ");
12660  ShortPrint();
12661  PrintF(" -- already in optimization queue.\n");
12662  }
12663  return;
12664  }
12665  if (FLAG_trace_concurrent_recompilation) {
12666  PrintF(" ** Marking ");
12667  ShortPrint();
12668  PrintF(" for concurrent recompilation.\n");
12669  }
12670  }
12671 
12672  SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
12673  ? OptimizationMarker::kCompileOptimizedConcurrent
12674  : OptimizationMarker::kCompileOptimized);
12675 }
12676 
12677 // static
12678 void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) {
12679  Isolate* const isolate = function->GetIsolate();
12680  if (function->feedback_cell()->value()->IsUndefined(isolate)) {
12681  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
12682  if (!shared->HasAsmWasmData()) {
12683  Handle<FeedbackVector> feedback_vector =
12684  FeedbackVector::New(isolate, shared);
12685  if (function->feedback_cell() == isolate->heap()->many_closures_cell()) {
12686  Handle<FeedbackCell> feedback_cell =
12687  isolate->factory()->NewOneClosureCell(feedback_vector);
12688  function->set_feedback_cell(*feedback_cell);
12689  } else {
12690  function->feedback_cell()->set_value(*feedback_vector);
12691  }
12692  }
12693  }
12694 }
12695 
12696 static void GetMinInobjectSlack(Map map, void* data) {
12697  int slack = map->UnusedPropertyFields();
12698  if (*reinterpret_cast<int*>(data) > slack) {
12699  *reinterpret_cast<int*>(data) = slack;
12700  }
12701 }
12702 
12703 int Map::InstanceSizeFromSlack(int slack) const {
12704  return instance_size() - slack * kPointerSize;
12705 }
12706 
12707 static void ShrinkInstanceSize(Map map, void* data) {
12708  int slack = *reinterpret_cast<int*>(data);
12709  DCHECK_GE(slack, 0);
12710 #ifdef DEBUG
12711  int old_visitor_id = Map::GetVisitorId(map);
12712  int new_unused = map->UnusedPropertyFields() - slack;
12713 #endif
12714  map->set_instance_size(map->InstanceSizeFromSlack(slack));
12715  map->set_construction_counter(Map::kNoSlackTracking);
12716  DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
12717  DCHECK_EQ(new_unused, map->UnusedPropertyFields());
12718 }
12719 
12720 static void StopSlackTracking(Map map, void* data) {
12721  map->set_construction_counter(Map::kNoSlackTracking);
12722 }
12723 
12724 int Map::ComputeMinObjectSlack(Isolate* isolate) {
12725  DisallowHeapAllocation no_gc;
12726  // Has to be an initial map.
12727  DCHECK(GetBackPointer()->IsUndefined(isolate));
12728 
12729  int slack = UnusedPropertyFields();
12730  TransitionsAccessor transitions(isolate, *this, &no_gc);
12731  transitions.TraverseTransitionTree(&GetMinInobjectSlack, &slack);
12732  return slack;
12733 }
12734 
12735 void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
12736  DisallowHeapAllocation no_gc;
12737  // Has to be an initial map.
12738  DCHECK(GetBackPointer()->IsUndefined(isolate));
12739 
12740  int slack = ComputeMinObjectSlack(isolate);
12741  TransitionsAccessor transitions(isolate, *this, &no_gc);
12742  if (slack != 0) {
12743  // Resize the initial map and all maps in its transition tree.
12744  transitions.TraverseTransitionTree(&ShrinkInstanceSize, &slack);
12745  } else {
12746  transitions.TraverseTransitionTree(&StopSlackTracking, nullptr);
12747  }
12748 }
12749 
12750 
12751 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
12752  DisallowHeapAllocation no_gc;
12753  if (!object->HasFastProperties()) return false;
12754  if (object->IsJSGlobalProxy()) return false;
12755  if (object->GetIsolate()->bootstrapper()->IsActive()) return false;
12756  return !object->map()->is_prototype_map() ||
12757  !object->map()->should_be_fast_prototype_map();
12758 }
12759 
12760 // static
12761 void JSObject::MakePrototypesFast(Handle<Object> receiver,
12762  WhereToStart where_to_start,
12763  Isolate* isolate) {
12764  if (!receiver->IsJSReceiver()) return;
12765  for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
12766  where_to_start);
12767  !iter.IsAtEnd(); iter.Advance()) {
12768  Handle<Object> current = PrototypeIterator::GetCurrent(iter);
12769  if (!current->IsJSObject()) return;
12770  Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
12771  Map current_map = current_obj->map();
12772  if (current_map->is_prototype_map()) {
12773  // If the map is already marked as should be fast, we're done. Its
12774  // prototypes will have been marked already as well.
12775  if (current_map->should_be_fast_prototype_map()) return;
12776  Handle<Map> map(current_map, isolate);
12777  Map::SetShouldBeFastPrototypeMap(map, true, isolate);
12778  JSObject::OptimizeAsPrototype(current_obj);
12779  }
12780  }
12781 }
12782 
12783 // static
12784 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
12785  bool enable_setup_mode) {
12786  if (object->IsJSGlobalObject()) return;
12787  if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) {
12788  // First normalize to ensure all JSFunctions are DATA_CONSTANT.
12789  JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
12790  "NormalizeAsPrototype");
12791  }
12792  if (object->map()->is_prototype_map()) {
12793  if (object->map()->should_be_fast_prototype_map() &&
12794  !object->HasFastProperties()) {
12795  JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
12796  }
12797  } else {
12798  Handle<Map> new_map = Map::Copy(object->GetIsolate(),
12799  handle(object->map(), object->GetIsolate()),
12800  "CopyAsPrototype");
12801  JSObject::MigrateToMap(object, new_map);
12802  object->map()->set_is_prototype_map(true);
12803 
12804  // Replace the pointer to the exact constructor with the Object function
12805  // from the same context if undetectable from JS. This is to avoid keeping
12806  // memory alive unnecessarily.
12807  Object* maybe_constructor = object->map()->GetConstructor();
12808  if (maybe_constructor->IsJSFunction()) {
12809  JSFunction* constructor = JSFunction::cast(maybe_constructor);
12810  if (!constructor->shared()->IsApiFunction()) {
12811  Context context = constructor->context()->native_context();
12812  JSFunction* object_function = context->object_function();
12813  object->map()->SetConstructor(object_function);
12814  }
12815  }
12816  }
12817 }
12818 
12819 
12820 // static
12821 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
12822  if (!object->map()->is_prototype_map()) return;
12823  if (!object->map()->should_be_fast_prototype_map()) return;
12824  OptimizeAsPrototype(object);
12825 }
12826 
12827 
12828 // static
12829 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12830  // Contract: In line with InvalidatePrototypeChains()'s requirements,
12831  // leaf maps don't need to register as users, only prototypes do.
12832  DCHECK(user->is_prototype_map());
12833 
12834  Handle<Map> current_user = user;
12835  Handle<PrototypeInfo> current_user_info =
12836  Map::GetOrCreatePrototypeInfo(user, isolate);
12837  for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) {
12838  // Walk up the prototype chain as far as links haven't been registered yet.
12839  if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
12840  break;
12841  }
12842  Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
12843  // Proxies on the prototype chain are not supported. They make it
12844  // impossible to make any assumptions about the prototype chain anyway.
12845  if (maybe_proto->IsJSProxy()) return;
12846  Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
12847  Handle<PrototypeInfo> proto_info =
12848  Map::GetOrCreatePrototypeInfo(proto, isolate);
12849  Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
12850  Handle<WeakArrayList> registry =
12851  maybe_registry->IsSmi()
12852  ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
12853  isolate)
12854  : Handle<WeakArrayList>::cast(maybe_registry);
12855  int slot = 0;
12856  Handle<WeakArrayList> new_array =
12857  PrototypeUsers::Add(isolate, registry, current_user, &slot);
12858  current_user_info->set_registry_slot(slot);
12859  if (!maybe_registry.is_identical_to(new_array)) {
12860  proto_info->set_prototype_users(*new_array);
12861  }
12862  if (FLAG_trace_prototype_users) {
12863  PrintF("Registering %p as a user of prototype %p (map=%p).\n",
12864  reinterpret_cast<void*>(current_user->ptr()),
12865  reinterpret_cast<void*>(*proto),
12866  reinterpret_cast<void*>(proto->map()->ptr()));
12867  }
12868 
12869  current_user = handle(proto->map(), isolate);
12870  current_user_info = proto_info;
12871  }
12872 }
12873 
12874 
12875 // Can be called regardless of whether |user| was actually registered with
12876 // |prototype|. Returns true when there was a registration.
12877 // static
12878 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12879  DCHECK(user->is_prototype_map());
12880  // If it doesn't have a PrototypeInfo, it was never registered.
12881  if (!user->prototype_info()->IsPrototypeInfo()) return false;
12882  // If it had no prototype before, see if it had users that might expect
12883  // registration.
12884  if (!user->prototype()->IsJSObject()) {
12885  Object* users =
12886  PrototypeInfo::cast(user->prototype_info())->prototype_users();
12887  return users->IsWeakArrayList();
12888  }
12889  Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
12890  Handle<PrototypeInfo> user_info =
12891  Map::GetOrCreatePrototypeInfo(user, isolate);
12892  int slot = user_info->registry_slot();
12893  if (slot == PrototypeInfo::UNREGISTERED) return false;
12894  DCHECK(prototype->map()->is_prototype_map());
12895  Object* maybe_proto_info = prototype->map()->prototype_info();
12896  // User knows its registry slot, prototype info and user registry must exist.
12897  DCHECK(maybe_proto_info->IsPrototypeInfo());
12898  Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
12899  isolate);
12900  Handle<WeakArrayList> prototype_users(
12901  WeakArrayList::cast(proto_info->prototype_users()), isolate);
12902  DCHECK_EQ(prototype_users->Get(slot), HeapObjectReference::Weak(*user));
12903  PrototypeUsers::MarkSlotEmpty(*prototype_users, slot);
12904  if (FLAG_trace_prototype_users) {
12905  PrintF("Unregistering %p as a user of prototype %p.\n",
12906  reinterpret_cast<void*>(user->ptr()),
12907  reinterpret_cast<void*>(*prototype));
12908  }
12909  return true;
12910 }
12911 
12912 namespace {
12913 
12914 // This function must be kept in sync with
12915 // AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks
12916 // before jumping here.
12917 void InvalidateOnePrototypeValidityCellInternal(Map map) {
12918  DCHECK(map->is_prototype_map());
12919  if (FLAG_trace_prototype_users) {
12920  PrintF("Invalidating prototype map %p 's cell\n",
12921  reinterpret_cast<void*>(map.ptr()));
12922  }
12923  Object* maybe_cell = map->prototype_validity_cell();
12924  if (maybe_cell->IsCell()) {
12925  // Just set the value; the cell will be replaced lazily.
12926  Cell* cell = Cell::cast(maybe_cell);
12927  cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
12928  }
12929 }
12930 
12931 void InvalidatePrototypeChainsInternal(Map map) {
12932  InvalidateOnePrototypeValidityCellInternal(map);
12933 
12934  Object* maybe_proto_info = map->prototype_info();
12935  if (!maybe_proto_info->IsPrototypeInfo()) return;
12936  PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
12937  if (!proto_info->prototype_users()->IsWeakArrayList()) {
12938  return;
12939  }
12940  WeakArrayList* prototype_users =
12941  WeakArrayList::cast(proto_info->prototype_users());
12942  // For now, only maps register themselves as users.
12943  for (int i = PrototypeUsers::kFirstIndex; i < prototype_users->length();
12944  ++i) {
12945  HeapObject* heap_object;
12946  if (prototype_users->Get(i)->GetHeapObjectIfWeak(&heap_object) &&
12947  heap_object->IsMap()) {
12948  // Walk the prototype chain (backwards, towards leaf objects) if
12949  // necessary.
12950  InvalidatePrototypeChainsInternal(Map::cast(heap_object));
12951  }
12952  }
12953 }
12954 
12955 } // namespace
12956 
12957 // static
12958 Map JSObject::InvalidatePrototypeChains(Map map) {
12959  DisallowHeapAllocation no_gc;
12960  InvalidatePrototypeChainsInternal(map);
12961  return map;
12962 }
12963 
12964 // We also invalidate global objects validity cell when a new lexical
12965 // environment variable is added. This is necessary to ensure that
12966 // Load/StoreGlobalIC handlers that load/store from global object's prototype
12967 // get properly invalidated.
12968 // Note, that the normal Load/StoreICs that load/store through the global object
12969 // in the prototype chain are not affected by appearance of a new lexical
12970 // variable and therefore we don't propagate invalidation down.
12971 // static
12972 void JSObject::InvalidatePrototypeValidityCell(JSGlobalObject* global) {
12973  DisallowHeapAllocation no_gc;
12974  InvalidateOnePrototypeValidityCellInternal(global->map());
12975 }
12976 
12977 // static
12978 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
12979  Isolate* isolate) {
12980  Object* maybe_proto_info = prototype->map()->prototype_info();
12981  if (maybe_proto_info->IsPrototypeInfo()) {
12982  return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12983  }
12984  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12985  prototype->map()->set_prototype_info(*proto_info);
12986  return proto_info;
12987 }
12988 
12989 
12990 // static
12991 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
12992  Isolate* isolate) {
12993  Object* maybe_proto_info = prototype_map->prototype_info();
12994  if (maybe_proto_info->IsPrototypeInfo()) {
12995  return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12996  }
12997  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12998  prototype_map->set_prototype_info(*proto_info);
12999  return proto_info;
13000 }
13001 
13002 // static
13003 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
13004  Isolate* isolate) {
13005  if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
13006  // "False" is the implicit default value, so there's nothing to do.
13007  return;
13008  }
13009  GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
13010 }
13011 
13012 // static
13013 Handle<Object> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
13014  Isolate* isolate) {
13015  Handle<Object> maybe_prototype;
13016  if (map->IsJSGlobalObjectMap()) {
13017  DCHECK(map->is_prototype_map());
13018  // Global object is prototype of a global proxy and therefore we can
13019  // use its validity cell for guarding global object's prototype change.
13020  maybe_prototype = isolate->global_object();
13021  } else {
13022  maybe_prototype =
13023  handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
13024  }
13025  if (!maybe_prototype->IsJSObject()) {
13026  return handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
13027  }
13028  Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
13029  // Ensure the prototype is registered with its own prototypes so its cell
13030  // will be invalidated when necessary.
13031  JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
13032  isolate);
13033 
13034  Object* maybe_cell = prototype->map()->prototype_validity_cell();
13035  // Return existing cell if it's still valid.
13036  if (maybe_cell->IsCell()) {
13037  Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
13038  if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
13039  return cell;
13040  }
13041  }
13042  // Otherwise create a new cell.
13043  Handle<Cell> cell = isolate->factory()->NewCell(
13044  handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
13045  prototype->map()->set_prototype_validity_cell(*cell);
13046  return cell;
13047 }
13048 
13049 // static
13050 bool Map::IsPrototypeChainInvalidated(Map map) {
13051  DCHECK(map->is_prototype_map());
13052  Object* maybe_cell = map->prototype_validity_cell();
13053  if (maybe_cell->IsCell()) {
13054  Cell* cell = Cell::cast(maybe_cell);
13055  return cell->value() != Smi::FromInt(Map::kPrototypeChainValid);
13056  }
13057  return true;
13058 }
13059 
13060 // static
13061 void Map::SetPrototype(Isolate* isolate, Handle<Map> map,
13062  Handle<Object> prototype,
13063  bool enable_prototype_setup_mode) {
13064  RuntimeCallTimerScope stats_scope(isolate, *map,
13065  RuntimeCallCounterId::kMap_SetPrototype);
13066 
13067  bool is_hidden = false;
13068  if (prototype->IsJSObject()) {
13069  Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
13070  JSObject::OptimizeAsPrototype(prototype_jsobj, enable_prototype_setup_mode);
13071 
13072  Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
13073  if (maybe_constructor->IsJSFunction()) {
13074  JSFunction* constructor = JSFunction::cast(maybe_constructor);
13075  Object* data = constructor->shared()->function_data();
13076  is_hidden = (data->IsFunctionTemplateInfo() &&
13077  FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
13078  prototype->IsJSGlobalObject();
13079  } else if (maybe_constructor->IsFunctionTemplateInfo()) {
13080  is_hidden =
13081  FunctionTemplateInfo::cast(maybe_constructor)->hidden_prototype() ||
13082  prototype->IsJSGlobalObject();
13083  }
13084  }
13085  map->set_has_hidden_prototype(is_hidden);
13086 
13087  WriteBarrierMode wb_mode =
13088  prototype->IsNull(isolate) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
13089  map->set_prototype(*prototype, wb_mode);
13090 }
13091 
13092 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
13093  Handle<Map> initial_map) {
13094  // Replace all of the cached initial array maps in the native context with
13095  // the appropriate transitioned elements kind maps.
13096  Handle<Map> current_map = initial_map;
13097  ElementsKind kind = current_map->elements_kind();
13098  DCHECK_EQ(GetInitialFastElementsKind(), kind);
13099  native_context->set(Context::ArrayMapIndex(kind), *current_map);
13100  for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
13101  i < kFastElementsKindCount; ++i) {
13102  Handle<Map> new_map;
13103  ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
13104  Map maybe_elements_transition = current_map->ElementsTransitionMap();
13105  if (!maybe_elements_transition.is_null()) {
13106  new_map = handle(maybe_elements_transition, native_context->GetIsolate());
13107  } else {
13108  new_map =
13109  Map::CopyAsElementsKind(native_context->GetIsolate(), current_map,
13110  next_kind, INSERT_TRANSITION);
13111  }
13112  DCHECK_EQ(next_kind, new_map->elements_kind());
13113  native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
13114  current_map = new_map;
13115  }
13116  return initial_map;
13117 }
13118 
13119 namespace {
13120 
13121 void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
13122  Handle<JSReceiver> value) {
13123  // Now some logic for the maps of the objects that are created by using this
13124  // function as a constructor.
13125  if (function->has_initial_map()) {
13126  // If the function has allocated the initial map replace it with a
13127  // copy containing the new prototype. Also complete any in-object
13128  // slack tracking that is in progress at this point because it is
13129  // still tracking the old copy.
13130  function->CompleteInobjectSlackTrackingIfActive();
13131 
13132  Handle<Map> initial_map(function->initial_map(), isolate);
13133 
13134  if (!isolate->bootstrapper()->IsActive() &&
13135  initial_map->instance_type() == JS_OBJECT_TYPE) {
13136  // Put the value in the initial map field until an initial map is needed.
13137  // At that point, a new initial map is created and the prototype is put
13138  // into the initial map where it belongs.
13139  function->set_prototype_or_initial_map(*value);
13140  } else {
13141  Handle<Map> new_map =
13142  Map::Copy(isolate, initial_map, "SetInstancePrototype");
13143  JSFunction::SetInitialMap(function, new_map, value);
13144 
13145  // If the function is used as the global Array function, cache the
13146  // updated initial maps (and transitioned versions) in the native context.
13147  Handle<Context> native_context(function->context()->native_context(),
13148  isolate);
13149  Handle<Object> array_function(
13150  native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
13151  if (array_function->IsJSFunction() &&
13152  *function == JSFunction::cast(*array_function)) {
13153  CacheInitialJSArrayMaps(native_context, new_map);
13154  }
13155  }
13156 
13157  // Deoptimize all code that embeds the previous initial map.
13158  initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
13159  isolate, DependentCode::kInitialMapChangedGroup);
13160  } else {
13161  // Put the value in the initial map field until an initial map is
13162  // needed. At that point, a new initial map is created and the
13163  // prototype is put into the initial map where it belongs.
13164  function->set_prototype_or_initial_map(*value);
13165  if (value->IsJSObject()) {
13166  // Optimize as prototype to detach it from its transition tree.
13167  JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
13168  }
13169  }
13170 }
13171 
13172 } // anonymous namespace
13173 
13174 void JSFunction::SetPrototype(Handle<JSFunction> function,
13175  Handle<Object> value) {
13176  DCHECK(function->IsConstructor() ||
13177  IsGeneratorFunction(function->shared()->kind()));
13178  Isolate* isolate = function->GetIsolate();
13179  Handle<JSReceiver> construct_prototype;
13180 
13181  // If the value is not a JSReceiver, store the value in the map's
13182  // constructor field so it can be accessed. Also, set the prototype
13183  // used for constructing objects to the original object prototype.
13184  // See ECMA-262 13.2.2.
13185  if (!value->IsJSReceiver()) {
13186  // Copy the map so this does not affect unrelated functions.
13187  // Remove map transitions because they point to maps with a
13188  // different prototype.
13189  Handle<Map> new_map =
13190  Map::Copy(isolate, handle(function->map(), isolate), "SetPrototype");
13191 
13192  JSObject::MigrateToMap(function, new_map);
13193  new_map->SetConstructor(*value);
13194  new_map->set_has_non_instance_prototype(true);
13195 
13196  FunctionKind kind = function->shared()->kind();
13197  Handle<Context> native_context(function->context()->native_context(),
13198  isolate);
13199 
13200  construct_prototype = Handle<JSReceiver>(
13201  IsGeneratorFunction(kind)
13202  ? IsAsyncFunction(kind)
13203  ? native_context->initial_async_generator_prototype()
13204  : native_context->initial_generator_prototype()
13205  : native_context->initial_object_prototype(),
13206  isolate);
13207  } else {
13208  construct_prototype = Handle<JSReceiver>::cast(value);
13209  function->map()->set_has_non_instance_prototype(false);
13210  }
13211 
13212  SetInstancePrototype(isolate, function, construct_prototype);
13213 }
13214 
13215 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
13216  Handle<Object> prototype) {
13217  if (map->prototype() != *prototype)
13218  Map::SetPrototype(function->GetIsolate(), map, prototype);
13219  function->set_prototype_or_initial_map(*map);
13220  map->SetConstructor(*function);
13221  if (FLAG_trace_maps) {
13222  LOG(function->GetIsolate(), MapEvent("InitialMap", Map(), *map, "",
13223  function->shared()->DebugName()));
13224  }
13225 }
13226 
13227 
13228 #ifdef DEBUG
13229 namespace {
13230 
13231 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
13232  switch (instance_type) {
13233  case JS_API_OBJECT_TYPE:
13234  case JS_ARRAY_BUFFER_TYPE:
13235  case JS_ARRAY_TYPE:
13236  case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
13237  case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
13238  case JS_DATA_VIEW_TYPE:
13239  case JS_DATE_TYPE:
13240  case JS_FUNCTION_TYPE:
13241  case JS_GENERATOR_OBJECT_TYPE:
13242 #ifdef V8_INTL_SUPPORT
13243  case JS_INTL_COLLATOR_TYPE:
13244  case JS_INTL_DATE_TIME_FORMAT_TYPE:
13245  case JS_INTL_LIST_FORMAT_TYPE:
13246  case JS_INTL_LOCALE_TYPE:
13247  case JS_INTL_NUMBER_FORMAT_TYPE:
13248  case JS_INTL_PLURAL_RULES_TYPE:
13249  case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
13250  case JS_INTL_SEGMENT_ITERATOR_TYPE:
13251  case JS_INTL_SEGMENTER_TYPE:
13252  case JS_INTL_V8_BREAK_ITERATOR_TYPE:
13253 #endif
13254  case JS_ASYNC_FUNCTION_OBJECT_TYPE:
13255  case JS_ASYNC_GENERATOR_OBJECT_TYPE:
13256  case JS_MAP_TYPE:
13257  case JS_MESSAGE_OBJECT_TYPE:
13258  case JS_OBJECT_TYPE:
13259  case JS_ERROR_TYPE:
13260  case JS_ARGUMENTS_TYPE:
13261  case JS_PROMISE_TYPE:
13262  case JS_REGEXP_TYPE:
13263  case JS_SET_TYPE:
13264  case JS_SPECIAL_API_OBJECT_TYPE:
13265  case JS_TYPED_ARRAY_TYPE:
13266  case JS_VALUE_TYPE:
13267  case JS_WEAK_MAP_TYPE:
13268  case JS_WEAK_SET_TYPE:
13269  case WASM_GLOBAL_TYPE:
13270  case WASM_INSTANCE_TYPE:
13271  case WASM_MEMORY_TYPE:
13272  case WASM_MODULE_TYPE:
13273  case WASM_TABLE_TYPE:
13274  return true;
13275 
13276  case BIGINT_TYPE:
13277  case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
13278  case BYTECODE_ARRAY_TYPE:
13279  case BYTE_ARRAY_TYPE:
13280  case CELL_TYPE:
13281  case CODE_TYPE:
13282  case FILLER_TYPE:
13283  case FIXED_ARRAY_TYPE:
13284  case SCRIPT_CONTEXT_TABLE_TYPE:
13285  case FIXED_DOUBLE_ARRAY_TYPE:
13286  case FEEDBACK_METADATA_TYPE:
13287  case FOREIGN_TYPE:
13288  case FREE_SPACE_TYPE:
13289  case HASH_TABLE_TYPE:
13290  case ORDERED_HASH_MAP_TYPE:
13291  case ORDERED_HASH_SET_TYPE:
13292  case ORDERED_NAME_DICTIONARY_TYPE:
13293  case NAME_DICTIONARY_TYPE:
13294  case GLOBAL_DICTIONARY_TYPE:
13295  case NUMBER_DICTIONARY_TYPE:
13296  case SIMPLE_NUMBER_DICTIONARY_TYPE:
13297  case STRING_TABLE_TYPE:
13298  case HEAP_NUMBER_TYPE:
13299  case JS_BOUND_FUNCTION_TYPE:
13300  case JS_GLOBAL_OBJECT_TYPE:
13301  case JS_GLOBAL_PROXY_TYPE:
13302  case JS_PROXY_TYPE:
13303  case MAP_TYPE:
13304  case MUTABLE_HEAP_NUMBER_TYPE:
13305  case ODDBALL_TYPE:
13306  case PROPERTY_CELL_TYPE:
13307  case SHARED_FUNCTION_INFO_TYPE:
13308  case SYMBOL_TYPE:
13309  case ALLOCATION_SITE_TYPE:
13310 
13311 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
13312  case FIXED_##TYPE##_ARRAY_TYPE:
13313 #undef TYPED_ARRAY_CASE
13314 
13315 #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
13316  STRUCT_LIST(MAKE_STRUCT_CASE)
13317 #undef MAKE_STRUCT_CASE
13318  // We must not end up here for these instance types at all.
13319  UNREACHABLE();
13320  // Fall through.
13321  default:
13322  return false;
13323  }
13324 }
13325 
13326 } // namespace
13327 #endif
13328 
13329 
13330 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
13331  DCHECK(function->has_prototype_slot());
13332  DCHECK(function->IsConstructor() ||
13333  IsResumableFunction(function->shared()->kind()));
13334  if (function->has_initial_map()) return;
13335  Isolate* isolate = function->GetIsolate();
13336 
13337  // First create a new map with the size and number of in-object properties
13338  // suggested by the function.
13339  InstanceType instance_type;
13340  if (IsResumableFunction(function->shared()->kind())) {
13341  instance_type = IsAsyncGeneratorFunction(function->shared()->kind())
13342  ? JS_ASYNC_GENERATOR_OBJECT_TYPE
13343  : JS_GENERATOR_OBJECT_TYPE;
13344  } else {
13345  instance_type = JS_OBJECT_TYPE;
13346  }
13347 
13348  // The constructor should be compiled for the optimization hints to be
13349  // available.
13350  int expected_nof_properties = 0;
13351  if (function->shared()->is_compiled() ||
13352  Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
13353  DCHECK(function->shared()->is_compiled());
13354  expected_nof_properties = function->shared()->expected_nof_properties();
13355  }
13356 
13357  int instance_size;
13358  int inobject_properties;
13359  CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties,
13360  &instance_size, &inobject_properties);
13361 
13362  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size,
13363  TERMINAL_FAST_ELEMENTS_KIND,
13364  inobject_properties);
13365 
13366  // Fetch or allocate prototype.
13367  Handle<Object> prototype;
13368  if (function->has_instance_prototype()) {
13369  prototype = handle(function->instance_prototype(), isolate);
13370  } else {
13371  prototype = isolate->factory()->NewFunctionPrototype(function);
13372  }
13373  DCHECK(map->has_fast_object_elements());
13374 
13375  // Finally link initial map and constructor function.
13376  DCHECK(prototype->IsJSReceiver());
13377  JSFunction::SetInitialMap(function, map, prototype);
13378  map->StartInobjectSlackTracking();
13379 }
13380 
13381 namespace {
13382 bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
13383  Handle<JSFunction> constructor,
13384  Handle<Map> constructor_initial_map) {
13385  // Use the default intrinsic prototype instead.
13386  if (!new_target->has_prototype_slot()) return false;
13387  // Check that |function|'s initial map still in sync with the |constructor|,
13388  // otherwise we must create a new initial map for |function|.
13389  if (new_target->has_initial_map() &&
13390  new_target->initial_map()->GetConstructor() == *constructor) {
13391  DCHECK(new_target->instance_prototype()->IsJSReceiver());
13392  return true;
13393  }
13394  InstanceType instance_type = constructor_initial_map->instance_type();
13395  DCHECK(CanSubclassHaveInobjectProperties(instance_type));
13396  // Create a new map with the size and number of in-object properties
13397  // suggested by |function|.
13398 
13399  // Link initial map and constructor function if the new.target is actually a
13400  // subclass constructor.
13401  if (!IsDerivedConstructor(new_target->shared()->kind())) return false;
13402 
13403  int instance_size;
13404  int in_object_properties;
13405  int embedder_fields =
13406  JSObject::GetEmbedderFieldCount(*constructor_initial_map);
13407  bool success = JSFunction::CalculateInstanceSizeForDerivedClass(
13408  new_target, instance_type, embedder_fields, &instance_size,
13409  &in_object_properties);
13410 
13411  Handle<Map> map;
13412  if (success) {
13413  int pre_allocated = constructor_initial_map->GetInObjectProperties() -
13414  constructor_initial_map->UnusedPropertyFields();
13415  CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size);
13416  int unused_property_fields = in_object_properties - pre_allocated;
13417  map = Map::CopyInitialMap(isolate, constructor_initial_map, instance_size,
13418  in_object_properties, unused_property_fields);
13419  } else {
13420  map = Map::CopyInitialMap(isolate, constructor_initial_map);
13421  }
13422  map->set_new_target_is_base(false);
13423  Handle<Object> prototype(new_target->instance_prototype(), isolate);
13424  JSFunction::SetInitialMap(new_target, map, prototype);
13425  DCHECK(new_target->instance_prototype()->IsJSReceiver());
13426  map->SetConstructor(*constructor);
13427  map->set_construction_counter(Map::kNoSlackTracking);
13428  map->StartInobjectSlackTracking();
13429  return true;
13430 }
13431 
13432 } // namespace
13433 
13434 // static
13435 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
13436  Handle<JSFunction> constructor,
13437  Handle<JSReceiver> new_target) {
13438  EnsureHasInitialMap(constructor);
13439 
13440  Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
13441  if (*new_target == *constructor) return constructor_initial_map;
13442 
13443  Handle<Map> result_map;
13444  // Fast case, new.target is a subclass of constructor. The map is cacheable
13445  // (and may already have been cached). new.target.prototype is guaranteed to
13446  // be a JSReceiver.
13447  if (new_target->IsJSFunction()) {
13448  Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
13449  if (FastInitializeDerivedMap(isolate, function, constructor,
13450  constructor_initial_map)) {
13451  return handle(function->initial_map(), isolate);
13452  }
13453  }
13454 
13455  // Slow path, new.target is either a proxy or can't cache the map.
13456  // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
13457  // fall back to the intrinsicDefaultProto.
13458  Handle<Object> prototype;
13459  if (new_target->IsJSFunction()) {
13460  Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
13461  if (function->has_prototype_slot()) {
13462  // Make sure the new.target.prototype is cached.
13463  EnsureHasInitialMap(function);
13464  prototype = handle(function->prototype(), isolate);
13465  } else {
13466  // No prototype property, use the intrinsict default proto further down.
13467  prototype = isolate->factory()->undefined_value();
13468  }
13469  } else {
13470  Handle<String> prototype_string = isolate->factory()->prototype_string();
13471  ASSIGN_RETURN_ON_EXCEPTION(
13472  isolate, prototype,
13473  JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);
13474  // The above prototype lookup might change the constructor and its
13475  // prototype, hence we have to reload the initial map.
13476  EnsureHasInitialMap(constructor);
13477  constructor_initial_map = handle(constructor->initial_map(), isolate);
13478  }
13479 
13480  // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
13481  // correct realm. Rather than directly fetching the .prototype, we fetch the
13482  // constructor that points to the .prototype. This relies on
13483  // constructor.prototype being FROZEN for those constructors.
13484  if (!prototype->IsJSReceiver()) {
13485  Handle<Context> context;
13486  ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
13487  JSReceiver::GetFunctionRealm(new_target), Map);
13488  DCHECK(context->IsNativeContext());
13489  Handle<Object> maybe_index = JSReceiver::GetDataProperty(
13490  constructor, isolate->factory()->native_context_index_symbol());
13491  int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index)
13492  : Context::OBJECT_FUNCTION_INDEX;
13493  Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)),
13494  isolate);
13495  prototype = handle(realm_constructor->prototype(), isolate);
13496  }
13497 
13498  Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map);
13499  map->set_new_target_is_base(false);
13500  CHECK(prototype->IsJSReceiver());
13501  if (map->prototype() != *prototype)
13502  Map::SetPrototype(isolate, map, prototype);
13503  map->SetConstructor(*constructor);
13504  return map;
13505 }
13506 
13507 int JSFunction::ComputeInstanceSizeWithMinSlack(Isolate* isolate) {
13508  CHECK(has_initial_map());
13509  if (initial_map()->IsInobjectSlackTrackingInProgress()) {
13510  int slack = initial_map()->ComputeMinObjectSlack(isolate);
13511  return initial_map()->InstanceSizeFromSlack(slack);
13512  }
13513  return initial_map()->instance_size();
13514 }
13515 
13516 void JSFunction::PrintName(FILE* out) {
13517  std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
13518  PrintF(out, "%s", name.get());
13519 }
13520 
13521 
13522 Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
13523  Isolate* isolate = function->GetIsolate();
13524  Handle<Object> name =
13525  JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
13526  if (name->IsString()) return Handle<String>::cast(name);
13527  return handle(function->shared()->DebugName(), isolate);
13528 }
13529 
13530 
13531 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
13532  Isolate* isolate = function->GetIsolate();
13533  Handle<Object> name = JSReceiver::GetDataProperty(
13534  function, isolate->factory()->display_name_string());
13535  if (name->IsString()) return Handle<String>::cast(name);
13536  return JSFunction::GetName(function);
13537 }
13538 
13539 bool JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
13540  Handle<String> prefix) {
13541  Isolate* isolate = function->GetIsolate();
13542  Handle<String> function_name;
13543  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name,
13544  Name::ToFunctionName(isolate, name), false);
13545  if (prefix->length() > 0) {
13546  IncrementalStringBuilder builder(isolate);
13547  builder.AppendString(prefix);
13548  builder.AppendCharacter(' ');
13549  builder.AppendString(function_name);
13550  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name, builder.Finish(),
13551  false);
13552  }
13553  RETURN_ON_EXCEPTION_VALUE(
13554  isolate,
13555  JSObject::DefinePropertyOrElementIgnoreAttributes(
13556  function, isolate->factory()->name_string(), function_name,
13557  static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY)),
13558  false);
13559  return true;
13560 }
13561 
13562 namespace {
13563 
13564 Handle<String> NativeCodeFunctionSourceString(
13565  Handle<SharedFunctionInfo> shared_info) {
13566  Isolate* const isolate = shared_info->GetIsolate();
13567  IncrementalStringBuilder builder(isolate);
13568  builder.AppendCString("function ");
13569  builder.AppendString(handle(shared_info->Name(), isolate));
13570  builder.AppendCString("() { [native code] }");
13571  return builder.Finish().ToHandleChecked();
13572 }
13573 
13574 } // namespace
13575 
13576 
13577 // static
13578 Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
13579  Isolate* const isolate = function->GetIsolate();
13580  return isolate->factory()->function_native_code_string();
13581 }
13582 
13583 
13584 // static
13585 Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
13586  Isolate* const isolate = function->GetIsolate();
13587  Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
13588 
13589  // Check if {function} should hide its source code.
13590  if (!shared_info->IsUserJavaScript()) {
13591  return NativeCodeFunctionSourceString(shared_info);
13592  }
13593 
13594  // Check if we should print {function} as a class.
13595  Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
13596  function, isolate->factory()->class_positions_symbol());
13597  if (maybe_class_positions->IsTuple2()) {
13598  Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
13599  int start_position = Smi::ToInt(class_positions->value1());
13600  int end_position = Smi::ToInt(class_positions->value2());
13601  Handle<String> script_source(
13602  String::cast(Script::cast(shared_info->script())->source()), isolate);
13603  return isolate->factory()->NewSubString(script_source, start_position,
13604  end_position);
13605  }
13606 
13607  // Check if we have source code for the {function}.
13608  if (!shared_info->HasSourceCode()) {
13609  return NativeCodeFunctionSourceString(shared_info);
13610  }
13611 
13612  if (shared_info->function_token_position() == kNoSourcePosition) {
13613  // If the function token position isn't valid, return [native code] to
13614  // ensure calling eval on the returned source code throws rather than
13615  // giving inconsistent call behaviour.
13616  isolate->CountUsage(
13617  v8::Isolate::UseCounterFeature::kFunctionTokenOffsetTooLongForToString);
13618  return NativeCodeFunctionSourceString(shared_info);
13619  }
13620  return Handle<String>::cast(
13621  SharedFunctionInfo::GetSourceCodeHarmony(shared_info));
13622 }
13623 
13624 void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
13625  const char* to_string, Handle<Object> to_number,
13626  const char* type_of, byte kind) {
13627  Handle<String> internalized_to_string =
13628  isolate->factory()->InternalizeUtf8String(to_string);
13629  Handle<String> internalized_type_of =
13630  isolate->factory()->InternalizeUtf8String(type_of);
13631  if (to_number->IsHeapNumber()) {
13632  oddball->set_to_number_raw_as_bits(
13633  Handle<HeapNumber>::cast(to_number)->value_as_bits());
13634  } else {
13635  oddball->set_to_number_raw(to_number->Number());
13636  }
13637  oddball->set_to_number(*to_number);
13638  oddball->set_to_string(*internalized_to_string);
13639  oddball->set_type_of(*internalized_type_of);
13640  oddball->set_kind(kind);
13641 }
13642 
13643 int Script::GetEvalPosition() {
13644  DisallowHeapAllocation no_gc;
13645  DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
13646  int position = eval_from_position();
13647  if (position < 0) {
13648  // Due to laziness, the position may not have been translated from code
13649  // offset yet, which would be encoded as negative integer. In that case,
13650  // translate and set the position.
13651  if (!has_eval_from_shared()) {
13652  position = 0;
13653  } else {
13654  SharedFunctionInfo* shared = eval_from_shared();
13655  position = shared->abstract_code()->SourcePosition(-position);
13656  }
13657  DCHECK_GE(position, 0);
13658  set_eval_from_position(position);
13659  }
13660  return position;
13661 }
13662 
13663 void Script::InitLineEnds(Handle<Script> script) {
13664  Isolate* isolate = script->GetIsolate();
13665  if (!script->line_ends()->IsUndefined(isolate)) return;
13666  DCHECK(script->type() != Script::TYPE_WASM ||
13667  script->source_mapping_url()->IsString());
13668 
13669  Object* src_obj = script->source();
13670  if (!src_obj->IsString()) {
13671  DCHECK(src_obj->IsUndefined(isolate));
13672  script->set_line_ends(ReadOnlyRoots(isolate).empty_fixed_array());
13673  } else {
13674  DCHECK(src_obj->IsString());
13675  Handle<String> src(String::cast(src_obj), isolate);
13676  Handle<FixedArray> array = String::CalculateLineEnds(isolate, src, true);
13677  script->set_line_ends(*array);
13678  }
13679 
13680  DCHECK(script->line_ends()->IsFixedArray());
13681 }
13682 
13683 bool Script::GetPositionInfo(Handle<Script> script, int position,
13684  PositionInfo* info, OffsetFlag offset_flag) {
13685  // For wasm, we do not create an artificial line_ends array, but do the
13686  // translation directly.
13687  if (script->type() != Script::TYPE_WASM) InitLineEnds(script);
13688  return script->GetPositionInfo(position, info, offset_flag);
13689 }
13690 
13691 bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; }
13692 
13693 bool Script::ContainsAsmModule() {
13694  DisallowHeapAllocation no_gc;
13695  SharedFunctionInfo::ScriptIterator iter(this->GetIsolate(), this);
13696  while (SharedFunctionInfo* info = iter.Next()) {
13697  if (info->HasAsmWasmData()) return true;
13698  }
13699  return false;
13700 }
13701 
13702 namespace {
13703 bool GetPositionInfoSlow(const Script* script, int position,
13704  Script::PositionInfo* info) {
13705  if (!script->source()->IsString()) return false;
13706  if (position < 0) position = 0;
13707 
13708  String source_string = String::cast(script->source());
13709  int line = 0;
13710  int line_start = 0;
13711  int len = source_string->length();
13712  for (int pos = 0; pos <= len; ++pos) {
13713  if (pos == len || source_string->Get(pos) == '\n') {
13714  if (position <= pos) {
13715  info->line = line;
13716  info->column = position - line_start;
13717  info->line_start = line_start;
13718  info->line_end = pos;
13719  return true;
13720  }
13721  line++;
13722  line_start = pos + 1;
13723  }
13724  }
13725  return false;
13726 }
13727 } // namespace
13728 
13729 #define SMI_VALUE(x) (Smi::ToInt(x))
13730 bool Script::GetPositionInfo(int position, PositionInfo* info,
13731  OffsetFlag offset_flag) const {
13732  DisallowHeapAllocation no_allocation;
13733 
13734  // For wasm, we do not rely on the line_ends array, but do the translation
13735  // directly.
13736  if (type() == Script::TYPE_WASM) {
13737  DCHECK_LE(0, position);
13738  return WasmModuleObject::cast(wasm_module_object())
13739  ->GetPositionInfo(static_cast<uint32_t>(position), info);
13740  }
13741 
13742  if (line_ends()->IsUndefined()) {
13743  // Slow mode: we do not have line_ends. We have to iterate through source.
13744  if (!GetPositionInfoSlow(this, position, info)) return false;
13745  } else {
13746  DCHECK(line_ends()->IsFixedArray());
13747  FixedArray ends = FixedArray::cast(line_ends());
13748 
13749  const int ends_len = ends->length();
13750  if (ends_len == 0) return false;
13751 
13752  // Return early on invalid positions. Negative positions behave as if 0 was
13753  // passed, and positions beyond the end of the script return as failure.
13754  if (position < 0) {
13755  position = 0;
13756  } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
13757  return false;
13758  }
13759 
13760  // Determine line number by doing a binary search on the line ends array.
13761  if (SMI_VALUE(ends->get(0)) >= position) {
13762  info->line = 0;
13763  info->line_start = 0;
13764  info->column = position;
13765  } else {
13766  int left = 0;
13767  int right = ends_len - 1;
13768 
13769  while (right > 0) {
13770  DCHECK_LE(left, right);
13771  const int mid = (left + right) / 2;
13772  if (position > SMI_VALUE(ends->get(mid))) {
13773  left = mid + 1;
13774  } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
13775  right = mid - 1;
13776  } else {
13777  info->line = mid;
13778  break;
13779  }
13780  }
13781  DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
13782  SMI_VALUE(ends->get(info->line - 1)) < position);
13783  info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
13784  info->column = position - info->line_start;
13785  }
13786 
13787  // Line end is position of the linebreak character.
13788  info->line_end = SMI_VALUE(ends->get(info->line));
13789  if (info->line_end > 0) {
13790  DCHECK(source()->IsString());
13791  String src = String::cast(source());
13792  if (src->length() >= info->line_end &&
13793  src->Get(info->line_end - 1) == '\r') {
13794  info->line_end--;
13795  }
13796  }
13797  }
13798 
13799  // Add offsets if requested.
13800  if (offset_flag == WITH_OFFSET) {
13801  if (info->line == 0) {
13802  info->column += column_offset();
13803  }
13804  info->line += line_offset();
13805  }
13806 
13807  return true;
13808 }
13809 #undef SMI_VALUE
13810 
13811 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
13812  PositionInfo info;
13813  GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
13814  return info.column;
13815 }
13816 
13817 int Script::GetColumnNumber(int code_pos) const {
13818  PositionInfo info;
13819  GetPositionInfo(code_pos, &info, WITH_OFFSET);
13820  return info.column;
13821 }
13822 
13823 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
13824  PositionInfo info;
13825  GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
13826  return info.line;
13827 }
13828 
13829 int Script::GetLineNumber(int code_pos) const {
13830  PositionInfo info;
13831  GetPositionInfo(code_pos, &info, WITH_OFFSET);
13832  return info.line;
13833 }
13834 
13835 Object* Script::GetNameOrSourceURL() {
13836  // Keep in sync with ScriptNameOrSourceURL in messages.js.
13837  if (!source_url()->IsUndefined()) return source_url();
13838  return name();
13839 }
13840 
13841 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
13842  Isolate* isolate, const FunctionLiteral* fun) {
13843  CHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
13844  // If this check fails, the problem is most probably the function id
13845  // renumbering done by AstFunctionLiteralIdReindexer; in particular, that
13846  // AstTraversalVisitor doesn't recurse properly in the construct which
13847  // triggers the mismatch.
13848  CHECK_LT(fun->function_literal_id(), shared_function_infos()->length());
13849  MaybeObject shared = shared_function_infos()->Get(fun->function_literal_id());
13850  HeapObject* heap_object;
13851  if (!shared->GetHeapObject(&heap_object) ||
13852  heap_object->IsUndefined(isolate)) {
13853  return MaybeHandle<SharedFunctionInfo>();
13854  }
13855  return handle(SharedFunctionInfo::cast(heap_object), isolate);
13856 }
13857 
13858 Script::Iterator::Iterator(Isolate* isolate)
13859  : iterator_(isolate->heap()->script_list()) {}
13860 
13861 Script* Script::Iterator::Next() {
13862  Object* o = iterator_.Next();
13863  if (o != nullptr) {
13864  return Script::cast(o);
13865  }
13866  return nullptr;
13867 }
13868 
13869 Code SharedFunctionInfo::GetCode() const {
13870  // ======
13871  // NOTE: This chain of checks MUST be kept in sync with the equivalent CSA
13872  // GetSharedFunctionInfoCode method in code-stub-assembler.cc.
13873  // ======
13874 
13875  Isolate* isolate = GetIsolate();
13876  Object* data = function_data();
13877  if (data->IsSmi()) {
13878  // Holding a Smi means we are a builtin.
13879  DCHECK(HasBuiltinId());
13880  return isolate->builtins()->builtin(builtin_id());
13881  } else if (data->IsBytecodeArray()) {
13882  // Having a bytecode array means we are a compiled, interpreted function.
13883  DCHECK(HasBytecodeArray());
13884  return isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
13885  } else if (data->IsAsmWasmData()) {
13886  // Having AsmWasmData means we are an asm.js/wasm function.
13887  DCHECK(HasAsmWasmData());
13888  return isolate->builtins()->builtin(Builtins::kInstantiateAsmJs);
13889  } else if (data->IsUncompiledData()) {
13890  // Having uncompiled data (with or without scope) means we need to compile.
13891  DCHECK(HasUncompiledData());
13892  return isolate->builtins()->builtin(Builtins::kCompileLazy);
13893  } else if (data->IsFunctionTemplateInfo()) {
13894  // Having a function template info means we are an API function.
13895  DCHECK(IsApiFunction());
13896  return isolate->builtins()->builtin(Builtins::kHandleApiCall);
13897  } else if (data->IsWasmExportedFunctionData()) {
13898  // Having a WasmExportedFunctionData means the code is in there.
13899  DCHECK(HasWasmExportedFunctionData());
13900  return wasm_exported_function_data()->wrapper_code();
13901  } else if (data->IsInterpreterData()) {
13902  Code code = InterpreterTrampoline();
13903  DCHECK(code->IsCode());
13904  DCHECK(code->is_interpreter_trampoline_builtin());
13905  return code;
13906  }
13907  UNREACHABLE();
13908 }
13909 
13910 WasmExportedFunctionData* SharedFunctionInfo::wasm_exported_function_data()
13911  const {
13912  DCHECK(HasWasmExportedFunctionData());
13913  return WasmExportedFunctionData::cast(function_data());
13914 }
13915 
13916 SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
13917  Script* script)
13918  : ScriptIterator(isolate,
13919  handle(script->shared_function_infos(), isolate)) {}
13920 
13921 SharedFunctionInfo::ScriptIterator::ScriptIterator(
13922  Isolate* isolate, Handle<WeakFixedArray> shared_function_infos)
13923  : isolate_(isolate),
13924  shared_function_infos_(shared_function_infos),
13925  index_(0) {}
13926 
13927 SharedFunctionInfo* SharedFunctionInfo::ScriptIterator::Next() {
13928  while (index_ < shared_function_infos_->length()) {
13929  MaybeObject raw = shared_function_infos_->Get(index_++);
13930  HeapObject* heap_object;
13931  if (!raw->GetHeapObject(&heap_object) ||
13932  heap_object->IsUndefined(isolate_)) {
13933  continue;
13934  }
13935  return SharedFunctionInfo::cast(heap_object);
13936  }
13937  return nullptr;
13938 }
13939 
13940 void SharedFunctionInfo::ScriptIterator::Reset(Script* script) {
13941  shared_function_infos_ = handle(script->shared_function_infos(), isolate_);
13942  index_ = 0;
13943 }
13944 
13945 SharedFunctionInfo::GlobalIterator::GlobalIterator(Isolate* isolate)
13946  : script_iterator_(isolate),
13947  noscript_sfi_iterator_(isolate->heap()->noscript_shared_function_infos()),
13948  sfi_iterator_(isolate, script_iterator_.Next()) {}
13949 
13950 SharedFunctionInfo* SharedFunctionInfo::GlobalIterator::Next() {
13951  HeapObject* next = noscript_sfi_iterator_.Next();
13952  if (next != nullptr) return SharedFunctionInfo::cast(next);
13953  for (;;) {
13954  next = sfi_iterator_.Next();
13955  if (next != nullptr) return SharedFunctionInfo::cast(next);
13956  Script* next_script = script_iterator_.Next();
13957  if (next_script == nullptr) return nullptr;
13958  sfi_iterator_.Reset(next_script);
13959  }
13960 }
13961 
13962 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
13963  Handle<Object> script_object,
13964  int function_literal_id,
13965  bool reset_preparsed_scope_data) {
13966  if (shared->script() == *script_object) return;
13967  Isolate* isolate = shared->GetIsolate();
13968 
13969  if (reset_preparsed_scope_data &&
13970  shared->HasUncompiledDataWithPreParsedScope()) {
13971  shared->ClearPreParsedScopeData();
13972  }
13973 
13974  // Add shared function info to new script's list. If a collection occurs,
13975  // the shared function info may be temporarily in two lists.
13976  // This is okay because the gc-time processing of these lists can tolerate
13977  // duplicates.
13978  if (script_object->IsScript()) {
13979  DCHECK(!shared->script()->IsScript());
13980  Handle<Script> script = Handle<Script>::cast(script_object);
13981  Handle<WeakFixedArray> list =
13982  handle(script->shared_function_infos(), isolate);
13983 #ifdef DEBUG
13984  DCHECK_LT(function_literal_id, list->length());
13985  MaybeObject maybe_object = list->Get(function_literal_id);
13986  HeapObject* heap_object;
13987  if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
13988  DCHECK_EQ(heap_object, *shared);
13989  }
13990 #endif
13991  list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
13992 
13993  // Remove shared function info from root array.
13994  WeakArrayList* noscript_list =
13995  isolate->heap()->noscript_shared_function_infos();
13996  CHECK(noscript_list->RemoveOne(MaybeObjectHandle::Weak(shared)));
13997  } else {
13998  DCHECK(shared->script()->IsScript());
13999  Handle<WeakArrayList> list =
14000  isolate->factory()->noscript_shared_function_infos();
14001 
14002 #ifdef DEBUG
14003  if (FLAG_enable_slow_asserts) {
14004  WeakArrayList::Iterator iterator(*list);
14005  HeapObject* next;
14006  while ((next = iterator.Next()) != nullptr) {
14007  DCHECK_NE(next, *shared);
14008  }
14009  }
14010 #endif // DEBUG
14011 
14012  list =
14013  WeakArrayList::AddToEnd(isolate, list, MaybeObjectHandle::Weak(shared));
14014 
14015  isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
14016 
14017  // Remove shared function info from old script's list.
14018  Script* old_script = Script::cast(shared->script());
14019 
14020  // Due to liveedit, it might happen that the old_script doesn't know
14021  // about the SharedFunctionInfo, so we have to guard against that.
14022  Handle<WeakFixedArray> infos(old_script->shared_function_infos(), isolate);
14023  if (function_literal_id < infos->length()) {
14024  MaybeObject raw =
14025  old_script->shared_function_infos()->Get(function_literal_id);
14026  HeapObject* heap_object;
14027  if (raw->GetHeapObjectIfWeak(&heap_object) && heap_object == *shared) {
14028  old_script->shared_function_infos()->Set(
14029  function_literal_id, HeapObjectReference::Strong(
14030  ReadOnlyRoots(isolate).undefined_value()));
14031  }
14032  }
14033  }
14034 
14035  // Finally set new script.
14036  shared->set_script(*script_object);
14037 }
14038 
14039 bool SharedFunctionInfo::HasBreakInfo() const {
14040  if (!HasDebugInfo()) return false;
14041  DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14042  bool has_break_info = info->HasBreakInfo();
14043  return has_break_info;
14044 }
14045 
14046 bool SharedFunctionInfo::BreakAtEntry() const {
14047  if (!HasDebugInfo()) return false;
14048  DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14049  bool break_at_entry = info->BreakAtEntry();
14050  return break_at_entry;
14051 }
14052 
14053 bool SharedFunctionInfo::HasCoverageInfo() const {
14054  if (!HasDebugInfo()) return false;
14055  DebugInfo* info = DebugInfo::cast(GetDebugInfo());
14056  bool has_coverage_info = info->HasCoverageInfo();
14057  return has_coverage_info;
14058 }
14059 
14060 CoverageInfo SharedFunctionInfo::GetCoverageInfo() const {
14061  DCHECK(HasCoverageInfo());
14062  return CoverageInfo::cast(GetDebugInfo()->coverage_info());
14063 }
14064 
14065 String SharedFunctionInfo::DebugName() {
14066  DisallowHeapAllocation no_gc;
14067  String function_name = Name();
14068  if (function_name->length() > 0) return function_name;
14069  return inferred_name();
14070 }
14071 
14072 bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
14073  Vector<const char> filter = CStrVector(raw_filter);
14074  std::unique_ptr<char[]> cstrname(DebugName()->ToCString());
14075  return v8::internal::PassesFilter(CStrVector(cstrname.get()), filter);
14076 }
14077 
14078 bool SharedFunctionInfo::HasSourceCode() const {
14079  Isolate* isolate = GetIsolate();
14080  return !script()->IsUndefined(isolate) &&
14081  !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
14082 }
14083 
14084 // static
14085 Handle<Object> SharedFunctionInfo::GetSourceCode(
14086  Handle<SharedFunctionInfo> shared) {
14087  Isolate* isolate = shared->GetIsolate();
14088  if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
14089  Handle<String> source(String::cast(Script::cast(shared->script())->source()),
14090  isolate);
14091  return isolate->factory()->NewSubString(source, shared->StartPosition(),
14092  shared->EndPosition());
14093 }
14094 
14095 // static
14096 Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony(
14097  Handle<SharedFunctionInfo> shared) {
14098  Isolate* isolate = shared->GetIsolate();
14099  if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
14100  Handle<String> script_source(
14101  String::cast(Script::cast(shared->script())->source()), isolate);
14102  int start_pos = shared->function_token_position();
14103  DCHECK_NE(start_pos, kNoSourcePosition);
14104  Handle<String> source = isolate->factory()->NewSubString(
14105  script_source, start_pos, shared->EndPosition());
14106  if (!shared->is_wrapped()) return source;
14107 
14108  DCHECK(!shared->name_should_print_as_anonymous());
14109  IncrementalStringBuilder builder(isolate);
14110  builder.AppendCString("function ");
14111  builder.AppendString(Handle<String>(shared->Name(), isolate));
14112  builder.AppendCString("(");
14113  Handle<FixedArray> args(Script::cast(shared->script())->wrapped_arguments(),
14114  isolate);
14115  int argc = args->length();
14116  for (int i = 0; i < argc; i++) {
14117  if (i > 0) builder.AppendCString(", ");
14118  builder.AppendString(Handle<String>(String::cast(args->get(i)), isolate));
14119  }
14120  builder.AppendCString(") {\n");
14121  builder.AppendString(source);
14122  builder.AppendCString("\n}");
14123  return builder.Finish().ToHandleChecked();
14124 }
14125 
14126 bool SharedFunctionInfo::IsInlineable() {
14127  // Check that the function has a script associated with it.
14128  if (!script()->IsScript()) return false;
14129  if (GetIsolate()->is_precise_binary_code_coverage() &&
14130  !has_reported_binary_coverage()) {
14131  // We may miss invocations if this function is inlined.
14132  return false;
14133  }
14134  return !optimization_disabled();
14135 }
14136 
14137 int SharedFunctionInfo::SourceSize() { return EndPosition() - StartPosition(); }
14138 
14139 int SharedFunctionInfo::FindIndexInScript(Isolate* isolate) const {
14140  DisallowHeapAllocation no_gc;
14141 
14142  Object* script_obj = script();
14143  if (!script_obj->IsScript()) return FunctionLiteral::kIdTypeInvalid;
14144 
14145  WeakFixedArray* shared_info_list =
14146  Script::cast(script_obj)->shared_function_infos();
14147  SharedFunctionInfo::ScriptIterator iterator(
14148  isolate, Handle<WeakFixedArray>(&shared_info_list));
14149 
14150  for (SharedFunctionInfo* shared = iterator.Next(); shared != nullptr;
14151  shared = iterator.Next()) {
14152  if (shared == this) {
14153  return iterator.CurrentIndex();
14154  }
14155  }
14156 
14157  return FunctionLiteral::kIdTypeInvalid;
14158 }
14159 
14160 void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
14161  bool has_prototype_slot,
14162  int requested_embedder_fields,
14163  int requested_in_object_properties,
14164  int* instance_size,
14165  int* in_object_properties) {
14166  DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
14167  JSObject::kMaxEmbedderFields);
14168  requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
14169  int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
14170  int max_nof_fields =
14171  (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2;
14172  CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
14173  CHECK_LE(static_cast<unsigned>(requested_embedder_fields),
14174  static_cast<unsigned>(max_nof_fields));
14175  *in_object_properties = Min(requested_in_object_properties,
14176  max_nof_fields - requested_embedder_fields);
14177  *instance_size =
14178  header_size +
14179  ((requested_embedder_fields + *in_object_properties) << kPointerSizeLog2);
14180  CHECK_EQ(*in_object_properties,
14181  ((*instance_size - header_size) >> kPointerSizeLog2) -
14182  requested_embedder_fields);
14183  CHECK_LE(static_cast<unsigned>(*instance_size),
14184  static_cast<unsigned>(JSObject::kMaxInstanceSize));
14185 }
14186 
14187 // static
14188 bool JSFunction::CalculateInstanceSizeForDerivedClass(
14189  Handle<JSFunction> function, InstanceType instance_type,
14190  int requested_embedder_fields, int* instance_size,
14191  int* in_object_properties) {
14192  Isolate* isolate = function->GetIsolate();
14193  int expected_nof_properties = 0;
14194  for (PrototypeIterator iter(isolate, function, kStartAtReceiver);
14195  !iter.IsAtEnd(); iter.Advance()) {
14196  Handle<JSReceiver> current =
14197  PrototypeIterator::GetCurrent<JSReceiver>(iter);
14198  if (!current->IsJSFunction()) break;
14199  Handle<JSFunction> func(Handle<JSFunction>::cast(current));
14200  // The super constructor should be compiled for the number of expected
14201  // properties to be available.
14202  Handle<SharedFunctionInfo> shared(func->shared(), isolate);
14203  if (shared->is_compiled() ||
14204  Compiler::Compile(func, Compiler::CLEAR_EXCEPTION)) {
14205  DCHECK(shared->is_compiled());
14206  int count = shared->expected_nof_properties();
14207  // Check that the estimate is sane.
14208  if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) {
14209  expected_nof_properties += count;
14210  } else {
14211  expected_nof_properties = JSObject::kMaxInObjectProperties;
14212  }
14213  } else if (!shared->is_compiled()) {
14214  // In case there was a compilation error for the constructor we will
14215  // throw an error during instantiation. Hence we directly return 0;
14216  return false;
14217  }
14218  if (!IsDerivedConstructor(shared->kind())) break;
14219  }
14220  CalculateInstanceSizeHelper(instance_type, true, requested_embedder_fields,
14221  expected_nof_properties, instance_size,
14222  in_object_properties);
14223  return true;
14224 }
14225 
14226 
14227 // Output the source code without any allocation in the heap.
14228 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
14229  const SharedFunctionInfo* s = v.value;
14230  // For some native functions there is no source.
14231  if (!s->HasSourceCode()) return os << "<No Source>";
14232 
14233  // Get the source for the script which this function came from.
14234  // Don't use String::cast because we don't want more assertion errors while
14235  // we are already creating a stack dump.
14236  String script_source =
14237  String::unchecked_cast(Script::cast(s->script())->source());
14238 
14239  if (!script_source->LooksValid()) return os << "<Invalid Source>";
14240 
14241  if (!s->is_toplevel()) {
14242  os << "function ";
14243  String name = s->Name();
14244  if (name->length() > 0) {
14245  name->PrintUC16(os);
14246  }
14247  }
14248 
14249  int len = s->EndPosition() - s->StartPosition();
14250  if (len <= v.max_length || v.max_length < 0) {
14251  script_source->PrintUC16(os, s->StartPosition(), s->EndPosition());
14252  return os;
14253  } else {
14254  script_source->PrintUC16(os, s->StartPosition(),
14255  s->StartPosition() + v.max_length);
14256  return os << "...\n";
14257  }
14258 }
14259 
14260 
14261 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
14262  DCHECK_NE(reason, BailoutReason::kNoReason);
14263 
14264  set_flags(DisabledOptimizationReasonBits::update(flags(), reason));
14265  // Code should be the lazy compilation stub or else interpreted.
14266  DCHECK(abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
14267  abstract_code()->kind() == AbstractCode::BUILTIN);
14268  PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), this));
14269  if (FLAG_trace_opt) {
14270  PrintF("[disabled optimization for ");
14271  ShortPrint();
14272  PrintF(", reason: %s]\n", GetBailoutReason(reason));
14273  }
14274 }
14275 
14276 void SharedFunctionInfo::InitFromFunctionLiteral(
14277  Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit,
14278  bool is_toplevel) {
14279  Isolate* isolate = shared_info->GetIsolate();
14280  bool needs_position_info = true;
14281 
14282  // When adding fields here, make sure DeclarationScope::AnalyzePartially is
14283  // updated accordingly.
14284  shared_info->set_internal_formal_parameter_count(lit->parameter_count());
14285  shared_info->SetFunctionTokenPosition(lit->function_token_position(),
14286  lit->start_position());
14287  if (shared_info->scope_info()->HasPositionInfo()) {
14288  shared_info->scope_info()->SetPositionInfo(lit->start_position(),
14289  lit->end_position());
14290  needs_position_info = false;
14291  }
14292  shared_info->set_is_declaration(lit->is_declaration());
14293  shared_info->set_is_named_expression(lit->is_named_expression());
14294  shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
14295  shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
14296  shared_info->set_language_mode(lit->language_mode());
14297  shared_info->set_is_wrapped(lit->is_wrapped());
14298  // shared_info->set_kind(lit->kind());
14299  // FunctionKind must have already been set.
14300  DCHECK(lit->kind() == shared_info->kind());
14301  shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
14302  DCHECK_IMPLIES(lit->requires_instance_members_initializer(),
14303  IsClassConstructor(lit->kind()));
14304  shared_info->set_requires_instance_members_initializer(
14305  lit->requires_instance_members_initializer());
14306 
14307  shared_info->set_is_toplevel(is_toplevel);
14308  DCHECK(shared_info->outer_scope_info()->IsTheHole());
14309  if (!is_toplevel) {
14310  Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
14311  if (outer_scope) {
14312  shared_info->set_outer_scope_info(*outer_scope->scope_info());
14313  }
14314  }
14315 
14316  // For lazy parsed functions, the following flags will be inaccurate since we
14317  // don't have the information yet. They're set later in
14318  // SetSharedFunctionFlagsFromLiteral (compiler.cc), when the function is
14319  // really parsed and compiled.
14320  if (lit->ShouldEagerCompile()) {
14321  shared_info->set_length(lit->function_length());
14322  shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
14323  shared_info->SetExpectedNofPropertiesFromEstimate(lit);
14324  DCHECK_NULL(lit->produced_preparsed_scope_data());
14325  // If we're about to eager compile, we'll have the function literal
14326  // available, so there's no need to wastefully allocate an uncompiled data.
14327  // TODO(leszeks): This should be explicitly passed as a parameter, rather
14328  // than relying on a property of the literal.
14329  needs_position_info = false;
14330  } else {
14331  // Set an invalid length for lazy functions. This way we can set the correct
14332  // value after compiling, but avoid overwriting values set manually by the
14333  // bootstrapper.
14334  shared_info->set_length(SharedFunctionInfo::kInvalidLength);
14335  ProducedPreParsedScopeData* scope_data =
14336  lit->produced_preparsed_scope_data();
14337  if (scope_data != nullptr) {
14338  Handle<PreParsedScopeData> pre_parsed_scope_data;
14339  if (scope_data->Serialize(shared_info->GetIsolate())
14340  .ToHandle(&pre_parsed_scope_data)) {
14341  Handle<UncompiledData> data =
14342  isolate->factory()->NewUncompiledDataWithPreParsedScope(
14343  lit->inferred_name(), lit->start_position(),
14344  lit->end_position(), lit->function_literal_id(),
14345  pre_parsed_scope_data);
14346  shared_info->set_uncompiled_data(*data);
14347  needs_position_info = false;
14348  }
14349  }
14350  }
14351  if (needs_position_info) {
14352  Handle<UncompiledData> data =
14353  isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
14354  lit->inferred_name(), lit->start_position(), lit->end_position(),
14355  lit->function_literal_id());
14356  shared_info->set_uncompiled_data(*data);
14357  }
14358 }
14359 
14360 void SharedFunctionInfo::SetExpectedNofPropertiesFromEstimate(
14361  FunctionLiteral* literal) {
14362  int estimate = literal->expected_property_count();
14363 
14364  // If no properties are added in the constructor, they are more likely
14365  // to be added later.
14366  if (estimate == 0) estimate = 2;
14367 
14368  // Inobject slack tracking will reclaim redundant inobject space later,
14369  // so we can afford to adjust the estimate generously.
14370  estimate += 8;
14371 
14372  // Limit actual estimate to fit in a 8 bit field, we will never allocate
14373  // more than this in any case.
14374  STATIC_ASSERT(JSObject::kMaxInObjectProperties <= kMaxUInt8);
14375  estimate = std::min(estimate, kMaxUInt8);
14376 
14377  set_expected_nof_properties(estimate);
14378 }
14379 
14380 void SharedFunctionInfo::SetFunctionTokenPosition(int function_token_position,
14381  int start_position) {
14382  int offset;
14383  if (function_token_position == kNoSourcePosition) {
14384  offset = 0;
14385  } else {
14386  offset = start_position - function_token_position;
14387  }
14388 
14389  if (offset > kMaximumFunctionTokenOffset) {
14390  offset = kFunctionTokenOutOfRange;
14391  }
14392  set_raw_function_token_offset(offset);
14393 }
14394 
14395 int SharedFunctionInfo::StartPosition() const {
14396  Object* maybe_scope_info = name_or_scope_info();
14397  if (maybe_scope_info->IsScopeInfo()) {
14398  ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14399  if (info->HasPositionInfo()) {
14400  return info->StartPosition();
14401  }
14402  } else if (HasUncompiledData()) {
14403  // Works with or without scope.
14404  return uncompiled_data()->start_position();
14405  } else if (IsApiFunction() || HasBuiltinId()) {
14406  DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
14407  return 0;
14408  }
14409  return kNoSourcePosition;
14410 }
14411 
14412 int SharedFunctionInfo::EndPosition() const {
14413  Object* maybe_scope_info = name_or_scope_info();
14414  if (maybe_scope_info->IsScopeInfo()) {
14415  ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14416  if (info->HasPositionInfo()) {
14417  return info->EndPosition();
14418  }
14419  } else if (HasUncompiledData()) {
14420  // Works with or without scope.
14421  return uncompiled_data()->end_position();
14422  } else if (IsApiFunction() || HasBuiltinId()) {
14423  DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
14424  return 0;
14425  }
14426  return kNoSourcePosition;
14427 }
14428 
14429 int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate) const {
14430  // Fast path for the common case when the SFI is uncompiled and so the
14431  // function literal id is already in the uncompiled data.
14432  if (HasUncompiledData()) {
14433  int id = uncompiled_data()->function_literal_id();
14434  // Make sure the id is what we should have found with the slow path.
14435  DCHECK_EQ(id, FindIndexInScript(isolate));
14436  return id;
14437  }
14438 
14439  // Otherwise, search for the function in the SFI's script's function list,
14440  // and return its index in that list.e
14441  return FindIndexInScript(isolate);
14442 }
14443 
14444 void SharedFunctionInfo::SetPosition(int start_position, int end_position) {
14445  Object* maybe_scope_info = name_or_scope_info();
14446  if (maybe_scope_info->IsScopeInfo()) {
14447  ScopeInfo info = ScopeInfo::cast(maybe_scope_info);
14448  if (info->HasPositionInfo()) {
14449  info->SetPositionInfo(start_position, end_position);
14450  }
14451  } else if (HasUncompiledData()) {
14452  if (HasUncompiledDataWithPreParsedScope()) {
14453  // Clear out preparsed scope data, since the position setter invalidates
14454  // any scope data.
14455  ClearPreParsedScopeData();
14456  }
14457  uncompiled_data()->set_start_position(start_position);
14458  uncompiled_data()->set_end_position(end_position);
14459  } else {
14460  UNREACHABLE();
14461  }
14462 }
14463 
14464 void Map::StartInobjectSlackTracking() {
14465  DCHECK(!IsInobjectSlackTrackingInProgress());
14466  if (UnusedPropertyFields() == 0) return;
14467  set_construction_counter(Map::kSlackTrackingCounterStart);
14468 }
14469 
14470 void ObjectVisitor::VisitCodeTarget(Code host, RelocInfo* rinfo) {
14471  DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
14472  Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
14473  Object* new_pointer = old_pointer;
14474  VisitPointer(host, ObjectSlot(&new_pointer));
14475  DCHECK_EQ(old_pointer, new_pointer);
14476 }
14477 
14478 void ObjectVisitor::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) {
14479  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
14480  Object* old_pointer = rinfo->target_object();
14481  Object* new_pointer = old_pointer;
14482  VisitPointer(host, ObjectSlot(&new_pointer));
14483  DCHECK_EQ(old_pointer, new_pointer);
14484 }
14485 
14486 void ObjectVisitor::VisitRelocInfo(RelocIterator* it) {
14487  for (; !it->done(); it->next()) {
14488  it->rinfo()->Visit(this);
14489  }
14490 }
14491 
14492 void Code::ClearEmbeddedObjects(Heap* heap) {
14493  HeapObject* undefined = ReadOnlyRoots(heap).undefined_value();
14494  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14495  for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
14496  RelocInfo::Mode mode = it.rinfo()->rmode();
14497  if (mode == RelocInfo::EMBEDDED_OBJECT) {
14498  it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
14499  }
14500  }
14501  set_embedded_objects_cleared(true);
14502 }
14503 
14504 
14505 void Code::Relocate(intptr_t delta) {
14506  for (RelocIterator it(*this, RelocInfo::kApplyMask); !it.done(); it.next()) {
14507  it.rinfo()->apply(delta);
14508  }
14509  Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
14510 }
14511 
14512 void Code::FlushICache() const {
14513  Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
14514 }
14515 
14516 void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
14517  // Copy code.
14518  CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
14519  static_cast<size_t>(desc.instr_size));
14520 
14521  // Copy unwinding info, if any.
14522  if (desc.unwinding_info) {
14523  DCHECK_GT(desc.unwinding_info_size, 0);
14524  set_unwinding_info_size(desc.unwinding_info_size);
14525  CopyBytes(reinterpret_cast<byte*>(unwinding_info_start()),
14526  desc.unwinding_info,
14527  static_cast<size_t>(desc.unwinding_info_size));
14528  }
14529 
14530  // Copy reloc info.
14531  CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
14532 
14533  // Unbox handles and relocate.
14534  Assembler* origin = desc.origin;
14535  AllowDeferredHandleDereference embedding_raw_address;
14536  const int mode_mask = RelocInfo::PostCodegenRelocationMask();
14537  for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
14538  RelocInfo::Mode mode = it.rinfo()->rmode();
14539  if (mode == RelocInfo::EMBEDDED_OBJECT) {
14540  Handle<HeapObject> p = it.rinfo()->target_object_handle(origin);
14541  it.rinfo()->set_target_object(heap, *p, UPDATE_WRITE_BARRIER,
14542  SKIP_ICACHE_FLUSH);
14543  } else if (RelocInfo::IsCodeTargetMode(mode)) {
14544  // Rewrite code handles to direct pointers to the first instruction in the
14545  // code object.
14546  Handle<Object> p = it.rinfo()->target_object_handle(origin);
14547  Code code = Code::cast(*p);
14548  it.rinfo()->set_target_address(code->raw_instruction_start(),
14549  UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
14550  } else if (RelocInfo::IsRuntimeEntry(mode)) {
14551  Address p = it.rinfo()->target_runtime_entry(origin);
14552  it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
14553  SKIP_ICACHE_FLUSH);
14554  } else {
14555  intptr_t delta =
14556  raw_instruction_start() - reinterpret_cast<Address>(desc.buffer);
14557  it.rinfo()->apply(delta);
14558  }
14559  }
14560 }
14561 
14562 
14563 SafepointEntry Code::GetSafepointEntry(Address pc) {
14564  SafepointTable table(*this);
14565  return table.FindEntry(pc);
14566 }
14567 
14568 int Code::OffHeapInstructionSize() const {
14569  DCHECK(is_off_heap_trampoline());
14570  if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_size();
14571  EmbeddedData d = EmbeddedData::FromBlob();
14572  return d.InstructionSizeOfBuiltin(builtin_index());
14573 }
14574 
14575 Address Code::OffHeapInstructionStart() const {
14576  DCHECK(is_off_heap_trampoline());
14577  if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_start();
14578  EmbeddedData d = EmbeddedData::FromBlob();
14579  return d.InstructionStartOfBuiltin(builtin_index());
14580 }
14581 
14582 Address Code::OffHeapInstructionEnd() const {
14583  DCHECK(is_off_heap_trampoline());
14584  if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_end();
14585  EmbeddedData d = EmbeddedData::FromBlob();
14586  return d.InstructionStartOfBuiltin(builtin_index()) +
14587  d.InstructionSizeOfBuiltin(builtin_index());
14588 }
14589 
14590 namespace {
14591 template <typename Code>
14592 void SetStackFrameCacheCommon(Isolate* isolate, Handle<Code> code,
14593  Handle<SimpleNumberDictionary> cache) {
14594  Handle<Object> maybe_table(code->source_position_table(), isolate);
14595  if (maybe_table->IsSourcePositionTableWithFrameCache()) {
14596  Handle<SourcePositionTableWithFrameCache>::cast(maybe_table)
14597  ->set_stack_frame_cache(*cache);
14598  return;
14599  }
14600  DCHECK(maybe_table->IsByteArray());
14601  Handle<ByteArray> table(Handle<ByteArray>::cast(maybe_table));
14602  Handle<SourcePositionTableWithFrameCache> table_with_cache =
14603  isolate->factory()->NewSourcePositionTableWithFrameCache(table, cache);
14604  code->set_source_position_table(*table_with_cache);
14605 }
14606 } // namespace
14607 
14608 // static
14609 void AbstractCode::SetStackFrameCache(Handle<AbstractCode> abstract_code,
14610  Handle<SimpleNumberDictionary> cache) {
14611  if (abstract_code->IsCode()) {
14612  SetStackFrameCacheCommon(
14613  abstract_code->GetIsolate(),
14614  handle(abstract_code->GetCode(), abstract_code->GetIsolate()), cache);
14615  } else {
14616  SetStackFrameCacheCommon(
14617  abstract_code->GetIsolate(),
14618  handle(abstract_code->GetBytecodeArray(), abstract_code->GetIsolate()),
14619  cache);
14620  }
14621 }
14622 
14623 namespace {
14624 template <typename Code>
14625 void DropStackFrameCacheCommon(Code code) {
14626  i::Object* maybe_table = code->source_position_table();
14627  if (maybe_table->IsByteArray()) return;
14628  DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
14629  code->set_source_position_table(
14630  i::SourcePositionTableWithFrameCache::cast(maybe_table)
14631  ->source_position_table());
14632 }
14633 } // namespace
14634 
14635 void AbstractCode::DropStackFrameCache() {
14636  if (IsCode()) {
14637  DropStackFrameCacheCommon(GetCode());
14638  } else {
14639  DropStackFrameCacheCommon(GetBytecodeArray());
14640  }
14641 }
14642 
14643 int AbstractCode::SourcePosition(int offset) {
14644  int position = 0;
14645  // Subtract one because the current PC is one instruction after the call site.
14646  if (IsCode()) offset--;
14647  for (SourcePositionTableIterator iterator(source_position_table());
14648  !iterator.done() && iterator.code_offset() <= offset;
14649  iterator.Advance()) {
14650  position = iterator.source_position().ScriptOffset();
14651  }
14652  return position;
14653 }
14654 
14655 int AbstractCode::SourceStatementPosition(int offset) {
14656  // First find the closest position.
14657  int position = SourcePosition(offset);
14658  // Now find the closest statement position before the position.
14659  int statement_position = 0;
14660  for (SourcePositionTableIterator it(source_position_table()); !it.done();
14661  it.Advance()) {
14662  if (it.is_statement()) {
14663  int p = it.source_position().ScriptOffset();
14664  if (statement_position < p && p <= position) {
14665  statement_position = p;
14666  }
14667  }
14668  }
14669  return statement_position;
14670 }
14671 
14672 void JSFunction::ClearTypeFeedbackInfo() {
14673  if (feedback_cell()->value()->IsFeedbackVector()) {
14674  FeedbackVector* vector = feedback_vector();
14675  Isolate* isolate = GetIsolate();
14676  if (vector->ClearSlots(isolate)) {
14677  IC::OnFeedbackChanged(isolate, vector, FeedbackSlot::Invalid(), this,
14678  "ClearTypeFeedbackInfo");
14679  }
14680  }
14681 }
14682 
14683 void Code::PrintDeoptLocation(FILE* out, const char* str, Address pc) {
14684  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(*this, pc);
14685  class SourcePosition pos = info.position;
14686  if (info.deopt_reason != DeoptimizeReason::kUnknown || pos.IsKnown()) {
14687  PrintF(out, "%s", str);
14688  OFStream outstr(out);
14689  pos.Print(outstr, *this);
14690  PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
14691  }
14692 }
14693 
14694 
14695 bool Code::CanDeoptAt(Address pc) {
14696  DeoptimizationData deopt_data =
14697  DeoptimizationData::cast(deoptimization_data());
14698  Address code_start_address = InstructionStart();
14699  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
14700  if (deopt_data->Pc(i)->value() == -1) continue;
14701  Address address = code_start_address + deopt_data->Pc(i)->value();
14702  if (address == pc && deopt_data->BytecodeOffset(i) != BailoutId::None()) {
14703  return true;
14704  }
14705  }
14706  return false;
14707 }
14708 
14709 
14710 // Identify kind of code.
14711 const char* Code::Kind2String(Kind kind) {
14712  switch (kind) {
14713 #define CASE(name) case name: return #name;
14714  CODE_KIND_LIST(CASE)
14715 #undef CASE
14716  case NUMBER_OF_KINDS: break;
14717  }
14718  UNREACHABLE();
14719 }
14720 
14721 // Identify kind of code.
14722 const char* AbstractCode::Kind2String(Kind kind) {
14723  if (kind < AbstractCode::INTERPRETED_FUNCTION)
14724  return Code::Kind2String(static_cast<Code::Kind>(kind));
14725  if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
14726  UNREACHABLE();
14727 }
14728 
14729 bool Code::IsIsolateIndependent(Isolate* isolate) {
14730  constexpr int all_real_modes_mask =
14731  (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
14732  constexpr int mode_mask = all_real_modes_mask &
14733  ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
14734  ~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
14735  ~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
14736  ~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
14737  STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
14738  STATIC_ASSERT(RelocInfo::ModeMask(RelocInfo::COMMENT) ==
14739  (1 << RelocInfo::COMMENT));
14740  STATIC_ASSERT(mode_mask ==
14741  (RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14742  RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
14743  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
14744  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
14745  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
14746  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
14747  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
14748  RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
14749  RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
14750 
14751  bool is_process_independent = true;
14752  for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
14753 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
14754  defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) || \
14755  defined(V8_TARGET_ARCH_IA32)
14756  // On these platforms we emit relative builtin-to-builtin
14757  // jumps for isolate independent builtins in the snapshot. They are later
14758  // rewritten as pc-relative jumps to the off-heap instruction stream and are
14759  // thus process-independent. See also: FinalizeEmbeddedCodeTargets.
14760  if (RelocInfo::IsCodeTargetMode(it.rinfo()->rmode())) {
14761  Address target_address = it.rinfo()->target_address();
14762  if (InstructionStream::PcIsOffHeap(isolate, target_address)) continue;
14763 
14764  Code target = Code::GetCodeFromTargetAddress(target_address);
14765  CHECK(target->IsCode());
14766  if (Builtins::IsIsolateIndependentBuiltin(target)) continue;
14767  }
14768 #endif
14769  is_process_independent = false;
14770  }
14771 
14772  return is_process_independent;
14773 }
14774 
14775 bool Code::Inlines(SharedFunctionInfo* sfi) {
14776  // We can only check for inlining for optimized code.
14777  DCHECK(is_optimized_code());
14778  DisallowHeapAllocation no_gc;
14779  DeoptimizationData const data =
14780  DeoptimizationData::cast(deoptimization_data());
14781  if (data->length() == 0) return false;
14782  if (data->SharedFunctionInfo() == sfi) return true;
14783  FixedArray const literals = data->LiteralArray();
14784  int const inlined_count = data->InlinedFunctionCount()->value();
14785  for (int i = 0; i < inlined_count; ++i) {
14786  if (SharedFunctionInfo::cast(literals->get(i)) == sfi) return true;
14787  }
14788  return false;
14789 }
14790 
14791 Code::OptimizedCodeIterator::OptimizedCodeIterator(Isolate* isolate) {
14792  isolate_ = isolate;
14793  Object* list = isolate->heap()->native_contexts_list();
14794  next_context_ = list->IsUndefined(isolate_) ? Context() : Context::cast(list);
14795 }
14796 
14797 Code Code::OptimizedCodeIterator::Next() {
14798  do {
14799  Object* next;
14800  if (!current_code_.is_null()) {
14801  // Get next code in the linked list.
14802  next = current_code_->next_code_link();
14803  } else if (!next_context_.is_null()) {
14804  // Linked list of code exhausted. Get list of next context.
14805  next = next_context_->OptimizedCodeListHead();
14806  Object* next_context = next_context_->next_context_link();
14807  next_context_ = next_context->IsUndefined(isolate_)
14808  ? Context()
14809  : Context::cast(next_context);
14810  } else {
14811  // Exhausted contexts.
14812  return Code();
14813  }
14814  current_code_ = next->IsUndefined(isolate_) ? Code() : Code::cast(next);
14815  } while (current_code_.is_null());
14816  DCHECK_EQ(Code::OPTIMIZED_FUNCTION, current_code_->kind());
14817  return current_code_;
14818 }
14819 
14820 #ifdef ENABLE_DISASSEMBLER
14821 
14822 namespace {
14823 void print_pc(std::ostream& os, int pc) {
14824  if (pc == -1) {
14825  os << "NA";
14826  } else {
14827  os << std::hex << pc << std::dec;
14828  }
14829 }
14830 } // anonymous namespace
14831 
14832 void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT
14833  if (length() == 0) {
14834  os << "Deoptimization Input Data invalidated by lazy deoptimization\n";
14835  return;
14836  }
14837 
14838  disasm::NameConverter converter;
14839  int const inlined_function_count = InlinedFunctionCount()->value();
14840  os << "Inlined functions (count = " << inlined_function_count << ")\n";
14841  for (int id = 0; id < inlined_function_count; ++id) {
14842  Object* info = LiteralArray()->get(id);
14843  os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
14844  }
14845  os << "\n";
14846  int deopt_count = DeoptCount();
14847  os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
14848  if (0 != deopt_count) {
14849  os << " index bytecode-offset pc";
14850  if (FLAG_print_code_verbose) os << " commands";
14851  os << "\n";
14852  }
14853  for (int i = 0; i < deopt_count; i++) {
14854  os << std::setw(6) << i << " " << std::setw(15)
14855  << BytecodeOffset(i).ToInt() << " " << std::setw(4);
14856  print_pc(os, Pc(i)->value());
14857  os << std::setw(2);
14858 
14859  if (!FLAG_print_code_verbose) {
14860  os << "\n";
14861  continue;
14862  }
14863 
14864  // Print details of the frame translation.
14865  int translation_index = TranslationIndex(i)->value();
14866  TranslationIterator iterator(TranslationByteArray(), translation_index);
14867  Translation::Opcode opcode =
14868  static_cast<Translation::Opcode>(iterator.Next());
14869  DCHECK(Translation::BEGIN == opcode);
14870  int frame_count = iterator.Next();
14871  int jsframe_count = iterator.Next();
14872  int update_feedback_count = iterator.Next();
14873  os << " " << Translation::StringFor(opcode)
14874  << " {frame count=" << frame_count
14875  << ", js frame count=" << jsframe_count
14876  << ", update_feedback_count=" << update_feedback_count << "}\n";
14877 
14878  while (iterator.HasNext() &&
14879  Translation::BEGIN !=
14880  (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
14881  os << std::setw(31) << " " << Translation::StringFor(opcode) << " ";
14882 
14883  switch (opcode) {
14884  case Translation::BEGIN:
14885  UNREACHABLE();
14886  break;
14887 
14888  case Translation::INTERPRETED_FRAME: {
14889  int bytecode_offset = iterator.Next();
14890  int shared_info_id = iterator.Next();
14891  unsigned height = iterator.Next();
14892  int return_value_offset = iterator.Next();
14893  int return_value_count = iterator.Next();
14894  Object* shared_info = LiteralArray()->get(shared_info_id);
14895  os << "{bytecode_offset=" << bytecode_offset << ", function="
14896  << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14897  << ", height=" << height << ", retval=@" << return_value_offset
14898  << "(#" << return_value_count << ")}";
14899  break;
14900  }
14901 
14902  case Translation::CONSTRUCT_STUB_FRAME: {
14903  int bailout_id = iterator.Next();
14904  int shared_info_id = iterator.Next();
14905  Object* shared_info = LiteralArray()->get(shared_info_id);
14906  unsigned height = iterator.Next();
14907  os << "{bailout_id=" << bailout_id << ", function="
14908  << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14909  << ", height=" << height << "}";
14910  break;
14911  }
14912 
14913  case Translation::BUILTIN_CONTINUATION_FRAME:
14914  case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
14915  case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
14916  int bailout_id = iterator.Next();
14917  int shared_info_id = iterator.Next();
14918  Object* shared_info = LiteralArray()->get(shared_info_id);
14919  unsigned height = iterator.Next();
14920  os << "{bailout_id=" << bailout_id << ", function="
14921  << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14922  << ", height=" << height << "}";
14923  break;
14924  }
14925 
14926  case Translation::ARGUMENTS_ADAPTOR_FRAME: {
14927  int shared_info_id = iterator.Next();
14928  Object* shared_info = LiteralArray()->get(shared_info_id);
14929  unsigned height = iterator.Next();
14930  os << "{function="
14931  << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14932  << ", height=" << height << "}";
14933  break;
14934  }
14935 
14936  case Translation::REGISTER: {
14937  int reg_code = iterator.Next();
14938  os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
14939  break;
14940  }
14941 
14942  case Translation::INT32_REGISTER: {
14943  int reg_code = iterator.Next();
14944  os << "{input=" << converter.NameOfCPURegister(reg_code)
14945  << " (int32)}";
14946  break;
14947  }
14948 
14949  case Translation::INT64_REGISTER: {
14950  int reg_code = iterator.Next();
14951  os << "{input=" << converter.NameOfCPURegister(reg_code)
14952  << " (int64)}";
14953  break;
14954  }
14955 
14956  case Translation::UINT32_REGISTER: {
14957  int reg_code = iterator.Next();
14958  os << "{input=" << converter.NameOfCPURegister(reg_code)
14959  << " (uint32)}";
14960  break;
14961  }
14962 
14963  case Translation::BOOL_REGISTER: {
14964  int reg_code = iterator.Next();
14965  os << "{input=" << converter.NameOfCPURegister(reg_code)
14966  << " (bool)}";
14967  break;
14968  }
14969 
14970  case Translation::FLOAT_REGISTER: {
14971  int reg_code = iterator.Next();
14972  os << "{input=" << FloatRegister::from_code(reg_code) << "}";
14973  break;
14974  }
14975 
14976  case Translation::DOUBLE_REGISTER: {
14977  int reg_code = iterator.Next();
14978  os << "{input=" << DoubleRegister::from_code(reg_code) << "}";
14979  break;
14980  }
14981 
14982  case Translation::STACK_SLOT: {
14983  int input_slot_index = iterator.Next();
14984  os << "{input=" << input_slot_index << "}";
14985  break;
14986  }
14987 
14988  case Translation::INT32_STACK_SLOT: {
14989  int input_slot_index = iterator.Next();
14990  os << "{input=" << input_slot_index << " (int32)}";
14991  break;
14992  }
14993 
14994  case Translation::INT64_STACK_SLOT: {
14995  int input_slot_index = iterator.Next();
14996  os << "{input=" << input_slot_index << " (int64)}";
14997  break;
14998  }
14999 
15000  case Translation::UINT32_STACK_SLOT: {
15001  int input_slot_index = iterator.Next();
15002  os << "{input=" << input_slot_index << " (uint32)}";
15003  break;
15004  }
15005 
15006  case Translation::BOOL_STACK_SLOT: {
15007  int input_slot_index = iterator.Next();
15008  os << "{input=" << input_slot_index << " (bool)}";
15009  break;
15010  }
15011 
15012  case Translation::FLOAT_STACK_SLOT:
15013  case Translation::DOUBLE_STACK_SLOT: {
15014  int input_slot_index = iterator.Next();
15015  os << "{input=" << input_slot_index << "}";
15016  break;
15017  }
15018 
15019  case Translation::LITERAL: {
15020  int literal_index = iterator.Next();
15021  Object* literal_value = LiteralArray()->get(literal_index);
15022  os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
15023  << ")}";
15024  break;
15025  }
15026 
15027  case Translation::DUPLICATED_OBJECT: {
15028  int object_index = iterator.Next();
15029  os << "{object_index=" << object_index << "}";
15030  break;
15031  }
15032 
15033  case Translation::ARGUMENTS_ELEMENTS:
15034  case Translation::ARGUMENTS_LENGTH: {
15035  CreateArgumentsType arguments_type =
15036  static_cast<CreateArgumentsType>(iterator.Next());
15037  os << "{arguments_type=" << arguments_type << "}";
15038  break;
15039  }
15040 
15041  case Translation::CAPTURED_OBJECT: {
15042  int args_length = iterator.Next();
15043  os << "{length=" << args_length << "}";
15044  break;
15045  }
15046 
15047  case Translation::UPDATE_FEEDBACK: {
15048  int literal_index = iterator.Next();
15049  FeedbackSlot slot(iterator.Next());
15050  os << "{feedback={vector_index=" << literal_index << ", slot=" << slot
15051  << "}}";
15052  break;
15053  }
15054  }
15055  os << "\n";
15056  }
15057  }
15058 }
15059 
15060 const char* Code::GetName(Isolate* isolate) const {
15061  if (is_stub()) {
15062  return CodeStub::MajorName(CodeStub::GetMajorKey(*this));
15063  } else if (kind() == BYTECODE_HANDLER) {
15064  return isolate->interpreter()->LookupNameOfBytecodeHandler(*this);
15065  } else {
15066  // There are some handlers and ICs that we can also find names for with
15067  // Builtins::Lookup.
15068  return isolate->builtins()->Lookup(raw_instruction_start());
15069  }
15070 }
15071 
15072 namespace {
15073 
15074 inline void DisassembleCodeRange(Isolate* isolate, std::ostream& os, Code code,
15075  Address begin, size_t size,
15076  Address current_pc) {
15077  Address end = begin + size;
15078  // TODO(mstarzinger): Refactor CodeReference to avoid the
15079  // unhandlified->handlified transition.
15080  AllowHandleAllocation allow_handles;
15081  DisallowHeapAllocation no_gc;
15082  HandleScope handle_scope(isolate);
15083  Disassembler::Decode(isolate, &os, reinterpret_cast<byte*>(begin),
15084  reinterpret_cast<byte*>(end),
15085  CodeReference(handle(code, isolate)), current_pc);
15086 }
15087 
15088 } // namespace
15089 
15090 void Code::Disassemble(const char* name, std::ostream& os, Address current_pc) {
15091  Isolate* isolate = GetIsolate();
15092  os << "kind = " << Kind2String(kind()) << "\n";
15093  if (is_stub()) {
15094  const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(*this));
15095  os << "major_key = " << (n == nullptr ? "null" : n) << "\n";
15096  os << "minor_key = " << CodeStub::MinorKeyFromKey(this->stub_key()) << "\n";
15097  }
15098  if (name == nullptr) {
15099  name = GetName(isolate);
15100  }
15101  if ((name != nullptr) && (name[0] != '\0')) {
15102  os << "name = " << name << "\n";
15103  }
15104  if (kind() == OPTIMIZED_FUNCTION) {
15105  os << "stack_slots = " << stack_slots() << "\n";
15106  }
15107  os << "compiler = " << (is_turbofanned() ? "turbofan" : "unknown") << "\n";
15108  os << "address = " << static_cast<const void*>(this) << "\n\n";
15109 
15110  if (is_off_heap_trampoline()) {
15111  int trampoline_size = raw_instruction_size();
15112  os << "Trampoline (size = " << trampoline_size << ")\n";
15113  DisassembleCodeRange(isolate, os, *this, raw_instruction_start(),
15114  trampoline_size, current_pc);
15115  os << "\n";
15116  }
15117 
15118  {
15119  int size = InstructionSize();
15120  int safepoint_offset =
15121  has_safepoint_info() ? safepoint_table_offset() : size;
15122  int constant_pool_offset = this->constant_pool_offset();
15123  int handler_offset = handler_table_offset() ? handler_table_offset() : size;
15124 
15125  // Stop before reaching any embedded tables
15126  int code_size =
15127  Min(handler_offset, Min(safepoint_offset, constant_pool_offset));
15128  os << "Instructions (size = " << code_size << ")\n";
15129  DisassembleCodeRange(isolate, os, *this, InstructionStart(), code_size,
15130  current_pc);
15131 
15132  if (constant_pool_offset < size) {
15133  int constant_pool_size = safepoint_offset - constant_pool_offset;
15134  DCHECK_EQ(constant_pool_size & kPointerAlignmentMask, 0);
15135  os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
15136  Vector<char> buf = Vector<char>::New(50);
15137  intptr_t* ptr = reinterpret_cast<intptr_t*>(InstructionStart() +
15138  constant_pool_offset);
15139  for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
15140  SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
15141  os << static_cast<const void*>(ptr) << " " << buf.start() << "\n";
15142  }
15143  }
15144  }
15145  os << "\n";
15146 
15147  SourcePositionTableIterator it(SourcePositionTable());
15148  if (!it.done()) {
15149  os << "Source positions:\n pc offset position\n";
15150  for (; !it.done(); it.Advance()) {
15151  os << std::setw(10) << std::hex << it.code_offset() << std::dec
15152  << std::setw(10) << it.source_position().ScriptOffset()
15153  << (it.is_statement() ? " statement" : "") << "\n";
15154  }
15155  os << "\n";
15156  }
15157 
15158  if (kind() == OPTIMIZED_FUNCTION) {
15159  DeoptimizationData data =
15160  DeoptimizationData::cast(this->deoptimization_data());
15161  data->DeoptimizationDataPrint(os);
15162  }
15163  os << "\n";
15164 
15165  if (has_safepoint_info()) {
15166  SafepointTable table(*this);
15167  os << "Safepoints (size = " << table.size() << ")\n";
15168  for (unsigned i = 0; i < table.length(); i++) {
15169  unsigned pc_offset = table.GetPcOffset(i);
15170  os << reinterpret_cast<const void*>(InstructionStart() + pc_offset)
15171  << " ";
15172  os << std::setw(6) << std::hex << pc_offset << " " << std::setw(4);
15173  int trampoline_pc = table.GetTrampolinePcOffset(i);
15174  print_pc(os, trampoline_pc);
15175  os << std::dec << " ";
15176  table.PrintEntry(i, os);
15177  os << " (sp -> fp) ";
15178  SafepointEntry entry = table.GetEntry(i);
15179  if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
15180  os << std::setw(6) << entry.deoptimization_index();
15181  } else {
15182  os << "<none>";
15183  }
15184  if (entry.argument_count() > 0) {
15185  os << " argc: " << entry.argument_count();
15186  }
15187  os << "\n";
15188  }
15189  os << "\n";
15190  }
15191 
15192  if (handler_table_offset() > 0) {
15193  HandlerTable table(*this);
15194  os << "Handler Table (size = " << table.NumberOfReturnEntries() << ")\n";
15195  if (kind() == OPTIMIZED_FUNCTION) {
15196  table.HandlerTableReturnPrint(os);
15197  }
15198  os << "\n";
15199  }
15200 
15201  os << "RelocInfo (size = " << relocation_size() << ")\n";
15202  for (RelocIterator it(*this); !it.done(); it.next()) {
15203  it.rinfo()->Print(isolate, os);
15204  }
15205  os << "\n";
15206 
15207  if (has_unwinding_info()) {
15208  os << "UnwindingInfo (size = " << unwinding_info_size() << ")\n";
15209  EhFrameDisassembler eh_frame_disassembler(
15210  reinterpret_cast<byte*>(unwinding_info_start()),
15211  reinterpret_cast<byte*>(unwinding_info_end()));
15212  eh_frame_disassembler.DisassembleToStream(os);
15213  os << "\n";
15214  }
15215 }
15216 #endif // ENABLE_DISASSEMBLER
15217 
15218 void BytecodeArray::Disassemble(std::ostream& os) {
15219  DisallowHeapAllocation no_gc;
15220 
15221  os << "Parameter count " << parameter_count() << "\n";
15222  os << "Frame size " << frame_size() << "\n";
15223 
15224  Address base_address = GetFirstBytecodeAddress();
15225  SourcePositionTableIterator source_positions(SourcePositionTable());
15226 
15227  // Storage for backing the handle passed to the iterator. This handle won't be
15228  // updated by the gc, but that's ok because we've disallowed GCs anyway.
15229  BytecodeArray handle_storage = *this;
15230  Handle<BytecodeArray> handle(reinterpret_cast<Address*>(&handle_storage));
15231  interpreter::BytecodeArrayIterator iterator(handle);
15232  while (!iterator.done()) {
15233  if (!source_positions.done() &&
15234  iterator.current_offset() == source_positions.code_offset()) {
15235  os << std::setw(5) << source_positions.source_position().ScriptOffset();
15236  os << (source_positions.is_statement() ? " S> " : " E> ");
15237  source_positions.Advance();
15238  } else {
15239  os << " ";
15240  }
15241  Address current_address = base_address + iterator.current_offset();
15242  os << reinterpret_cast<const void*>(current_address) << " @ "
15243  << std::setw(4) << iterator.current_offset() << " : ";
15244  interpreter::BytecodeDecoder::Decode(
15245  os, reinterpret_cast<byte*>(current_address), parameter_count());
15246  if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
15247  Address jump_target = base_address + iterator.GetJumpTargetOffset();
15248  os << " (" << reinterpret_cast<void*>(jump_target) << " @ "
15249  << iterator.GetJumpTargetOffset() << ")";
15250  }
15251  if (interpreter::Bytecodes::IsSwitch(iterator.current_bytecode())) {
15252  os << " {";
15253  bool first_entry = true;
15254  for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
15255  if (first_entry) {
15256  first_entry = false;
15257  } else {
15258  os << ",";
15259  }
15260  os << " " << entry.case_value << ": @" << entry.target_offset;
15261  }
15262  os << " }";
15263  }
15264  os << std::endl;
15265  iterator.Advance();
15266  }
15267 
15268  os << "Constant pool (size = " << constant_pool()->length() << ")\n";
15269 #ifdef OBJECT_PRINT
15270  if (constant_pool()->length() > 0) {
15271  constant_pool()->Print();
15272  }
15273 #endif
15274 
15275  os << "Handler Table (size = " << handler_table()->length() << ")\n";
15276 #ifdef ENABLE_DISASSEMBLER
15277  if (handler_table()->length() > 0) {
15278  HandlerTable table(*this);
15279  table.HandlerTableRangePrint(os);
15280  }
15281 #endif
15282 }
15283 
15284 void BytecodeArray::CopyBytecodesTo(BytecodeArray to) {
15285  BytecodeArray from = *this;
15286  DCHECK_EQ(from->length(), to->length());
15287  CopyBytes(reinterpret_cast<byte*>(to->GetFirstBytecodeAddress()),
15288  reinterpret_cast<byte*>(from->GetFirstBytecodeAddress()),
15289  from->length());
15290 }
15291 
15292 void BytecodeArray::MakeOlder() {
15293  // BytecodeArray is aged in concurrent marker.
15294  // The word must be completely within the byte code array.
15295  Address age_addr = address() + kBytecodeAgeOffset;
15296  DCHECK_LE((age_addr & ~kPointerAlignmentMask) + kPointerSize,
15297  address() + Size());
15298  Age age = bytecode_age();
15299  if (age < kLastBytecodeAge) {
15300  base::AsAtomic8::Release_CompareAndSwap(reinterpret_cast<byte*>(age_addr),
15301  age, age + 1);
15302  }
15303 
15304  DCHECK_GE(bytecode_age(), kFirstBytecodeAge);
15305  DCHECK_LE(bytecode_age(), kLastBytecodeAge);
15306 }
15307 
15308 bool BytecodeArray::IsOld() const {
15309  return bytecode_age() >= kIsOldBytecodeAge;
15310 }
15311 
15312 // static
15313 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
15314  DCHECK_GE(capacity, 0);
15315  array->GetIsolate()->factory()->NewJSArrayStorage(
15316  array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
15317 }
15318 
15319 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
15320  // We should never end in here with a pixel or external array.
15321  DCHECK(array->AllowsSetLength());
15322  if (array->SetLengthWouldNormalize(new_length)) {
15323  JSObject::NormalizeElements(array);
15324  }
15325  array->GetElementsAccessor()->SetLength(array, new_length);
15326 }
15327 
15328 DependentCode* DependentCode::GetDependentCode(Handle<HeapObject> object) {
15329  if (object->IsMap()) {
15330  return Handle<Map>::cast(object)->dependent_code();
15331  } else if (object->IsPropertyCell()) {
15332  return Handle<PropertyCell>::cast(object)->dependent_code();
15333  } else if (object->IsAllocationSite()) {
15334  return Handle<AllocationSite>::cast(object)->dependent_code();
15335  }
15336  UNREACHABLE();
15337 }
15338 
15339 void DependentCode::SetDependentCode(Handle<HeapObject> object,
15340  Handle<DependentCode> dep) {
15341  if (object->IsMap()) {
15342  Handle<Map>::cast(object)->set_dependent_code(*dep);
15343  } else if (object->IsPropertyCell()) {
15344  Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
15345  } else if (object->IsAllocationSite()) {
15346  Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
15347  } else {
15348  UNREACHABLE();
15349  }
15350 }
15351 
15352 void DependentCode::InstallDependency(Isolate* isolate,
15353  const MaybeObjectHandle& code,
15354  Handle<HeapObject> object,
15355  DependencyGroup group) {
15356  Handle<DependentCode> old_deps(DependentCode::GetDependentCode(object),
15357  isolate);
15358  Handle<DependentCode> new_deps =
15359  InsertWeakCode(isolate, old_deps, group, code);
15360  // Update the list head if necessary.
15361  if (!new_deps.is_identical_to(old_deps))
15362  DependentCode::SetDependentCode(object, new_deps);
15363 }
15364 
15365 Handle<DependentCode> DependentCode::InsertWeakCode(
15366  Isolate* isolate, Handle<DependentCode> entries, DependencyGroup group,
15367  const MaybeObjectHandle& code) {
15368  if (entries->length() == 0 || entries->group() > group) {
15369  // There is no such group.
15370  return DependentCode::New(isolate, group, code, entries);
15371  }
15372  if (entries->group() < group) {
15373  // The group comes later in the list.
15374  Handle<DependentCode> old_next(entries->next_link(), isolate);
15375  Handle<DependentCode> new_next =
15376  InsertWeakCode(isolate, old_next, group, code);
15377  if (!old_next.is_identical_to(new_next)) {
15378  entries->set_next_link(*new_next);
15379  }
15380  return entries;
15381  }
15382  DCHECK_EQ(group, entries->group());
15383  int count = entries->count();
15384  // Check for existing entry to avoid duplicates.
15385  for (int i = 0; i < count; i++) {
15386  if (entries->object_at(i) == *code) return entries;
15387  }
15388  if (entries->length() < kCodesStartIndex + count + 1) {
15389  entries = EnsureSpace(isolate, entries);
15390  // Count could have changed, reload it.
15391  count = entries->count();
15392  }
15393  entries->set_object_at(count, *code);
15394  entries->set_count(count + 1);
15395  return entries;
15396 }
15397 
15398 Handle<DependentCode> DependentCode::New(Isolate* isolate,
15399  DependencyGroup group,
15400  const MaybeObjectHandle& object,
15401  Handle<DependentCode> next) {
15402  Handle<DependentCode> result = Handle<DependentCode>::cast(
15403  isolate->factory()->NewWeakFixedArray(kCodesStartIndex + 1, TENURED));
15404  result->set_next_link(*next);
15405  result->set_flags(GroupField::encode(group) | CountField::encode(1));
15406  result->set_object_at(0, *object);
15407  return result;
15408 }
15409 
15410 Handle<DependentCode> DependentCode::EnsureSpace(
15411  Isolate* isolate, Handle<DependentCode> entries) {
15412  if (entries->Compact()) return entries;
15413  int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
15414  int grow_by = capacity - entries->length();
15415  return Handle<DependentCode>::cast(
15416  isolate->factory()->CopyWeakFixedArrayAndGrow(entries, grow_by, TENURED));
15417 }
15418 
15419 
15420 bool DependentCode::Compact() {
15421  int old_count = count();
15422  int new_count = 0;
15423  for (int i = 0; i < old_count; i++) {
15424  MaybeObject obj = object_at(i);
15425  if (!obj->IsCleared()) {
15426  if (i != new_count) {
15427  copy(i, new_count);
15428  }
15429  new_count++;
15430  }
15431  }
15432  set_count(new_count);
15433  for (int i = new_count; i < old_count; i++) {
15434  clear_at(i);
15435  }
15436  return new_count < old_count;
15437 }
15438 
15439 bool DependentCode::MarkCodeForDeoptimization(
15440  Isolate* isolate,
15441  DependentCode::DependencyGroup group) {
15442  if (this->length() == 0 || this->group() > group) {
15443  // There is no such group.
15444  return false;
15445  }
15446  if (this->group() < group) {
15447  // The group comes later in the list.
15448  return next_link()->MarkCodeForDeoptimization(isolate, group);
15449  }
15450  DCHECK_EQ(group, this->group());
15451  DisallowHeapAllocation no_allocation_scope;
15452  // Mark all the code that needs to be deoptimized.
15453  bool marked = false;
15454  int count = this->count();
15455  for (int i = 0; i < count; i++) {
15456  MaybeObject obj = object_at(i);
15457  if (obj->IsCleared()) continue;
15458  Code code = Code::cast(obj->GetHeapObjectAssumeWeak());
15459  if (!code->marked_for_deoptimization()) {
15460  code->SetMarkedForDeoptimization(DependencyGroupName(group));
15461  marked = true;
15462  }
15463  }
15464  for (int i = 0; i < count; i++) {
15465  clear_at(i);
15466  }
15467  set_count(0);
15468  return marked;
15469 }
15470 
15471 
15472 void DependentCode::DeoptimizeDependentCodeGroup(
15473  Isolate* isolate,
15474  DependentCode::DependencyGroup group) {
15475  DisallowHeapAllocation no_allocation_scope;
15476  bool marked = MarkCodeForDeoptimization(isolate, group);
15477  if (marked) {
15478  DCHECK(AllowCodeDependencyChange::IsAllowed());
15479  Deoptimizer::DeoptimizeMarkedCode(isolate);
15480  }
15481 }
15482 
15483 void Code::SetMarkedForDeoptimization(const char* reason) {
15484  set_marked_for_deoptimization(true);
15485  if (FLAG_trace_deopt &&
15486  (deoptimization_data() != GetReadOnlyRoots().empty_fixed_array())) {
15487  DeoptimizationData deopt_data =
15488  DeoptimizationData::cast(deoptimization_data());
15489  CodeTracer::Scope scope(GetHeap()->isolate()->GetCodeTracer());
15490  PrintF(scope.file(),
15491  "[marking dependent code " V8PRIxPTR_FMT
15492  " (opt #%d) for deoptimization, reason: %s]\n",
15493  ptr(), deopt_data->OptimizationId()->value(), reason);
15494  }
15495 }
15496 
15497 
15498 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
15499  switch (group) {
15500  case kTransitionGroup:
15501  return "transition";
15502  case kPrototypeCheckGroup:
15503  return "prototype-check";
15504  case kPropertyCellChangedGroup:
15505  return "property-cell-changed";
15506  case kFieldOwnerGroup:
15507  return "field-owner";
15508  case kInitialMapChangedGroup:
15509  return "initial-map-changed";
15510  case kAllocationSiteTenuringChangedGroup:
15511  return "allocation-site-tenuring-changed";
15512  case kAllocationSiteTransitionChangedGroup:
15513  return "allocation-site-transition-changed";
15514  }
15515  UNREACHABLE();
15516 }
15517 
15518 Handle<Map> Map::TransitionToPrototype(Isolate* isolate, Handle<Map> map,
15519  Handle<Object> prototype) {
15520  Handle<Map> new_map =
15521  TransitionsAccessor(isolate, map).GetPrototypeTransition(prototype);
15522  if (new_map.is_null()) {
15523  new_map = Copy(isolate, map, "TransitionToPrototype");
15524  TransitionsAccessor(isolate, map)
15525  .PutPrototypeTransition(prototype, new_map);
15526  Map::SetPrototype(isolate, new_map, prototype);
15527  }
15528  return new_map;
15529 }
15530 
15531 
15532 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
15533  Handle<Object> value, bool from_javascript,
15534  ShouldThrow should_throw) {
15535  if (object->IsJSProxy()) {
15536  return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
15537  from_javascript, should_throw);
15538  }
15539  return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
15540  from_javascript, should_throw);
15541 }
15542 
15543 
15544 // ES6: 9.5.2 [[SetPrototypeOf]] (V)
15545 // static
15546 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
15547  bool from_javascript,
15548  ShouldThrow should_throw) {
15549  Isolate* isolate = proxy->GetIsolate();
15550  STACK_CHECK(isolate, Nothing<bool>());
15551  Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
15552  // 1. Assert: Either Type(V) is Object or Type(V) is Null.
15553  DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
15554  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
15555  Handle<Object> handler(proxy->handler(), isolate);
15556  // 3. If handler is null, throw a TypeError exception.
15557  // 4. Assert: Type(handler) is Object.
15558  if (proxy->IsRevoked()) {
15559  isolate->Throw(*isolate->factory()->NewTypeError(
15560  MessageTemplate::kProxyRevoked, trap_name));
15561  return Nothing<bool>();
15562  }
15563  // 5. Let target be the value of the [[ProxyTarget]] internal slot.
15564  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
15565  // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
15566  Handle<Object> trap;
15567  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15568  isolate, trap,
15569  Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
15570  Nothing<bool>());
15571  // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
15572  if (trap->IsUndefined(isolate)) {
15573  return JSReceiver::SetPrototype(target, value, from_javascript,
15574  should_throw);
15575  }
15576  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)).
15577  Handle<Object> argv[] = {target, value};
15578  Handle<Object> trap_result;
15579  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15580  isolate, trap_result,
15581  Execution::Call(isolate, trap, handler, arraysize(argv), argv),
15582  Nothing<bool>());
15583  bool bool_trap_result = trap_result->BooleanValue(isolate);
15584  // 9. If booleanTrapResult is false, return false.
15585  if (!bool_trap_result) {
15586  RETURN_FAILURE(
15587  isolate, should_throw,
15588  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15589  }
15590  // 10. Let extensibleTarget be ? IsExtensible(target).
15591  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
15592  if (is_extensible.IsNothing()) return Nothing<bool>();
15593  // 11. If extensibleTarget is true, return true.
15594  if (is_extensible.FromJust()) {
15595  if (bool_trap_result) return Just(true);
15596  RETURN_FAILURE(
15597  isolate, should_throw,
15598  NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15599  }
15600  // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
15601  Handle<Object> target_proto;
15602  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
15603  JSReceiver::GetPrototype(isolate, target),
15604  Nothing<bool>());
15605  // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
15606  if (bool_trap_result && !value->SameValue(*target_proto)) {
15607  isolate->Throw(*isolate->factory()->NewTypeError(
15608  MessageTemplate::kProxySetPrototypeOfNonExtensible));
15609  return Nothing<bool>();
15610  }
15611  // 14. Return true.
15612  return Just(true);
15613 }
15614 
15615 
15616 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
15617  Handle<Object> value, bool from_javascript,
15618  ShouldThrow should_throw) {
15619  Isolate* isolate = object->GetIsolate();
15620 
15621 #ifdef DEBUG
15622  int size = object->Size();
15623 #endif
15624 
15625  if (from_javascript) {
15626  if (object->IsAccessCheckNeeded() &&
15627  !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
15628  isolate->ReportFailedAccessCheck(object);
15629  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
15630  RETURN_FAILURE(isolate, should_throw,
15631  NewTypeError(MessageTemplate::kNoAccess));
15632  }
15633  } else {
15634  DCHECK(!object->IsAccessCheckNeeded());
15635  }
15636 
15637  // Silently ignore the change if value is not a JSObject or null.
15638  // SpiderMonkey behaves this way.
15639  if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
15640 
15641  bool all_extensible = object->map()->is_extensible();
15642  Handle<JSObject> real_receiver = object;
15643  if (from_javascript) {
15644  // Find the first object in the chain whose prototype object is not
15645  // hidden.
15646  PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
15647  PrototypeIterator::END_AT_NON_HIDDEN);
15648  while (!iter.IsAtEnd()) {
15649  // Casting to JSObject is fine because hidden prototypes are never
15650  // JSProxies.
15651  real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
15652  iter.Advance();
15653  all_extensible = all_extensible && real_receiver->map()->is_extensible();
15654  }
15655  }
15656  Handle<Map> map(real_receiver->map(), isolate);
15657 
15658  // Nothing to do if prototype is already set.
15659  if (map->prototype() == *value) return Just(true);
15660 
15661  bool immutable_proto = map->is_immutable_proto();
15662  if (immutable_proto) {
15663  RETURN_FAILURE(
15664  isolate, should_throw,
15665  NewTypeError(MessageTemplate::kImmutablePrototypeSet, object));
15666  }
15667 
15668  // From 8.6.2 Object Internal Methods
15669  // ...
15670  // In addition, if [[Extensible]] is false the value of the [[Class]] and
15671  // [[Prototype]] internal properties of the object may not be modified.
15672  // ...
15673  // Implementation specific extensions that modify [[Class]], [[Prototype]]
15674  // or [[Extensible]] must not violate the invariants defined in the preceding
15675  // paragraph.
15676  if (!all_extensible) {
15677  RETURN_FAILURE(isolate, should_throw,
15678  NewTypeError(MessageTemplate::kNonExtensibleProto, object));
15679  }
15680 
15681  // Before we can set the prototype we need to be sure prototype cycles are
15682  // prevented. It is sufficient to validate that the receiver is not in the
15683  // new prototype chain.
15684  if (value->IsJSReceiver()) {
15685  for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
15686  kStartAtReceiver);
15687  !iter.IsAtEnd(); iter.Advance()) {
15688  if (iter.GetCurrent<JSReceiver>() == *object) {
15689  // Cycle detected.
15690  RETURN_FAILURE(isolate, should_throw,
15691  NewTypeError(MessageTemplate::kCyclicProto));
15692  }
15693  }
15694  }
15695 
15696  // Set the new prototype of the object.
15697 
15698  isolate->UpdateNoElementsProtectorOnSetPrototype(real_receiver);
15699 
15700  Handle<Map> new_map = Map::TransitionToPrototype(isolate, map, value);
15701  DCHECK(new_map->prototype() == *value);
15702  JSObject::MigrateToMap(real_receiver, new_map);
15703 
15704  DCHECK(size == object->Size());
15705  return Just(true);
15706 }
15707 
15708 // static
15709 void JSObject::SetImmutableProto(Handle<JSObject> object) {
15710  DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS
15711  Handle<Map> map(object->map(), object->GetIsolate());
15712 
15713  // Nothing to do if prototype is already set.
15714  if (map->is_immutable_proto()) return;
15715 
15716  Handle<Map> new_map =
15717  Map::TransitionToImmutableProto(object->GetIsolate(), map);
15718  object->synchronized_set_map(*new_map);
15719 }
15720 
15721 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
15722  Arguments* args,
15723  uint32_t first_arg,
15724  uint32_t arg_count,
15725  EnsureElementsMode mode) {
15726  // Elements in |Arguments| are ordered backwards (because they're on the
15727  // stack), but the method that's called here iterates over them in forward
15728  // direction.
15729  return EnsureCanContainElements(
15730  object, args->slot_at(first_arg + arg_count - 1), arg_count, mode);
15731 }
15732 
15733 
15734 ElementsAccessor* JSObject::GetElementsAccessor() {
15735  return ElementsAccessor::ForKind(GetElementsKind());
15736 }
15737 
15738 void JSObject::ValidateElements(JSObject* object) {
15739 #ifdef ENABLE_SLOW_DCHECKS
15740  if (FLAG_enable_slow_asserts) {
15741  object->GetElementsAccessor()->Validate(object);
15742  }
15743 #endif
15744 }
15745 
15746 
15747 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
15748  uint32_t index,
15749  uint32_t* new_capacity) {
15750  STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
15751  JSObject::kMaxUncheckedFastElementsLength);
15752  if (index < capacity) {
15753  *new_capacity = capacity;
15754  return false;
15755  }
15756  if (index - capacity >= JSObject::kMaxGap) return true;
15757  *new_capacity = JSObject::NewElementsCapacity(index + 1);
15758  DCHECK_LT(index, *new_capacity);
15759  if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
15760  (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
15761  Heap::InNewSpace(object))) {
15762  return false;
15763  }
15764  // If the fast-case backing storage takes up much more memory than a
15765  // dictionary backing storage would, the object should have slow elements.
15766  int used_elements = object->GetFastElementsUsage();
15767  uint32_t size_threshold = NumberDictionary::kPreferFastElementsSizeFactor *
15768  NumberDictionary::ComputeCapacity(used_elements) *
15769  NumberDictionary::kEntrySize;
15770  return size_threshold <= *new_capacity;
15771 }
15772 
15773 
15774 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
15775  if (!HasFastElements()) return false;
15776  uint32_t capacity = static_cast<uint32_t>(elements()->length());
15777  uint32_t new_capacity;
15778  return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
15779 }
15780 
15781 
15782 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
15783  if (!object->map()->CanHaveFastTransitionableElementsKind()) {
15784  return HOLEY_ELEMENTS;
15785  }
15786  if (object->HasSloppyArgumentsElements()) {
15787  return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
15788  }
15789  if (object->HasStringWrapperElements()) {
15790  return FAST_STRING_WRAPPER_ELEMENTS;
15791  }
15792  DCHECK(object->HasDictionaryElements());
15793  NumberDictionary dictionary = object->element_dictionary();
15794  ElementsKind kind = HOLEY_SMI_ELEMENTS;
15795  for (int i = 0; i < dictionary->Capacity(); i++) {
15796  Object* key = dictionary->KeyAt(i);
15797  if (key->IsNumber()) {
15798  Object* value = dictionary->ValueAt(i);
15799  if (!value->IsNumber()) return HOLEY_ELEMENTS;
15800  if (!value->IsSmi()) {
15801  if (!FLAG_unbox_double_arrays) return HOLEY_ELEMENTS;
15802  kind = HOLEY_DOUBLE_ELEMENTS;
15803  }
15804  }
15805  }
15806  return kind;
15807 }
15808 
15809 static bool ShouldConvertToFastElements(JSObject* object,
15810  NumberDictionary dictionary,
15811  uint32_t index,
15812  uint32_t* new_capacity) {
15813  // If properties with non-standard attributes or accessors were added, we
15814  // cannot go back to fast elements.
15815  if (dictionary->requires_slow_elements()) return false;
15816 
15817  // Adding a property with this index will require slow elements.
15818  if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
15819 
15820  if (object->IsJSArray()) {
15821  Object* length = JSArray::cast(object)->length();
15822  if (!length->IsSmi()) return false;
15823  *new_capacity = static_cast<uint32_t>(Smi::ToInt(length));
15824  } else if (object->IsJSSloppyArgumentsObject()) {
15825  return false;
15826  } else {
15827  *new_capacity = dictionary->max_number_key() + 1;
15828  }
15829  *new_capacity = Max(index + 1, *new_capacity);
15830 
15831  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
15832  NumberDictionary::kEntrySize;
15833 
15834  // Turn fast if the dictionary only saves 50% space.
15835  return 2 * dictionary_size >= *new_capacity;
15836 }
15837 
15838 // static
15839 void JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
15840  Handle<Object> value,
15841  PropertyAttributes attributes) {
15842  DCHECK(object->map()->is_extensible());
15843 
15844  Isolate* isolate = object->GetIsolate();
15845 
15846  uint32_t old_length = 0;
15847  uint32_t new_capacity = 0;
15848 
15849  if (object->IsJSArray()) {
15850  CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
15851  }
15852 
15853  ElementsKind kind = object->GetElementsKind();
15854  FixedArrayBase elements = object->elements();
15855  ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15856  if (IsSloppyArgumentsElementsKind(kind)) {
15857  elements = SloppyArgumentsElements::cast(elements)->arguments();
15858  dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15859  } else if (IsStringWrapperElementsKind(kind)) {
15860  dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
15861  }
15862 
15863  if (attributes != NONE) {
15864  kind = dictionary_kind;
15865  } else if (elements->IsNumberDictionary()) {
15866  kind = ShouldConvertToFastElements(
15867  *object, NumberDictionary::cast(elements), index, &new_capacity)
15868  ? BestFittingFastElementsKind(*object)
15869  : dictionary_kind;
15870  } else if (ShouldConvertToSlowElements(
15871  *object, static_cast<uint32_t>(elements->length()), index,
15872  &new_capacity)) {
15873  kind = dictionary_kind;
15874  }
15875 
15876  ElementsKind to = value->OptimalElementsKind();
15877  if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
15878  to = GetHoleyElementsKind(to);
15879  kind = GetHoleyElementsKind(kind);
15880  }
15881  to = GetMoreGeneralElementsKind(kind, to);
15882  ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
15883  accessor->Add(object, index, value, attributes, new_capacity);
15884 
15885  if (object->IsJSArray() && index >= old_length) {
15886  Handle<Object> new_length =
15887  isolate->factory()->NewNumberFromUint(index + 1);
15888  JSArray::cast(*object)->set_length(*new_length);
15889  }
15890 }
15891 
15892 
15893 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
15894  if (!HasFastElements()) return false;
15895  uint32_t capacity = static_cast<uint32_t>(elements()->length());
15896  uint32_t new_capacity;
15897  return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
15898  ShouldConvertToSlowElements(this, capacity, new_length - 1,
15899  &new_capacity);
15900 }
15901 
15902 
15903 const double AllocationSite::kPretenureRatio = 0.85;
15904 
15905 
15906 void AllocationSite::ResetPretenureDecision() {
15907  set_pretenure_decision(kUndecided);
15908  set_memento_found_count(0);
15909  set_memento_create_count(0);
15910 }
15911 
15912 PretenureFlag AllocationSite::GetPretenureMode() const {
15913  PretenureDecision mode = pretenure_decision();
15914  // Zombie objects "decide" to be untenured.
15915  return mode == kTenure ? TENURED : NOT_TENURED;
15916 }
15917 
15918 bool AllocationSite::IsNested() {
15919  DCHECK(FLAG_trace_track_allocation_sites);
15920  Object* current = boilerplate()->GetHeap()->allocation_sites_list();
15921  while (current->IsAllocationSite()) {
15922  AllocationSite* current_site = AllocationSite::cast(current);
15923  if (current_site->nested_site() == this) {
15924  return true;
15925  }
15926  current = current_site->weak_next();
15927  }
15928  return false;
15929 }
15930 
15931 template <AllocationSiteUpdateMode update_or_check>
15932 bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
15933  ElementsKind to_kind) {
15934  Isolate* isolate = site->GetIsolate();
15935  bool result = false;
15936 
15937  if (site->PointsToLiteral() && site->boilerplate()->IsJSArray()) {
15938  Handle<JSArray> boilerplate(JSArray::cast(site->boilerplate()), isolate);
15939  ElementsKind kind = boilerplate->GetElementsKind();
15940  // if kind is holey ensure that to_kind is as well.
15941  if (IsHoleyElementsKind(kind)) {
15942  to_kind = GetHoleyElementsKind(to_kind);
15943  }
15944  if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15945  // If the array is huge, it's not likely to be defined in a local
15946  // function, so we shouldn't make new instances of it very often.
15947  uint32_t length = 0;
15948  CHECK(boilerplate->length()->ToArrayLength(&length));
15949  if (length <= kMaximumArrayBytesToPretransition) {
15950  if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
15951  return true;
15952  }
15953  if (FLAG_trace_track_allocation_sites) {
15954  bool is_nested = site->IsNested();
15955  PrintF("AllocationSite: JSArray %p boilerplate %supdated %s->%s\n",
15956  reinterpret_cast<void*>(*site), is_nested ? "(nested)" : " ",
15957  ElementsKindToString(kind), ElementsKindToString(to_kind));
15958  }
15959  JSObject::TransitionElementsKind(boilerplate, to_kind);
15960  site->dependent_code()->DeoptimizeDependentCodeGroup(
15961  isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15962  result = true;
15963  }
15964  }
15965  } else {
15966  // The AllocationSite is for a constructed Array.
15967  ElementsKind kind = site->GetElementsKind();
15968  // if kind is holey ensure that to_kind is as well.
15969  if (IsHoleyElementsKind(kind)) {
15970  to_kind = GetHoleyElementsKind(to_kind);
15971  }
15972  if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15973  if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) return true;
15974  if (FLAG_trace_track_allocation_sites) {
15975  PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
15976  reinterpret_cast<void*>(*site),
15977  ElementsKindToString(kind),
15978  ElementsKindToString(to_kind));
15979  }
15980  site->SetElementsKind(to_kind);
15981  site->dependent_code()->DeoptimizeDependentCodeGroup(
15982  isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15983  result = true;
15984  }
15985  }
15986  return result;
15987 }
15988 
15989 bool AllocationSite::ShouldTrack(ElementsKind from, ElementsKind to) {
15990  return IsSmiElementsKind(from) &&
15991  IsMoreGeneralElementsKindTransition(from, to);
15992 }
15993 
15994 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
15995  switch (decision) {
15996  case kUndecided: return "undecided";
15997  case kDontTenure: return "don't tenure";
15998  case kMaybeTenure: return "maybe tenure";
15999  case kTenure: return "tenure";
16000  case kZombie: return "zombie";
16001  default: UNREACHABLE();
16002  }
16003  return nullptr;
16004 }
16005 
16006 template <AllocationSiteUpdateMode update_or_check>
16007 bool JSObject::UpdateAllocationSite(Handle<JSObject> object,
16008  ElementsKind to_kind) {
16009  if (!object->IsJSArray()) return false;
16010 
16011  if (!Heap::InNewSpace(*object)) return false;
16012 
16013  Handle<AllocationSite> site;
16014  {
16015  DisallowHeapAllocation no_allocation;
16016 
16017  Heap* heap = object->GetHeap();
16018  AllocationMemento* memento =
16019  heap->FindAllocationMemento<Heap::kForRuntime>(object->map(), *object);
16020  if (memento == nullptr) return false;
16021 
16022  // Walk through to the Allocation Site
16023  site = handle(memento->GetAllocationSite(), heap->isolate());
16024  }
16025  return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
16026  to_kind);
16027 }
16028 
16029 template bool
16030 JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
16031  Handle<JSObject> object, ElementsKind to_kind);
16032 
16033 template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
16034  Handle<JSObject> object, ElementsKind to_kind);
16035 
16036 void JSObject::TransitionElementsKind(Handle<JSObject> object,
16037  ElementsKind to_kind) {
16038  ElementsKind from_kind = object->GetElementsKind();
16039 
16040  if (IsHoleyElementsKind(from_kind)) {
16041  to_kind = GetHoleyElementsKind(to_kind);
16042  }
16043 
16044  if (from_kind == to_kind) return;
16045 
16046  // This method should never be called for any other case.
16047  DCHECK(IsFastElementsKind(from_kind));
16048  DCHECK(IsFastElementsKind(to_kind));
16049  DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
16050 
16051  UpdateAllocationSite(object, to_kind);
16052  if (object->elements() == object->GetReadOnlyRoots().empty_fixed_array() ||
16053  IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
16054  // No change is needed to the elements() buffer, the transition
16055  // only requires a map change.
16056  Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
16057  MigrateToMap(object, new_map);
16058  if (FLAG_trace_elements_transitions) {
16059  Handle<FixedArrayBase> elms(object->elements(), object->GetIsolate());
16060  PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
16061  }
16062  } else {
16063  DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
16064  (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
16065  uint32_t c = static_cast<uint32_t>(object->elements()->length());
16066  ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
16067  }
16068 }
16069 
16070 
16071 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
16072  Map map = array->map();
16073  // Fast path: "length" is the first fast property of arrays. Since it's not
16074  // configurable, it's guaranteed to be the first in the descriptor array.
16075  if (!map->is_dictionary_map()) {
16076  DCHECK(map->instance_descriptors()->GetKey(0) ==
16077  array->GetReadOnlyRoots().length_string());
16078  return map->instance_descriptors()->GetDetails(0).IsReadOnly();
16079  }
16080 
16081  Isolate* isolate = array->GetIsolate();
16082  LookupIterator it(array, isolate->factory()->length_string(), array,
16083  LookupIterator::OWN_SKIP_INTERCEPTOR);
16084  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
16085  return it.IsReadOnly();
16086 }
16087 
16088 
16089 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
16090  uint32_t index) {
16091  uint32_t length = 0;
16092  CHECK(array->length()->ToArrayLength(&length));
16093  if (length <= index) return HasReadOnlyLength(array);
16094  return false;
16095 }
16096 
16097 template <typename BackingStore>
16098 static int HoleyElementsUsage(JSObject* object, BackingStore store) {
16099  Isolate* isolate = object->GetIsolate();
16100  int limit = object->IsJSArray() ? Smi::ToInt(JSArray::cast(object)->length())
16101  : store->length();
16102  int used = 0;
16103  for (int i = 0; i < limit; ++i) {
16104  if (!store->is_the_hole(isolate, i)) ++used;
16105  }
16106  return used;
16107 }
16108 
16109 int JSObject::GetFastElementsUsage() {
16110  FixedArrayBase store = elements();
16111  switch (GetElementsKind()) {
16112  case PACKED_SMI_ELEMENTS:
16113  case PACKED_DOUBLE_ELEMENTS:
16114  case PACKED_ELEMENTS:
16115  return IsJSArray() ? Smi::ToInt(JSArray::cast(this)->length())
16116  : store->length();
16117  case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16118  store = SloppyArgumentsElements::cast(store)->arguments();
16119  V8_FALLTHROUGH;
16120  case HOLEY_SMI_ELEMENTS:
16121  case HOLEY_ELEMENTS:
16122  case FAST_STRING_WRAPPER_ELEMENTS:
16123  return HoleyElementsUsage(this, FixedArray::cast(store));
16124  case HOLEY_DOUBLE_ELEMENTS:
16125  if (elements()->length() == 0) return 0;
16126  return HoleyElementsUsage(this, FixedDoubleArray::cast(store));
16127 
16128  case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
16129  case SLOW_STRING_WRAPPER_ELEMENTS:
16130  case DICTIONARY_ELEMENTS:
16131  case NO_ELEMENTS:
16132 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
16133 
16134  TYPED_ARRAYS(TYPED_ARRAY_CASE)
16135 #undef TYPED_ARRAY_CASE
16136  UNREACHABLE();
16137  }
16138  return 0;
16139 }
16140 
16141 
16142 // Certain compilers request function template instantiation when they
16143 // see the definition of the other template functions in the
16144 // class. This requires us to have the template functions put
16145 // together, so even though this function belongs in objects-debug.cc,
16146 // we keep it here instead to satisfy certain compilers.
16147 #ifdef OBJECT_PRINT
16148 template <typename Derived, typename Shape>
16149 void Dictionary<Derived, Shape>::Print(std::ostream& os) {
16150  DisallowHeapAllocation no_gc;
16151  ReadOnlyRoots roots = this->GetReadOnlyRoots();
16152  Derived dictionary = Derived::cast(*this);
16153  int capacity = dictionary->Capacity();
16154  for (int i = 0; i < capacity; i++) {
16155  Object* k = dictionary->KeyAt(i);
16156  if (!dictionary->ToKey(roots, i, &k)) continue;
16157  os << "\n ";
16158  if (k->IsString()) {
16159  String::cast(k)->StringPrint(os);
16160  } else {
16161  os << Brief(k);
16162  }
16163  os << ": " << Brief(dictionary->ValueAt(i)) << " ";
16164  dictionary->DetailsAt(i).PrintAsSlowTo(os);
16165  }
16166 }
16167 template <typename Derived, typename Shape>
16168 void Dictionary<Derived, Shape>::Print() {
16169  StdoutStream os;
16170  Print(os);
16171  os << std::endl;
16172 }
16173 #endif
16174 
16175 
16176 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
16177  bool* done) {
16178  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
16179  return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
16180 }
16181 
16182 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
16183  Handle<Name> name) {
16184  LookupIterator it = LookupIterator::PropertyOrElement(
16185  object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16186  return HasProperty(&it);
16187 }
16188 
16189 
16190 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
16191  uint32_t index) {
16192  Isolate* isolate = object->GetIsolate();
16193  LookupIterator it(isolate, object, index, object,
16194  LookupIterator::OWN_SKIP_INTERCEPTOR);
16195  return HasProperty(&it);
16196 }
16197 
16198 
16199 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
16200  Handle<Name> name) {
16201  LookupIterator it = LookupIterator::PropertyOrElement(
16202  object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16203  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
16204  return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
16205  : Nothing<bool>();
16206 }
16207 
16208 int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
16209  return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
16210  ElementsKindToShiftSize(kind));
16211 }
16212 
16213 bool FixedArrayBase::IsCowArray() const {
16214  return map() == GetReadOnlyRoots().fixed_cow_array_map();
16215 }
16216 
16217 bool JSObject::IsApiWrapper() {
16218  // These object types can carry information relevant for embedders. The
16219  // *_API_* types are generated through templates which can have embedder
16220  // fields. The other types have their embedder fields added at compile time.
16221  auto instance_type = map()->instance_type();
16222  return instance_type == JS_API_OBJECT_TYPE ||
16223  instance_type == JS_ARRAY_BUFFER_TYPE ||
16224  instance_type == JS_DATA_VIEW_TYPE ||
16225  instance_type == JS_SPECIAL_API_OBJECT_TYPE ||
16226  instance_type == JS_TYPED_ARRAY_TYPE;
16227 }
16228 
16229 bool JSObject::IsDroppableApiWrapper() {
16230  auto instance_type = map()->instance_type();
16231  return instance_type == JS_API_OBJECT_TYPE ||
16232  instance_type == JS_SPECIAL_API_OBJECT_TYPE;
16233 }
16234 
16235 const char* Symbol::PrivateSymbolToName() const {
16236  ReadOnlyRoots roots = GetReadOnlyRoots();
16237 #define SYMBOL_CHECK_AND_PRINT(_, name) \
16238  if (*this == roots.name()) return #name;
16239  PRIVATE_SYMBOL_LIST_GENERATOR(SYMBOL_CHECK_AND_PRINT, /* not used */)
16240 #undef SYMBOL_CHECK_AND_PRINT
16241  return "UNKNOWN";
16242 }
16243 
16244 
16245 void Symbol::SymbolShortPrint(std::ostream& os) {
16246  os << "<Symbol:";
16247  if (!name()->IsUndefined()) {
16248  os << " ";
16249  HeapStringAllocator allocator;
16250  StringStream accumulator(&allocator);
16251  String::cast(name())->StringShortPrint(&accumulator, false);
16252  os << accumulator.ToCString().get();
16253  } else {
16254  os << " (" << PrivateSymbolToName() << ")";
16255  }
16256  os << ">";
16257 }
16258 
16259 
16260 // StringSharedKeys are used as keys in the eval cache.
16262  public:
16263  // This tuple unambiguously identifies calls to eval() or
16264  // CreateDynamicFunction() (such as through the Function() constructor).
16265  // * source is the string passed into eval(). For dynamic functions, this is
16266  // the effective source for the function, some of which is implicitly
16267  // generated.
16268  // * shared is the shared function info for the function containing the call
16269  // to eval(). for dynamic functions, shared is the native context closure.
16270  // * When positive, position is the position in the source where eval is
16271  // called. When negative, position is the negation of the position in the
16272  // dynamic function's effective source where the ')' ends the parameters.
16274  LanguageMode language_mode, int position)
16275  : HashTableKey(CompilationCacheShape::StringSharedHash(
16276  *source, *shared, language_mode, position)),
16277  source_(source),
16278  shared_(shared),
16279  language_mode_(language_mode),
16280  position_(position) {}
16281 
16282  bool IsMatch(Object* other) override {
16283  DisallowHeapAllocation no_allocation;
16284  if (!other->IsFixedArray()) {
16285  DCHECK(other->IsNumber());
16286  uint32_t other_hash = static_cast<uint32_t>(other->Number());
16287  return Hash() == other_hash;
16288  }
16289  FixedArray other_array = FixedArray::cast(other);
16290  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
16291  if (shared != *shared_) return false;
16292  int language_unchecked = Smi::ToInt(other_array->get(2));
16293  DCHECK(is_valid_language_mode(language_unchecked));
16294  LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
16295  if (language_mode != language_mode_) return false;
16296  int position = Smi::ToInt(other_array->get(3));
16297  if (position != position_) return false;
16298  String source = String::cast(other_array->get(1));
16299  return source->Equals(*source_);
16300  }
16301 
16302  Handle<Object> AsHandle(Isolate* isolate) {
16303  Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
16304  array->set(0, *shared_);
16305  array->set(1, *source_);
16306  array->set(2, Smi::FromEnum(language_mode_));
16307  array->set(3, Smi::FromInt(position_));
16308  array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
16309  return array;
16310  }
16311 
16312  private:
16313  Handle<String> source_;
16315  LanguageMode language_mode_;
16316  int position_;
16317 };
16318 
16319 v8::Promise::PromiseState JSPromise::status() const {
16320  int value = flags() & kStatusMask;
16321  DCHECK(value == 0 || value == 1 || value == 2);
16322  return static_cast<v8::Promise::PromiseState>(value);
16323 }
16324 
16325 void JSPromise::set_status(Promise::PromiseState status) {
16326  int value = flags() & ~kStatusMask;
16327  set_flags(value | status);
16328 }
16329 
16330 // static
16331 const char* JSPromise::Status(v8::Promise::PromiseState status) {
16332  switch (status) {
16333  case v8::Promise::kFulfilled:
16334  return "resolved";
16335  case v8::Promise::kPending:
16336  return "pending";
16337  case v8::Promise::kRejected:
16338  return "rejected";
16339  }
16340  UNREACHABLE();
16341 }
16342 
16343 int JSPromise::async_task_id() const {
16344  return AsyncTaskIdField::decode(flags());
16345 }
16346 
16347 void JSPromise::set_async_task_id(int id) {
16348  set_flags(AsyncTaskIdField::update(flags(), id));
16349 }
16350 
16351 // static
16352 Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
16353  Handle<Object> value) {
16354  Isolate* const isolate = promise->GetIsolate();
16355 
16356  // 1. Assert: The value of promise.[[PromiseState]] is "pending".
16357  DCHECK_EQ(Promise::kPending, promise->status());
16358 
16359  // 2. Let reactions be promise.[[PromiseFulfillReactions]].
16360  Handle<Object> reactions(promise->reactions(), isolate);
16361 
16362  // 3. Set promise.[[PromiseResult]] to value.
16363  // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
16364  // 5. Set promise.[[PromiseRejectReactions]] to undefined.
16365  promise->set_reactions_or_result(*value);
16366 
16367  // 6. Set promise.[[PromiseState]] to "fulfilled".
16368  promise->set_status(Promise::kFulfilled);
16369 
16370  // 7. Return TriggerPromiseReactions(reactions, value).
16371  return TriggerPromiseReactions(isolate, reactions, value,
16372  PromiseReaction::kFulfill);
16373 }
16374 
16375 // static
16376 Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
16377  Handle<Object> reason, bool debug_event) {
16378  Isolate* const isolate = promise->GetIsolate();
16379 
16380  if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
16381  isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
16382  isolate->factory()->undefined_value());
16383 
16384  // 1. Assert: The value of promise.[[PromiseState]] is "pending".
16385  DCHECK_EQ(Promise::kPending, promise->status());
16386 
16387  // 2. Let reactions be promise.[[PromiseRejectReactions]].
16388  Handle<Object> reactions(promise->reactions(), isolate);
16389 
16390  // 3. Set promise.[[PromiseResult]] to reason.
16391  // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
16392  // 5. Set promise.[[PromiseRejectReactions]] to undefined.
16393  promise->set_reactions_or_result(*reason);
16394 
16395  // 6. Set promise.[[PromiseState]] to "rejected".
16396  promise->set_status(Promise::kRejected);
16397 
16398  // 7. If promise.[[PromiseIsHandled]] is false, perform
16399  // HostPromiseRejectionTracker(promise, "reject").
16400  if (!promise->has_handler()) {
16401  isolate->ReportPromiseReject(promise, reason, kPromiseRejectWithNoHandler);
16402  }
16403 
16404  // 8. Return TriggerPromiseReactions(reactions, reason).
16405  return TriggerPromiseReactions(isolate, reactions, reason,
16406  PromiseReaction::kReject);
16407 }
16408 
16409 // static
16410 MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
16411  Handle<Object> resolution) {
16412  Isolate* const isolate = promise->GetIsolate();
16413 
16414  isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
16415  isolate->factory()->undefined_value());
16416 
16417  // 6. If SameValue(resolution, promise) is true, then
16418  if (promise.is_identical_to(resolution)) {
16419  // a. Let selfResolutionError be a newly created TypeError object.
16420  Handle<Object> self_resolution_error = isolate->factory()->NewTypeError(
16421  MessageTemplate::kPromiseCyclic, resolution);
16422  // b. Return RejectPromise(promise, selfResolutionError).
16423  return Reject(promise, self_resolution_error);
16424  }
16425 
16426  // 7. If Type(resolution) is not Object, then
16427  if (!resolution->IsJSReceiver()) {
16428  // a. Return FulfillPromise(promise, resolution).
16429  return Fulfill(promise, resolution);
16430  }
16431 
16432  // 8. Let then be Get(resolution, "then").
16433  MaybeHandle<Object> then;
16434  if (isolate->IsPromiseThenLookupChainIntact(
16435  Handle<JSReceiver>::cast(resolution))) {
16436  // We can skip the "then" lookup on {resolution} if its [[Prototype]]
16437  // is the (initial) Promise.prototype and the Promise#then protector
16438  // is intact, as that guards the lookup path for the "then" property
16439  // on JSPromise instances which have the (initial) %PromisePrototype%.
16440  then = isolate->promise_then();
16441  } else {
16442  then =
16443  JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(resolution),
16444  isolate->factory()->then_string());
16445  }
16446 
16447  // 9. If then is an abrupt completion, then
16448  Handle<Object> then_action;
16449  if (!then.ToHandle(&then_action)) {
16450  // a. Return RejectPromise(promise, then.[[Value]]).
16451  Handle<Object> reason(isolate->pending_exception(), isolate);
16452  isolate->clear_pending_exception();
16453  return Reject(promise, reason, false);
16454  }
16455 
16456  // 10. Let thenAction be then.[[Value]].
16457  // 11. If IsCallable(thenAction) is false, then
16458  if (!then_action->IsCallable()) {
16459  // a. Return FulfillPromise(promise, resolution).
16460  return Fulfill(promise, resolution);
16461  }
16462 
16463  // 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
16464  // «promise, resolution, thenAction»).
16465  Handle<PromiseResolveThenableJobTask> task =
16466  isolate->factory()->NewPromiseResolveThenableJobTask(
16467  promise, Handle<JSReceiver>::cast(then_action),
16468  Handle<JSReceiver>::cast(resolution), isolate->native_context());
16469  if (isolate->debug()->is_active() && resolution->IsJSPromise()) {
16470  // Mark the dependency of the new {promise} on the {resolution}.
16471  Object::SetProperty(isolate, resolution,
16472  isolate->factory()->promise_handled_by_symbol(),
16473  promise, LanguageMode::kStrict)
16474  .Check();
16475  }
16476  isolate->EnqueueMicrotask(task);
16477 
16478  // 13. Return undefined.
16479  return isolate->factory()->undefined_value();
16480 }
16481 
16482 // static
16483 Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
16484  Handle<Object> reactions,
16485  Handle<Object> argument,
16486  PromiseReaction::Type type) {
16487  DCHECK(reactions->IsSmi() || reactions->IsPromiseReaction());
16488 
16489  // We need to reverse the {reactions} here, since we record them
16490  // on the JSPromise in the reverse order.
16491  {
16492  DisallowHeapAllocation no_gc;
16493  Object* current = *reactions;
16494  Object* reversed = Smi::kZero;
16495  while (!current->IsSmi()) {
16496  Object* next = PromiseReaction::cast(current)->next();
16497  PromiseReaction::cast(current)->set_next(reversed);
16498  reversed = current;
16499  current = next;
16500  }
16501  reactions = handle(reversed, isolate);
16502  }
16503 
16504  // Morph the {reactions} into PromiseReactionJobTasks
16505  // and push them onto the microtask queue.
16506  while (!reactions->IsSmi()) {
16507  Handle<HeapObject> task = Handle<HeapObject>::cast(reactions);
16508  Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(task);
16509  reactions = handle(reaction->next(), isolate);
16510 
16511  STATIC_ASSERT(PromiseReaction::kSize == PromiseReactionJobTask::kSize);
16512  if (type == PromiseReaction::kFulfill) {
16513  task->synchronized_set_map(
16514  ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map());
16515  Handle<PromiseFulfillReactionJobTask>::cast(task)->set_argument(
16516  *argument);
16517  Handle<PromiseFulfillReactionJobTask>::cast(task)->set_context(
16518  *isolate->native_context());
16519  STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset ==
16520  PromiseFulfillReactionJobTask::kHandlerOffset);
16521  STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
16522  PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset);
16523  } else {
16524  DisallowHeapAllocation no_gc;
16525  HeapObject* handler = reaction->reject_handler();
16526  task->synchronized_set_map(
16527  ReadOnlyRoots(isolate).promise_reject_reaction_job_task_map());
16528  Handle<PromiseRejectReactionJobTask>::cast(task)->set_argument(*argument);
16529  Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
16530  *isolate->native_context());
16531  Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(handler);
16532  STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
16533  PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset);
16534  }
16535 
16536  isolate->EnqueueMicrotask(Handle<PromiseReactionJobTask>::cast(task));
16537  }
16538 
16539  return isolate->factory()->undefined_value();
16540 }
16541 
16542 namespace {
16543 
16544 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
16545  JSRegExp::Flags value = JSRegExp::kNone;
16546  int length = flags->length();
16547  // A longer flags string cannot be valid.
16548  if (length > JSRegExp::FlagCount()) return JSRegExp::Flags(0);
16549  for (int i = 0; i < length; i++) {
16550  JSRegExp::Flag flag = JSRegExp::kNone;
16551  switch (flags->Get(i)) {
16552  case 'g':
16553  flag = JSRegExp::kGlobal;
16554  break;
16555  case 'i':
16556  flag = JSRegExp::kIgnoreCase;
16557  break;
16558  case 'm':
16559  flag = JSRegExp::kMultiline;
16560  break;
16561  case 's':
16562  flag = JSRegExp::kDotAll;
16563  break;
16564  case 'u':
16565  flag = JSRegExp::kUnicode;
16566  break;
16567  case 'y':
16568  flag = JSRegExp::kSticky;
16569  break;
16570  default:
16571  return JSRegExp::Flags(0);
16572  }
16573  // Duplicate flag.
16574  if (value & flag) return JSRegExp::Flags(0);
16575  value |= flag;
16576  }
16577  *success = true;
16578  return value;
16579 }
16580 
16581 } // namespace
16582 
16583 
16584 // static
16585 MaybeHandle<JSRegExp> JSRegExp::New(Isolate* isolate, Handle<String> pattern,
16586  Flags flags) {
16587  Handle<JSFunction> constructor = isolate->regexp_function();
16588  Handle<JSRegExp> regexp =
16589  Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
16590 
16591  return JSRegExp::Initialize(regexp, pattern, flags);
16592 }
16593 
16594 
16595 // static
16596 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
16597  Isolate* const isolate = regexp->GetIsolate();
16598  return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
16599 }
16600 
16601 
16602 template <typename Char>
16603 inline int CountRequiredEscapes(Handle<String> source) {
16604  DisallowHeapAllocation no_gc;
16605  int escapes = 0;
16606  Vector<const Char> src = source->GetCharVector<Char>();
16607  for (int i = 0; i < src.length(); i++) {
16608  if (src[i] == '\\') {
16609  // Escape. Skip next character;
16610  i++;
16611  } else if (src[i] == '/') {
16612  // Not escaped forward-slash needs escape.
16613  escapes++;
16614  }
16615  }
16616  return escapes;
16617 }
16618 
16619 
16620 template <typename Char, typename StringType>
16621 inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
16622  Handle<StringType> result) {
16623  DisallowHeapAllocation no_gc;
16624  Vector<const Char> src = source->GetCharVector<Char>();
16625  Vector<Char> dst(result->GetChars(), result->length());
16626  int s = 0;
16627  int d = 0;
16628  while (s < src.length()) {
16629  if (src[s] == '\\') {
16630  // Escape. Copy this and next character.
16631  dst[d++] = src[s++];
16632  if (s == src.length()) break;
16633  } else if (src[s] == '/') {
16634  // Not escaped forward-slash needs escape.
16635  dst[d++] = '\\';
16636  }
16637  dst[d++] = src[s++];
16638  }
16639  DCHECK_EQ(result->length(), d);
16640  return result;
16641 }
16642 
16643 
16644 MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
16645  Handle<String> source) {
16646  DCHECK(source->IsFlat());
16647  if (source->length() == 0) return isolate->factory()->query_colon_string();
16648  bool one_byte = source->IsOneByteRepresentationUnderneath();
16649  int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
16650  : CountRequiredEscapes<uc16>(source);
16651  if (escapes == 0) return source;
16652  int length = source->length() + escapes;
16653  if (one_byte) {
16654  Handle<SeqOneByteString> result;
16655  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16656  isolate->factory()->NewRawOneByteString(length),
16657  String);
16658  return WriteEscapedRegExpSource<uint8_t>(source, result);
16659  } else {
16660  Handle<SeqTwoByteString> result;
16661  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16662  isolate->factory()->NewRawTwoByteString(length),
16663  String);
16664  return WriteEscapedRegExpSource<uc16>(source, result);
16665  }
16666 }
16667 
16668 
16669 // static
16670 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16671  Handle<String> source,
16672  Handle<String> flags_string) {
16673  Isolate* isolate = regexp->GetIsolate();
16674  bool success = false;
16675  Flags flags = RegExpFlagsFromString(flags_string, &success);
16676  if (!success) {
16677  THROW_NEW_ERROR(
16678  isolate,
16679  NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
16680  JSRegExp);
16681  }
16682  return Initialize(regexp, source, flags);
16683 }
16684 
16685 
16686 // static
16687 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16688  Handle<String> source, Flags flags) {
16689  Isolate* isolate = regexp->GetIsolate();
16690  Factory* factory = isolate->factory();
16691  // If source is the empty string we set it to "(?:)" instead as
16692  // suggested by ECMA-262, 5th, section 15.10.4.1.
16693  if (source->length() == 0) source = factory->query_colon_string();
16694 
16695  source = String::Flatten(isolate, source);
16696 
16697  Handle<String> escaped_source;
16698  ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
16699  EscapeRegExpSource(isolate, source), JSRegExp);
16700 
16701  RETURN_ON_EXCEPTION(
16702  isolate, RegExpImpl::Compile(isolate, regexp, source, flags), JSRegExp);
16703 
16704  regexp->set_source(*escaped_source);
16705  regexp->set_flags(Smi::FromInt(flags));
16706 
16707  Map map = regexp->map();
16708  Object* constructor = map->GetConstructor();
16709  if (constructor->IsJSFunction() &&
16710  JSFunction::cast(constructor)->initial_map() == map) {
16711  // If we still have the original map, set in-object properties directly.
16712  regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
16713  SKIP_WRITE_BARRIER);
16714  } else {
16715  // Map has changed, so use generic, but slower, method.
16716  RETURN_ON_EXCEPTION(
16717  isolate,
16718  JSReceiver::SetProperty(isolate, regexp, factory->lastIndex_string(),
16719  Handle<Smi>(Smi::zero(), isolate),
16720  LanguageMode::kStrict),
16721  JSRegExp);
16722  }
16723 
16724  return regexp;
16725 }
16726 
16727 
16728 // RegExpKey carries the source and flags of a regular expression as key.
16729 class RegExpKey : public HashTableKey {
16730  public:
16732  : HashTableKey(
16733  CompilationCacheShape::RegExpHash(*string, Smi::FromInt(flags))),
16734  string_(string),
16735  flags_(Smi::FromInt(flags)) {}
16736 
16737  // Rather than storing the key in the hash table, a pointer to the
16738  // stored value is stored where the key should be. IsMatch then
16739  // compares the search key to the found object, rather than comparing
16740  // a key to a key.
16741  bool IsMatch(Object* obj) override {
16742  FixedArray val = FixedArray::cast(obj);
16743  return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
16744  && (flags_ == val->get(JSRegExp::kFlagsIndex));
16745  }
16746 
16747  Handle<String> string_;
16748  Smi flags_;
16749 };
16750 
16751 Handle<String> OneByteStringKey::AsHandle(Isolate* isolate) {
16752  return isolate->factory()->NewOneByteInternalizedString(string_, HashField());
16753 }
16754 
16755 Handle<String> TwoByteStringKey::AsHandle(Isolate* isolate) {
16756  return isolate->factory()->NewTwoByteInternalizedString(string_, HashField());
16757 }
16758 
16759 Handle<String> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
16760  return isolate->factory()->NewOneByteInternalizedSubString(
16761  string_, from_, length_, HashField());
16762 }
16763 
16764 
16765 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
16766  DisallowHeapAllocation no_gc;
16767  Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
16768  return String::cast(string)->IsOneByteEqualTo(chars);
16769 }
16770 
16771 
16772 // InternalizedStringKey carries a string/internalized-string object as key.
16774  public:
16775  explicit InternalizedStringKey(Handle<String> string)
16776  : StringTableKey(0), string_(string) {
16777  DCHECK(!string->IsInternalizedString());
16778  DCHECK(string->IsFlat());
16779  // Make sure hash_field is computed.
16780  string->Hash();
16781  set_hash_field(string->hash_field());
16782  }
16783 
16784  bool IsMatch(Object* string) override {
16785  return string_->SlowEquals(String::cast(string));
16786  }
16787 
16788  Handle<String> AsHandle(Isolate* isolate) override {
16789  // Internalize the string if possible.
16790  MaybeHandle<Map> maybe_map =
16791  isolate->factory()->InternalizedStringMapForString(string_);
16792  Handle<Map> map;
16793  if (maybe_map.ToHandle(&map)) {
16794  string_->set_map_no_write_barrier(*map);
16795  DCHECK(string_->IsInternalizedString());
16796  return string_;
16797  }
16798  if (FLAG_thin_strings) {
16799  // External strings get special treatment, to avoid copying their
16800  // contents.
16801  if (string_->IsExternalOneByteString()) {
16802  return isolate->factory()
16803  ->InternalizeExternalString<ExternalOneByteString>(string_);
16804  } else if (string_->IsExternalTwoByteString()) {
16805  return isolate->factory()
16806  ->InternalizeExternalString<ExternalTwoByteString>(string_);
16807  }
16808  }
16809  // Otherwise allocate a new internalized string.
16810  return isolate->factory()->NewInternalizedStringImpl(
16811  string_, string_->length(), string_->hash_field());
16812  }
16813 
16814  private:
16815  Handle<String> string_;
16816 };
16817 
16818 template <typename Derived, typename Shape>
16820  BodyDescriptorBase::IteratePointers(*this, 0, kElementsStartOffset, v);
16821 }
16822 
16823 template <typename Derived, typename Shape>
16824 void HashTable<Derived, Shape>::IterateElements(ObjectVisitor* v) {
16825  BodyDescriptorBase::IteratePointers(*this, kElementsStartOffset,
16826  kHeaderSize + length() * kPointerSize, v);
16827 }
16828 
16829 template <typename Derived, typename Shape>
16830 Handle<Derived> HashTable<Derived, Shape>::New(
16831  Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
16832  MinimumCapacity capacity_option) {
16833  DCHECK_LE(0, at_least_space_for);
16834  DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
16835  base::bits::IsPowerOfTwo(at_least_space_for));
16836 
16837  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
16838  ? at_least_space_for
16839  : ComputeCapacity(at_least_space_for);
16840  if (capacity > HashTable::kMaxCapacity) {
16841  isolate->heap()->FatalProcessOutOfMemory("invalid table size");
16842  }
16843  return NewInternal(isolate, capacity, pretenure);
16844 }
16845 
16846 template <typename Derived, typename Shape>
16847 Handle<Derived> HashTable<Derived, Shape>::NewInternal(
16848  Isolate* isolate, int capacity, PretenureFlag pretenure) {
16849  Factory* factory = isolate->factory();
16850  int length = EntryToIndex(capacity);
16851  RootIndex map_root_index = Shape::GetMapRootIndex();
16852  Handle<FixedArray> array =
16853  factory->NewFixedArrayWithMap(map_root_index, length, pretenure);
16854  Handle<Derived> table = Handle<Derived>::cast(array);
16855 
16856  table->SetNumberOfElements(0);
16857  table->SetNumberOfDeletedElements(0);
16858  table->SetCapacity(capacity);
16859  return table;
16860 }
16861 
16862 template <typename Derived, typename Shape>
16863 void HashTable<Derived, Shape>::Rehash(Isolate* isolate, Derived new_table) {
16864  DisallowHeapAllocation no_gc;
16865  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
16866 
16867  DCHECK_LT(NumberOfElements(), new_table->Capacity());
16868 
16869  // Copy prefix to new array.
16870  for (int i = kPrefixStartIndex; i < kElementsStartIndex; i++) {
16871  new_table->set(i, get(i), mode);
16872  }
16873 
16874  // Rehash the elements.
16875  int capacity = this->Capacity();
16876  ReadOnlyRoots roots(isolate);
16877  for (int i = 0; i < capacity; i++) {
16878  uint32_t from_index = EntryToIndex(i);
16879  Object* k = this->get(from_index);
16880  if (!Shape::IsLive(roots, k)) continue;
16881  uint32_t hash = Shape::HashForObject(isolate, k);
16882  uint32_t insertion_index =
16883  EntryToIndex(new_table->FindInsertionEntry(hash));
16884  for (int j = 0; j < Shape::kEntrySize; j++) {
16885  new_table->set(insertion_index + j, get(from_index + j), mode);
16886  }
16887  }
16888  new_table->SetNumberOfElements(NumberOfElements());
16889  new_table->SetNumberOfDeletedElements(0);
16890 }
16891 
16892 template <typename Derived, typename Shape>
16893 uint32_t HashTable<Derived, Shape>::EntryForProbe(Isolate* isolate, Object* k,
16894  int probe,
16895  uint32_t expected) {
16896  uint32_t hash = Shape::HashForObject(isolate, k);
16897  uint32_t capacity = this->Capacity();
16898  uint32_t entry = FirstProbe(hash, capacity);
16899  for (int i = 1; i < probe; i++) {
16900  if (entry == expected) return expected;
16901  entry = NextProbe(entry, i, capacity);
16902  }
16903  return entry;
16904 }
16905 
16906 template <typename Derived, typename Shape>
16907 void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
16908  WriteBarrierMode mode) {
16909  int index1 = EntryToIndex(entry1);
16910  int index2 = EntryToIndex(entry2);
16911  Object* temp[Shape::kEntrySize];
16912  for (int j = 0; j < Shape::kEntrySize; j++) {
16913  temp[j] = get(index1 + j);
16914  }
16915  for (int j = 0; j < Shape::kEntrySize; j++) {
16916  set(index1 + j, get(index2 + j), mode);
16917  }
16918  for (int j = 0; j < Shape::kEntrySize; j++) {
16919  set(index2 + j, temp[j], mode);
16920  }
16921 }
16922 
16923 template <typename Derived, typename Shape>
16924 void HashTable<Derived, Shape>::Rehash(Isolate* isolate) {
16925  DisallowHeapAllocation no_gc;
16926  WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
16927  ReadOnlyRoots roots(isolate);
16928  uint32_t capacity = Capacity();
16929  bool done = false;
16930  for (int probe = 1; !done; probe++) {
16931  // All elements at entries given by one of the first _probe_ probes
16932  // are placed correctly. Other elements might need to be moved.
16933  done = true;
16934  for (uint32_t current = 0; current < capacity; current++) {
16935  Object* current_key = KeyAt(current);
16936  if (!Shape::IsLive(roots, current_key)) continue;
16937  uint32_t target = EntryForProbe(isolate, current_key, probe, current);
16938  if (current == target) continue;
16939  Object* target_key = KeyAt(target);
16940  if (!Shape::IsLive(roots, target_key) ||
16941  EntryForProbe(isolate, target_key, probe, target) != target) {
16942  // Put the current element into the correct position.
16943  Swap(current, target, mode);
16944  // The other element will be processed on the next iteration.
16945  current--;
16946  } else {
16947  // The place for the current element is occupied. Leave the element
16948  // for the next probe.
16949  done = false;
16950  }
16951  }
16952  }
16953  // Wipe deleted entries.
16954  Object* the_hole = roots.the_hole_value();
16955  Object* undefined = roots.undefined_value();
16956  for (uint32_t current = 0; current < capacity; current++) {
16957  if (KeyAt(current) == the_hole) {
16958  set(EntryToIndex(current) + kEntryKeyIndex, undefined);
16959  }
16960  }
16961  SetNumberOfDeletedElements(0);
16962 }
16963 
16964 template <typename Derived, typename Shape>
16965 Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
16966  Isolate* isolate, Handle<Derived> table, int n, PretenureFlag pretenure) {
16967  if (table->HasSufficientCapacityToAdd(n)) return table;
16968 
16969  int capacity = table->Capacity();
16970  int new_nof = table->NumberOfElements() + n;
16971 
16972  const int kMinCapacityForPretenure = 256;
16973  bool should_pretenure =
16974  pretenure == TENURED ||
16975  ((capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(*table));
16976  Handle<Derived> new_table = HashTable::New(
16977  isolate, new_nof, should_pretenure ? TENURED : NOT_TENURED);
16978 
16979  table->Rehash(isolate, *new_table);
16980  return new_table;
16981 }
16982 
16983 template bool
16984 HashTable<NameDictionary, NameDictionaryShape>::HasSufficientCapacityToAdd(int);
16985 
16986 template <typename Derived, typename Shape>
16987 bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
16988  int number_of_additional_elements) {
16989  int capacity = Capacity();
16990  int nof = NumberOfElements() + number_of_additional_elements;
16991  int nod = NumberOfDeletedElements();
16992  // Return true if:
16993  // 50% is still free after adding number_of_additional_elements elements and
16994  // at most 50% of the free elements are deleted elements.
16995  if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
16996  int needed_free = nof >> 1;
16997  if (nof + needed_free <= capacity) return true;
16998  }
16999  return false;
17000 }
17001 
17002 template <typename Derived, typename Shape>
17003 Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
17004  Handle<Derived> table,
17005  int additionalCapacity) {
17006  int capacity = table->Capacity();
17007  int nof = table->NumberOfElements();
17008 
17009  // Shrink to fit the number of elements if only a quarter of the
17010  // capacity is filled with elements.
17011  if (nof > (capacity >> 2)) return table;
17012  // Allocate a new dictionary with room for at least the current number of
17013  // elements + {additionalCapacity}. The allocation method will make sure that
17014  // there is extra room in the dictionary for additions. Don't go lower than
17015  // room for {kMinShrinkCapacity} elements.
17016  int at_least_room_for = nof + additionalCapacity;
17017  int new_capacity = ComputeCapacity(at_least_room_for);
17018  if (new_capacity < Derived::kMinShrinkCapacity) return table;
17019  if (new_capacity == capacity) return table;
17020 
17021  const int kMinCapacityForPretenure = 256;
17022  bool pretenure = (at_least_room_for > kMinCapacityForPretenure) &&
17023  !Heap::InNewSpace(*table);
17024  Handle<Derived> new_table =
17025  HashTable::New(isolate, new_capacity, pretenure ? TENURED : NOT_TENURED,
17026  USE_CUSTOM_MINIMUM_CAPACITY);
17027 
17028  table->Rehash(isolate, *new_table);
17029  return new_table;
17030 }
17031 
17032 template <typename Derived, typename Shape>
17033 uint32_t HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
17034  uint32_t capacity = Capacity();
17035  uint32_t entry = FirstProbe(hash, capacity);
17036  uint32_t count = 1;
17037  // EnsureCapacity will guarantee the hash table is never full.
17038  ReadOnlyRoots roots = GetReadOnlyRoots();
17039  while (true) {
17040  if (!Shape::IsLive(roots, KeyAt(entry))) break;
17041  entry = NextProbe(entry, count++, capacity);
17042  }
17043  return entry;
17044 }
17045 
17046 void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
17047  Handle<Name> name) {
17048  // Regardless of whether the property is there or not invalidate
17049  // Load/StoreGlobalICs that load/store through global object's prototype.
17050  JSObject::InvalidatePrototypeValidityCell(*global);
17051 
17052  DCHECK(!global->HasFastProperties());
17053  auto dictionary = handle(global->global_dictionary(), global->GetIsolate());
17054  int entry = dictionary->FindEntry(global->GetIsolate(), name);
17055  if (entry == GlobalDictionary::kNotFound) return;
17056  PropertyCell::InvalidateEntry(global->GetIsolate(), dictionary, entry);
17057 }
17058 
17059 Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
17060  Handle<JSGlobalObject> global, Handle<Name> name,
17061  PropertyCellType cell_type, int* entry_out) {
17062  Isolate* isolate = global->GetIsolate();
17063  DCHECK(!global->HasFastProperties());
17064  Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
17065  int entry = dictionary->FindEntry(isolate, name);
17066  Handle<PropertyCell> cell;
17067  if (entry != GlobalDictionary::kNotFound) {
17068  if (entry_out) *entry_out = entry;
17069  cell = handle(dictionary->CellAt(entry), isolate);
17070  PropertyCellType original_cell_type = cell->property_details().cell_type();
17071  DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
17072  original_cell_type == PropertyCellType::kUninitialized);
17073  DCHECK(cell->value()->IsTheHole(isolate));
17074  if (original_cell_type == PropertyCellType::kInvalidated) {
17075  cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
17076  }
17077  PropertyDetails details(kData, NONE, cell_type);
17078  cell->set_property_details(details);
17079  return cell;
17080  }
17081  cell = isolate->factory()->NewPropertyCell(name);
17082  PropertyDetails details(kData, NONE, cell_type);
17083  dictionary = GlobalDictionary::Add(isolate, dictionary, name, cell, details,
17084  entry_out);
17085  // {*entry_out} is initialized inside GlobalDictionary::Add().
17086  global->SetProperties(*dictionary);
17087  return cell;
17088 }
17089 
17090 
17091 // This class is used for looking up two character strings in the string table.
17092 // If we don't have a hit we don't want to waste much time so we unroll the
17093 // string hash calculation loop here for speed. Doesn't work if the two
17094 // characters form a decimal integer, since such strings have a different hash
17095 // algorithm.
17097  public:
17098  TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint64_t seed)
17099  : StringTableKey(ComputeHashField(c1, c2, seed)), c1_(c1), c2_(c2) {}
17100 
17101  bool IsMatch(Object* o) override {
17102  String other = String::cast(o);
17103  if (other->length() != 2) return false;
17104  if (other->Get(0) != c1_) return false;
17105  return other->Get(1) == c2_;
17106  }
17107 
17108  Handle<String> AsHandle(Isolate* isolate) override {
17109  // The TwoCharHashTableKey is only used for looking in the string
17110  // table, not for adding to it.
17111  UNREACHABLE();
17112  }
17113 
17114  private:
17115  uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint64_t seed) {
17116  // Char 1.
17117  uint32_t hash = static_cast<uint32_t>(seed);
17118  hash += c1;
17119  hash += hash << 10;
17120  hash ^= hash >> 6;
17121  // Char 2.
17122  hash += c2;
17123  hash += hash << 10;
17124  hash ^= hash >> 6;
17125  // GetHash.
17126  hash += hash << 3;
17127  hash ^= hash >> 11;
17128  hash += hash << 15;
17129  if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
17130  hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
17131 #ifdef DEBUG
17132  // If this assert fails then we failed to reproduce the two-character
17133  // version of the string hashing algorithm above. One reason could be
17134  // that we were passed two digits as characters, since the hash
17135  // algorithm is different in that case.
17136  uint16_t chars[2] = {c1, c2};
17137  uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
17138  DCHECK_EQ(hash, check_hash);
17139 #endif
17140  return hash;
17141  }
17142 
17143  uint16_t c1_;
17144  uint16_t c2_;
17145 };
17146 
17147 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
17148  Isolate* isolate,
17149  uint16_t c1,
17150  uint16_t c2) {
17151  TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
17152  Handle<StringTable> string_table = isolate->factory()->string_table();
17153  int entry = string_table->FindEntry(isolate, &key);
17154  if (entry == kNotFound) return MaybeHandle<String>();
17155 
17156  Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
17157  DCHECK(StringShape(*result).IsInternalized());
17158  DCHECK_EQ(result->Hash(), key.Hash());
17159  return result;
17160 }
17161 
17162 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17163  int expected) {
17164  Handle<StringTable> table = isolate->factory()->string_table();
17165  // We need a key instance for the virtual hash function.
17166  table = StringTable::EnsureCapacity(isolate, table, expected);
17167  isolate->heap()->SetRootStringTable(*table);
17168 }
17169 
17170 namespace {
17171 
17172 template <class StringClass>
17173 void MigrateExternalStringResource(Isolate* isolate, String from, String to) {
17174  StringClass cast_from = StringClass::cast(from);
17175  StringClass cast_to = StringClass::cast(to);
17176  const typename StringClass::Resource* to_resource = cast_to->resource();
17177  if (to_resource == nullptr) {
17178  // |to| is a just-created internalized copy of |from|. Migrate the resource.
17179  cast_to->SetResource(isolate, cast_from->resource());
17180  // Zap |from|'s resource pointer to reflect the fact that |from| has
17181  // relinquished ownership of its resource.
17182  isolate->heap()->UpdateExternalString(
17183  from, ExternalString::cast(from)->ExternalPayloadSize(), 0);
17184  cast_from->SetResource(isolate, nullptr);
17185  } else if (to_resource != cast_from->resource()) {
17186  // |to| already existed and has its own resource. Finalize |from|.
17187  isolate->heap()->FinalizeExternalString(from);
17188  }
17189 }
17190 
17191 void MakeStringThin(String string, String internalized, Isolate* isolate) {
17192  DCHECK_NE(string, internalized);
17193  DCHECK(internalized->IsInternalizedString());
17194 
17195  if (string->IsExternalString()) {
17196  if (internalized->IsExternalOneByteString()) {
17197  MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
17198  internalized);
17199  } else if (internalized->IsExternalTwoByteString()) {
17200  MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
17201  internalized);
17202  } else {
17203  // If the external string is duped into an existing non-external
17204  // internalized string, free its resource (it's about to be rewritten
17205  // into a ThinString below).
17206  isolate->heap()->FinalizeExternalString(string);
17207  }
17208  }
17209 
17210  DisallowHeapAllocation no_gc;
17211  int old_size = string->Size();
17212  isolate->heap()->NotifyObjectLayoutChange(string, old_size, no_gc);
17213  bool one_byte = internalized->IsOneByteRepresentation();
17214  Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
17215  : isolate->factory()->thin_string_map();
17216  DCHECK_GE(old_size, ThinString::kSize);
17217  string->synchronized_set_map(*map);
17218  ThinString thin = ThinString::cast(string);
17219  thin->set_actual(internalized);
17220  Address thin_end = thin->address() + ThinString::kSize;
17221  int size_delta = old_size - ThinString::kSize;
17222  if (size_delta != 0) {
17223  Heap* heap = isolate->heap();
17224  heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
17225  }
17226 }
17227 
17228 } // namespace
17229 
17230 // static
17231 Handle<String> StringTable::LookupString(Isolate* isolate,
17232  Handle<String> string) {
17233  string = String::Flatten(isolate, string);
17234  if (string->IsInternalizedString()) return string;
17235 
17236  InternalizedStringKey key(string);
17237  Handle<String> result = LookupKey(isolate, &key);
17238 
17239  if (FLAG_thin_strings) {
17240  if (!string->IsInternalizedString()) {
17241  MakeStringThin(*string, *result, isolate);
17242  }
17243  } else { // !FLAG_thin_strings
17244  if (string->IsConsString()) {
17245  Handle<ConsString> cons = Handle<ConsString>::cast(string);
17246  cons->set_first(isolate, *result);
17247  cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
17248  } else if (string->IsSlicedString()) {
17249  STATIC_ASSERT(static_cast<int>(ConsString::kSize) ==
17250  static_cast<int>(SlicedString::kSize));
17251  DisallowHeapAllocation no_gc;
17252  bool one_byte = result->IsOneByteRepresentation();
17253  Handle<Map> map = one_byte
17254  ? isolate->factory()->cons_one_byte_string_map()
17255  : isolate->factory()->cons_string_map();
17256  string->set_map(*map);
17257  Handle<ConsString> cons = Handle<ConsString>::cast(string);
17258  cons->set_first(isolate, *result);
17259  cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
17260  }
17261  }
17262  return result;
17263 }
17264 
17265 // static
17266 Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
17267  Handle<StringTable> table = isolate->factory()->string_table();
17268  int entry = table->FindEntry(isolate, key);
17269 
17270  // String already in table.
17271  if (entry != kNotFound) {
17272  return handle(String::cast(table->KeyAt(entry)), isolate);
17273  }
17274 
17275  table = StringTable::CautiousShrink(isolate, table);
17276  // Adding new string. Grow table if needed.
17277  table = StringTable::EnsureCapacity(isolate, table, 1);
17278  isolate->heap()->SetRootStringTable(*table);
17279 
17280  return AddKeyNoResize(isolate, key);
17281 }
17282 
17283 Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
17284  StringTableKey* key) {
17285  Handle<StringTable> table = isolate->factory()->string_table();
17286  DCHECK(table->HasSufficientCapacityToAdd(1));
17287  // Create string object.
17288  Handle<String> string = key->AsHandle(isolate);
17289  // There must be no attempts to internalize strings that could throw
17290  // InvalidStringLength error.
17291  CHECK(!string.is_null());
17292  DCHECK(string->HasHashCode());
17293  DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
17294 
17295  // Add the new string and return it along with the string table.
17296  int entry = table->FindInsertionEntry(key->Hash());
17297  table->set(EntryToIndex(entry), *string);
17298  table->ElementAdded();
17299 
17300  return Handle<String>::cast(string);
17301 }
17302 
17303 Handle<StringTable> StringTable::CautiousShrink(Isolate* isolate,
17304  Handle<StringTable> table) {
17305  // Only shrink if the table is very empty to avoid performance penalty.
17306  int capacity = table->Capacity();
17307  int nof = table->NumberOfElements();
17308  if (capacity <= StringTable::kMinCapacity) return table;
17309  if (nof > (capacity / kMaxEmptyFactor)) return table;
17310  // Keep capacity for at least half of the current nof elements.
17311  int slack_capacity = nof >> 2;
17312  return Shrink(isolate, table, slack_capacity);
17313 }
17314 
17315 namespace {
17316 
17317 class StringTableNoAllocateKey : public StringTableKey {
17318  public:
17319  StringTableNoAllocateKey(String string, uint64_t seed)
17320  : StringTableKey(0), string_(string) {
17321  StringShape shape(string);
17322  one_byte_ = shape.HasOnlyOneByteChars();
17323  DCHECK(!shape.IsInternalized());
17324  DCHECK(!shape.IsThin());
17325  int length = string->length();
17326  if (shape.IsCons() && length <= String::kMaxHashCalcLength) {
17327  special_flattening_ = true;
17328  uint32_t hash_field = 0;
17329  if (one_byte_) {
17330  if (V8_LIKELY(length <=
17331  static_cast<int>(arraysize(one_byte_buffer_)))) {
17332  one_byte_content_ = one_byte_buffer_;
17333  } else {
17334  one_byte_content_ = new uint8_t[length];
17335  }
17336  String::WriteToFlat(string, one_byte_content_, 0, length);
17337  hash_field =
17338  StringHasher::HashSequentialString(one_byte_content_, length, seed);
17339  } else {
17340  if (V8_LIKELY(length <=
17341  static_cast<int>(arraysize(two_byte_buffer_)))) {
17342  two_byte_content_ = two_byte_buffer_;
17343  } else {
17344  two_byte_content_ = new uint16_t[length];
17345  }
17346  String::WriteToFlat(string, two_byte_content_, 0, length);
17347  hash_field =
17348  StringHasher::HashSequentialString(two_byte_content_, length, seed);
17349  }
17350  string->set_hash_field(hash_field);
17351  } else {
17352  special_flattening_ = false;
17353  one_byte_content_ = nullptr;
17354  string->Hash();
17355  }
17356 
17357  DCHECK(string->HasHashCode());
17358  set_hash_field(string->hash_field());
17359  }
17360 
17361  ~StringTableNoAllocateKey() override {
17362  if (one_byte_) {
17363  if (one_byte_content_ != one_byte_buffer_) delete[] one_byte_content_;
17364  } else {
17365  if (two_byte_content_ != two_byte_buffer_) delete[] two_byte_content_;
17366  }
17367  }
17368 
17369  bool IsMatch(Object* otherstring) override {
17370  String other = String::cast(otherstring);
17371  DCHECK(other->IsInternalizedString());
17372  DCHECK(other->IsFlat());
17373  if (Hash() != other->Hash()) return false;
17374  int len = string_->length();
17375  if (len != other->length()) return false;
17376 
17377  if (!special_flattening_) {
17378  if (string_->Get(0) != other->Get(0)) return false;
17379  if (string_->IsFlat()) {
17380  StringShape shape1(string_);
17381  StringShape shape2(other);
17382  if (shape1.encoding_tag() == kOneByteStringTag &&
17383  shape2.encoding_tag() == kOneByteStringTag) {
17384  String::FlatContent flat1 = string_->GetFlatContent();
17385  String::FlatContent flat2 = other->GetFlatContent();
17386  return CompareRawStringContents(flat1.ToOneByteVector().start(),
17387  flat2.ToOneByteVector().start(), len);
17388  }
17389  if (shape1.encoding_tag() == kTwoByteStringTag &&
17390  shape2.encoding_tag() == kTwoByteStringTag) {
17391  String::FlatContent flat1 = string_->GetFlatContent();
17392  String::FlatContent flat2 = other->GetFlatContent();
17393  return CompareRawStringContents(flat1.ToUC16Vector().start(),
17394  flat2.ToUC16Vector().start(), len);
17395  }
17396  }
17397  StringComparator comparator;
17398  return comparator.Equals(string_, other);
17399  }
17400 
17401  String::FlatContent flat_content = other->GetFlatContent();
17402  if (one_byte_) {
17403  if (flat_content.IsOneByte()) {
17404  return CompareRawStringContents(
17405  one_byte_content_, flat_content.ToOneByteVector().start(), len);
17406  } else {
17407  DCHECK(flat_content.IsTwoByte());
17408  for (int i = 0; i < len; i++) {
17409  if (flat_content.Get(i) != one_byte_content_[i]) return false;
17410  }
17411  return true;
17412  }
17413  } else {
17414  if (flat_content.IsTwoByte()) {
17415  return CompareRawStringContents(
17416  two_byte_content_, flat_content.ToUC16Vector().start(), len);
17417  } else {
17418  DCHECK(flat_content.IsOneByte());
17419  for (int i = 0; i < len; i++) {
17420  if (flat_content.Get(i) != two_byte_content_[i]) return false;
17421  }
17422  return true;
17423  }
17424  }
17425  }
17426 
17427  V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override {
17428  UNREACHABLE();
17429  }
17430 
17431  private:
17432  String string_;
17433  bool one_byte_;
17434  bool special_flattening_;
17435  union {
17436  uint8_t* one_byte_content_;
17437  uint16_t* two_byte_content_;
17438  };
17439  union {
17440  uint8_t one_byte_buffer_[256];
17441  uint16_t two_byte_buffer_[128];
17442  };
17443 };
17444 
17445 } // namespace
17446 
17447 // static
17448 Address StringTable::LookupStringIfExists_NoAllocate(Isolate* isolate,
17449  Address raw_string) {
17450  DisallowHeapAllocation no_gc;
17451  String string = String::cast(ObjectPtr(raw_string));
17452  Heap* heap = isolate->heap();
17453  StringTable table = heap->string_table();
17454 
17455  StringTableNoAllocateKey key(string, heap->HashSeed());
17456 
17457  // String could be an array index.
17458  uint32_t hash = string->hash_field();
17459 
17460  // Valid array indices are >= 0, so they cannot be mixed up with any of
17461  // the result sentinels, which are negative.
17462  STATIC_ASSERT(
17463  !String::ArrayIndexValueBits::is_valid(ResultSentinel::kUnsupported));
17464  STATIC_ASSERT(
17465  !String::ArrayIndexValueBits::is_valid(ResultSentinel::kNotFound));
17466 
17467  if (Name::ContainsCachedArrayIndex(hash)) {
17468  return Smi::FromInt(String::ArrayIndexValueBits::decode(hash)).ptr();
17469  }
17470  if ((hash & Name::kIsNotArrayIndexMask) == 0) {
17471  // It is an indexed, but it's not cached.
17472  return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
17473  }
17474 
17475  DCHECK(!string->IsInternalizedString());
17476  int entry = table->FindEntry(ReadOnlyRoots(isolate), &key, key.Hash());
17477  if (entry != kNotFound) {
17478  String internalized = String::cast(table->KeyAt(entry));
17479  if (FLAG_thin_strings) {
17480  MakeStringThin(string, internalized, isolate);
17481  }
17482  return internalized.ptr();
17483  }
17484  // A string that's not an array index, and not in the string table,
17485  // cannot have been used as a property name before.
17486  return Smi::FromInt(ResultSentinel::kNotFound).ptr();
17487 }
17488 
17489 String StringTable::ForwardStringIfExists(Isolate* isolate, StringTableKey* key,
17490  String string) {
17491  Handle<StringTable> table = isolate->factory()->string_table();
17492  int entry = table->FindEntry(isolate, key);
17493  if (entry == kNotFound) return String();
17494 
17495  String canonical = String::cast(table->KeyAt(entry));
17496  if (canonical != string) MakeStringThin(string, canonical, isolate);
17497  return canonical;
17498 }
17499 
17500 Handle<StringSet> StringSet::New(Isolate* isolate) {
17501  return HashTable::New(isolate, 0);
17502 }
17503 
17504 Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
17505  Handle<String> name) {
17506  if (!stringset->Has(isolate, name)) {
17507  stringset = EnsureCapacity(isolate, stringset, 1);
17508  uint32_t hash = ShapeT::Hash(isolate, *name);
17509  int entry = stringset->FindInsertionEntry(hash);
17510  stringset->set(EntryToIndex(entry), *name);
17511  stringset->ElementAdded();
17512  }
17513  return stringset;
17514 }
17515 
17516 bool StringSet::Has(Isolate* isolate, Handle<String> name) {
17517  return FindEntry(isolate, *name) != kNotFound;
17518 }
17519 
17520 Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
17521  Handle<ObjectHashSet> set,
17522  Handle<Object> key) {
17523  int32_t hash = key->GetOrCreateHash(isolate)->value();
17524  if (!set->Has(isolate, key, hash)) {
17525  set = EnsureCapacity(isolate, set, 1);
17526  int entry = set->FindInsertionEntry(hash);
17527  set->set(EntryToIndex(entry), *key);
17528  set->ElementAdded();
17529  }
17530  return set;
17531 }
17532 
17533 namespace {
17534 
17535 const int kLiteralEntryLength = 2;
17536 const int kLiteralInitialLength = 2;
17537 const int kLiteralContextOffset = 0;
17538 const int kLiteralLiteralsOffset = 1;
17539 
17540 int SearchLiteralsMapEntry(CompilationCacheTable cache, int cache_entry,
17541  Context native_context) {
17542  DisallowHeapAllocation no_gc;
17543  DCHECK(native_context->IsNativeContext());
17544  Object* obj = cache->get(cache_entry);
17545 
17546  // Check that there's no confusion between FixedArray and WeakFixedArray (the
17547  // object used to be a FixedArray here).
17548  DCHECK(!obj->IsFixedArray());
17549  if (obj->IsWeakFixedArray()) {
17550  WeakFixedArray* literals_map = WeakFixedArray::cast(obj);
17551  int length = literals_map->length();
17552  for (int i = 0; i < length; i += kLiteralEntryLength) {
17553  DCHECK(literals_map->Get(i + kLiteralContextOffset)->IsWeakOrCleared());
17554  if (literals_map->Get(i + kLiteralContextOffset) ==
17555  HeapObjectReference::Weak(native_context)) {
17556  return i;
17557  }
17558  }
17559  }
17560  return -1;
17561 }
17562 
17563 void AddToFeedbackCellsMap(Handle<CompilationCacheTable> cache, int cache_entry,
17564  Handle<Context> native_context,
17565  Handle<FeedbackCell> feedback_cell) {
17566  Isolate* isolate = native_context->GetIsolate();
17567  DCHECK(native_context->IsNativeContext());
17568  STATIC_ASSERT(kLiteralEntryLength == 2);
17569  Handle<WeakFixedArray> new_literals_map;
17570  int entry;
17571 
17572  Object* obj = cache->get(cache_entry);
17573 
17574  // Check that there's no confusion between FixedArray and WeakFixedArray (the
17575  // object used to be a FixedArray here).
17576  DCHECK(!obj->IsFixedArray());
17577  if (!obj->IsWeakFixedArray() || WeakFixedArray::cast(obj)->length() == 0) {
17578  new_literals_map =
17579  isolate->factory()->NewWeakFixedArray(kLiteralInitialLength, TENURED);
17580  entry = 0;
17581  } else {
17582  Handle<WeakFixedArray> old_literals_map(WeakFixedArray::cast(obj), isolate);
17583  entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context);
17584  if (entry >= 0) {
17585  // Just set the code of the entry.
17586  old_literals_map->Set(entry + kLiteralLiteralsOffset,
17587  HeapObjectReference::Weak(*feedback_cell));
17588  return;
17589  }
17590 
17591  // Can we reuse an entry?
17592  DCHECK_LT(entry, 0);
17593  int length = old_literals_map->length();
17594  for (int i = 0; i < length; i += kLiteralEntryLength) {
17595  if (old_literals_map->Get(i + kLiteralContextOffset)->IsCleared()) {
17596  new_literals_map = old_literals_map;
17597  entry = i;
17598  break;
17599  }
17600  }
17601 
17602  if (entry < 0) {
17603  // Copy old optimized code map and append one new entry.
17604  new_literals_map = isolate->factory()->CopyWeakFixedArrayAndGrow(
17605  old_literals_map, kLiteralEntryLength, TENURED);
17606  entry = old_literals_map->length();
17607  }
17608  }
17609 
17610  new_literals_map->Set(entry + kLiteralContextOffset,
17611  HeapObjectReference::Weak(*native_context));
17612  new_literals_map->Set(entry + kLiteralLiteralsOffset,
17613  HeapObjectReference::Weak(*feedback_cell));
17614 
17615 #ifdef DEBUG
17616  for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) {
17617  MaybeObject object = new_literals_map->Get(i + kLiteralContextOffset);
17618  DCHECK(object->IsCleared() ||
17619  object->GetHeapObjectAssumeWeak()->IsNativeContext());
17620  object = new_literals_map->Get(i + kLiteralLiteralsOffset);
17621  DCHECK(object->IsCleared() ||
17622  object->GetHeapObjectAssumeWeak()->IsFeedbackCell());
17623  }
17624 #endif
17625 
17626  Object* old_literals_map = cache->get(cache_entry);
17627  if (old_literals_map != *new_literals_map) {
17628  cache->set(cache_entry, *new_literals_map);
17629  }
17630 }
17631 
17632 FeedbackCell* SearchLiteralsMap(CompilationCacheTable cache, int cache_entry,
17633  Context native_context) {
17634  FeedbackCell* result = nullptr;
17635  int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context);
17636  if (entry >= 0) {
17637  WeakFixedArray* literals_map =
17638  WeakFixedArray::cast(cache->get(cache_entry));
17639  DCHECK_LE(entry + kLiteralEntryLength, literals_map->length());
17640  MaybeObject object = literals_map->Get(entry + kLiteralLiteralsOffset);
17641 
17642  result = object->IsCleared()
17643  ? nullptr
17644  : FeedbackCell::cast(object->GetHeapObjectAssumeWeak());
17645  }
17646  DCHECK(result == nullptr || result->IsFeedbackCell());
17647  return result;
17648 }
17649 
17650 } // namespace
17651 
17652 MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
17653  Handle<CompilationCacheTable> table, Handle<String> src,
17654  Handle<Context> native_context, LanguageMode language_mode) {
17655  // We use the empty function SFI as part of the key. Although the
17656  // empty_function is native context dependent, the SFI is de-duped on
17657  // snapshot builds by the PartialSnapshotCache, and so this does not prevent
17658  // reuse of scripts in the compilation cache across native contexts.
17659  Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
17660  native_context->GetIsolate());
17661  Isolate* isolate = native_context->GetIsolate();
17662  src = String::Flatten(isolate, src);
17663  StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
17664  int entry = table->FindEntry(isolate, &key);
17665  if (entry == kNotFound) return MaybeHandle<SharedFunctionInfo>();
17666  int index = EntryToIndex(entry);
17667  if (!table->get(index)->IsFixedArray()) {
17668  return MaybeHandle<SharedFunctionInfo>();
17669  }
17670  Object* obj = table->get(index + 1);
17671  if (obj->IsSharedFunctionInfo()) {
17672  return handle(SharedFunctionInfo::cast(obj), native_context->GetIsolate());
17673  }
17674  return MaybeHandle<SharedFunctionInfo>();
17675 }
17676 
17677 InfoCellPair CompilationCacheTable::LookupEval(
17678  Handle<CompilationCacheTable> table, Handle<String> src,
17679  Handle<SharedFunctionInfo> outer_info, Handle<Context> native_context,
17680  LanguageMode language_mode, int position) {
17681  InfoCellPair empty_result;
17682  Isolate* isolate = native_context->GetIsolate();
17683  src = String::Flatten(isolate, src);
17684  StringSharedKey key(src, outer_info, language_mode, position);
17685  int entry = table->FindEntry(isolate, &key);
17686  if (entry == kNotFound) return empty_result;
17687  int index = EntryToIndex(entry);
17688  if (!table->get(index)->IsFixedArray()) return empty_result;
17689  Object* obj = table->get(EntryToIndex(entry) + 1);
17690  if (obj->IsSharedFunctionInfo()) {
17691  FeedbackCell* feedback_cell =
17692  SearchLiteralsMap(*table, EntryToIndex(entry) + 2, *native_context);
17693  return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
17694  }
17695  return empty_result;
17696 }
17697 
17698 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
17699  JSRegExp::Flags flags) {
17700  Isolate* isolate = GetIsolate();
17701  DisallowHeapAllocation no_allocation;
17702  RegExpKey key(src, flags);
17703  int entry = FindEntry(isolate, &key);
17704  if (entry == kNotFound) return isolate->factory()->undefined_value();
17705  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
17706 }
17707 
17708 Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
17709  Handle<CompilationCacheTable> cache, Handle<String> src,
17710  Handle<Context> native_context, LanguageMode language_mode,
17711  Handle<SharedFunctionInfo> value) {
17712  Isolate* isolate = native_context->GetIsolate();
17713  // We use the empty function SFI as part of the key. Although the
17714  // empty_function is native context dependent, the SFI is de-duped on
17715  // snapshot builds by the PartialSnapshotCache, and so this does not prevent
17716  // reuse of scripts in the compilation cache across native contexts.
17717  Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
17718  isolate);
17719  src = String::Flatten(isolate, src);
17720  StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
17721  Handle<Object> k = key.AsHandle(isolate);
17722  cache = EnsureCapacity(isolate, cache, 1);
17723  int entry = cache->FindInsertionEntry(key.Hash());
17724  cache->set(EntryToIndex(entry), *k);
17725  cache->set(EntryToIndex(entry) + 1, *value);
17726  cache->ElementAdded();
17727  return cache;
17728 }
17729 
17730 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
17731  Handle<CompilationCacheTable> cache, Handle<String> src,
17732  Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
17733  Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
17734  int position) {
17735  Isolate* isolate = native_context->GetIsolate();
17736  src = String::Flatten(isolate, src);
17737  StringSharedKey key(src, outer_info, value->language_mode(), position);
17738  {
17739  Handle<Object> k = key.AsHandle(isolate);
17740  int entry = cache->FindEntry(isolate, &key);
17741  if (entry != kNotFound) {
17742  cache->set(EntryToIndex(entry), *k);
17743  cache->set(EntryToIndex(entry) + 1, *value);
17744  // AddToFeedbackCellsMap may allocate a new sub-array to live in the
17745  // entry, but it won't change the cache array. Therefore EntryToIndex
17746  // and entry remains correct.
17747  AddToFeedbackCellsMap(cache, EntryToIndex(entry) + 2, native_context,
17748  feedback_cell);
17749  return cache;
17750  }
17751  }
17752 
17753  cache = EnsureCapacity(isolate, cache, 1);
17754  int entry = cache->FindInsertionEntry(key.Hash());
17755  Handle<Object> k =
17756  isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
17757  cache->set(EntryToIndex(entry), *k);
17758  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
17759  cache->ElementAdded();
17760  return cache;
17761 }
17762 
17763 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
17764  Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
17765  JSRegExp::Flags flags, Handle<FixedArray> value) {
17766  RegExpKey key(src, flags);
17767  cache = EnsureCapacity(isolate, cache, 1);
17768  int entry = cache->FindInsertionEntry(key.Hash());
17769  // We store the value in the key slot, and compare the search key
17770  // to the stored value with a custon IsMatch function during lookups.
17771  cache->set(EntryToIndex(entry), *value);
17772  cache->set(EntryToIndex(entry) + 1, *value);
17773  cache->ElementAdded();
17774  return cache;
17775 }
17776 
17777 
17778 void CompilationCacheTable::Age() {
17779  DisallowHeapAllocation no_allocation;
17780  Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
17781  for (int entry = 0, size = Capacity(); entry < size; entry++) {
17782  int entry_index = EntryToIndex(entry);
17783  int value_index = entry_index + 1;
17784 
17785  if (get(entry_index)->IsNumber()) {
17786  Smi count = Smi::cast(get(value_index));
17787  count = Smi::FromInt(count->value() - 1);
17788  if (count->value() == 0) {
17789  NoWriteBarrierSet(*this, entry_index, the_hole_value);
17790  NoWriteBarrierSet(*this, value_index, the_hole_value);
17791  ElementRemoved();
17792  } else {
17793  NoWriteBarrierSet(*this, value_index, count);
17794  }
17795  } else if (get(entry_index)->IsFixedArray()) {
17796  SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
17797  if (info->IsInterpreted() && info->GetBytecodeArray()->IsOld()) {
17798  for (int i = 0; i < kEntrySize; i++) {
17799  NoWriteBarrierSet(*this, entry_index + i, the_hole_value);
17800  }
17801  ElementRemoved();
17802  }
17803  }
17804  }
17805 }
17806 
17807 
17808 void CompilationCacheTable::Remove(Object* value) {
17809  DisallowHeapAllocation no_allocation;
17810  Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
17811  for (int entry = 0, size = Capacity(); entry < size; entry++) {
17812  int entry_index = EntryToIndex(entry);
17813  int value_index = entry_index + 1;
17814  if (get(value_index) == value) {
17815  for (int i = 0; i < kEntrySize; i++) {
17816  NoWriteBarrierSet(*this, entry_index + i, the_hole_value);
17817  }
17818  ElementRemoved();
17819  }
17820  }
17821  return;
17822 }
17823 
17824 template <typename Derived, typename Shape>
17825 Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
17826  Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
17827  MinimumCapacity capacity_option) {
17828  DCHECK_LE(0, at_least_space_for);
17829  Handle<Derived> dict = Dictionary<Derived, Shape>::New(
17830  isolate, at_least_space_for, pretenure, capacity_option);
17831  dict->SetHash(PropertyArray::kNoHashSentinel);
17832  dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
17833  return dict;
17834 }
17835 
17836 template <typename Derived, typename Shape>
17837 Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
17838  Isolate* isolate, Handle<Derived> dictionary, int n) {
17839  // Check whether there are enough enumeration indices to add n elements.
17840  if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
17841  // If not, we generate new indices for the properties.
17842  int length = dictionary->NumberOfElements();
17843 
17844  Handle<FixedArray> iteration_order = IterationIndices(isolate, dictionary);
17845  DCHECK_EQ(length, iteration_order->length());
17846 
17847  // Iterate over the dictionary using the enumeration order and update
17848  // the dictionary with new enumeration indices.
17849  for (int i = 0; i < length; i++) {
17850  int index = Smi::ToInt(iteration_order->get(i));
17851  DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
17852  dictionary->KeyAt(index)));
17853 
17854  int enum_index = PropertyDetails::kInitialIndex + i;
17855 
17856  PropertyDetails details = dictionary->DetailsAt(index);
17857  PropertyDetails new_details = details.set_index(enum_index);
17858  dictionary->DetailsAtPut(isolate, index, new_details);
17859  }
17860 
17861  // Set the next enumeration index.
17862  dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
17863  length);
17864  }
17865  return HashTable<Derived, Shape>::EnsureCapacity(isolate, dictionary, n);
17866 }
17867 
17868 template <typename Derived, typename Shape>
17869 Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
17870  Isolate* isolate, Handle<Derived> dictionary, int entry) {
17871  DCHECK(Shape::kEntrySize != 3 ||
17872  dictionary->DetailsAt(entry).IsConfigurable());
17873  dictionary->ClearEntry(isolate, entry);
17874  dictionary->ElementRemoved();
17875  return Shrink(isolate, dictionary);
17876 }
17877 
17878 template <typename Derived, typename Shape>
17879 Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
17880  Handle<Derived> dictionary,
17881  Key key, Handle<Object> value,
17882  PropertyDetails details) {
17883  int entry = dictionary->FindEntry(isolate, key);
17884 
17885  // If the entry is present set the value;
17886  if (entry == Dictionary::kNotFound) {
17887  return Derived::Add(isolate, dictionary, key, value, details);
17888  }
17889 
17890  // We don't need to copy over the enumeration index.
17891  dictionary->ValueAtPut(entry, *value);
17892  if (Shape::kEntrySize == 3) dictionary->DetailsAtPut(isolate, entry, details);
17893  return dictionary;
17894 }
17895 
17896 template <typename Derived, typename Shape>
17897 Handle<Derived>
17898 BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
17899  Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
17900  PropertyDetails details, int* entry_out) {
17901  // Insert element at empty or deleted entry
17902  return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
17903  details, entry_out);
17904 }
17905 
17906 // GCC workaround: Explicitly instantiate template method for NameDictionary
17907 // to avoid "undefined reference" issues during linking.
17908 template Handle<NameDictionary>
17909 BaseNameDictionary<NameDictionary, NameDictionaryShape>::
17910  AddNoUpdateNextEnumerationIndex(Isolate* isolate, Handle<NameDictionary>,
17911  Handle<Name>, Handle<Object>,
17912  PropertyDetails, int*);
17913 
17914 template <typename Derived, typename Shape>
17915 Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
17916  Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
17917  PropertyDetails details, int* entry_out) {
17918  // Insert element at empty or deleted entry
17919  DCHECK_EQ(0, details.dictionary_index());
17920  // Assign an enumeration index to the property and update
17921  // SetNextEnumerationIndex.
17922  int index = dictionary->NextEnumerationIndex();
17923  details = details.set_index(index);
17924  dictionary = AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
17925  details, entry_out);
17926  // Update enumeration index here in order to avoid potential modification of
17927  // the canonical empty dictionary which lives in read only space.
17928  dictionary->SetNextEnumerationIndex(index + 1);
17929  return dictionary;
17930 }
17931 
17932 template <typename Derived, typename Shape>
17933 Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
17934  Handle<Derived> dictionary,
17935  Key key, Handle<Object> value,
17936  PropertyDetails details,
17937  int* entry_out) {
17938  uint32_t hash = Shape::Hash(isolate, key);
17939  // Valdate key is absent.
17940  SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
17941  // Check whether the dictionary should be extended.
17942  dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
17943 
17944  // Compute the key object.
17945  Handle<Object> k = Shape::AsHandle(isolate, key);
17946 
17947  uint32_t entry = dictionary->FindInsertionEntry(hash);
17948  dictionary->SetEntry(isolate, entry, *k, *value, details);
17949  DCHECK(dictionary->KeyAt(entry)->IsNumber() ||
17950  Shape::Unwrap(dictionary->KeyAt(entry))->IsUniqueName());
17951  dictionary->ElementAdded();
17952  if (entry_out) *entry_out = entry;
17953  return dictionary;
17954 }
17955 
17956 // static
17957 Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
17958  Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
17959  Handle<Object> value) {
17960  return AtPut(isolate, dictionary, key, value, PropertyDetails::Empty());
17961 }
17962 
17963 bool NumberDictionary::HasComplexElements() {
17964  if (!requires_slow_elements()) return false;
17965  ReadOnlyRoots roots = GetReadOnlyRoots();
17966  int capacity = this->Capacity();
17967  for (int i = 0; i < capacity; i++) {
17968  Object* k;
17969  if (!this->ToKey(roots, i, &k)) continue;
17970  PropertyDetails details = this->DetailsAt(i);
17971  if (details.kind() == kAccessor) return true;
17972  PropertyAttributes attr = details.attributes();
17973  if (attr & ALL_ATTRIBUTES_MASK) return true;
17974  }
17975  return false;
17976 }
17977 
17978 void NumberDictionary::UpdateMaxNumberKey(uint32_t key,
17979  Handle<JSObject> dictionary_holder) {
17980  DisallowHeapAllocation no_allocation;
17981  // If the dictionary requires slow elements an element has already
17982  // been added at a high index.
17983  if (requires_slow_elements()) return;
17984  // Check if this index is high enough that we should require slow
17985  // elements.
17986  if (key > kRequiresSlowElementsLimit) {
17987  if (!dictionary_holder.is_null()) {
17988  dictionary_holder->RequireSlowElements(*this);
17989  }
17990  set_requires_slow_elements();
17991  return;
17992  }
17993  // Update max key value.
17994  Object* max_index_object = get(kMaxNumberKeyIndex);
17995  if (!max_index_object->IsSmi() || max_number_key() < key) {
17996  FixedArray::set(kMaxNumberKeyIndex,
17997  Smi::FromInt(key << kRequiresSlowElementsTagSize));
17998  }
17999 }
18000 
18001 Handle<NumberDictionary> NumberDictionary::Set(
18002  Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
18003  Handle<Object> value, Handle<JSObject> dictionary_holder,
18004  PropertyDetails details) {
18005  dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18006  return AtPut(isolate, dictionary, key, value, details);
18007 }
18008 
18009 void NumberDictionary::CopyValuesTo(FixedArray elements) {
18010  ReadOnlyRoots roots = GetReadOnlyRoots();
18011  int pos = 0;
18012  int capacity = this->Capacity();
18013  DisallowHeapAllocation no_gc;
18014  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
18015  for (int i = 0; i < capacity; i++) {
18016  Object* k;
18017  if (this->ToKey(roots, i, &k)) {
18018  elements->set(pos++, this->ValueAt(i), mode);
18019  }
18020  }
18021  DCHECK_EQ(pos, elements->length());
18022 }
18023 
18024 template <typename Derived, typename Shape>
18025 int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
18026  ReadOnlyRoots roots = this->GetReadOnlyRoots();
18027  int capacity = this->Capacity();
18028  int result = 0;
18029  for (int i = 0; i < capacity; i++) {
18030  Object* k;
18031  if (!this->ToKey(roots, i, &k)) continue;
18032  if (k->FilterKey(ENUMERABLE_STRINGS)) continue;
18033  PropertyDetails details = this->DetailsAt(i);
18034  PropertyAttributes attr = details.attributes();
18035  if ((attr & ONLY_ENUMERABLE) == 0) result++;
18036  }
18037  return result;
18038 }
18039 
18040 
18041 template <typename Dictionary>
18043  explicit EnumIndexComparator(Dictionary dict) : dict(dict) {}
18044  bool operator()(Tagged_t a, Tagged_t b) {
18045  // TODO(ishell): revisit the code below
18046  STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
18047  PropertyDetails da(dict->DetailsAt(Smi(a).value()));
18048  PropertyDetails db(dict->DetailsAt(Smi(b).value()));
18049  return da.dictionary_index() < db.dictionary_index();
18050  }
18051  Dictionary dict;
18052 };
18053 
18054 template <typename Derived, typename Shape>
18056  Isolate* isolate, Handle<Derived> dictionary, Handle<FixedArray> storage,
18057  KeyCollectionMode mode, KeyAccumulator* accumulator) {
18058  DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
18059  int length = storage->length();
18060  int capacity = dictionary->Capacity();
18061  int properties = 0;
18062  ReadOnlyRoots roots(isolate);
18063  for (int i = 0; i < capacity; i++) {
18064  Object* key;
18065  if (!dictionary->ToKey(roots, i, &key)) continue;
18066  bool is_shadowing_key = false;
18067  if (key->IsSymbol()) continue;
18068  PropertyDetails details = dictionary->DetailsAt(i);
18069  if (details.IsDontEnum()) {
18070  if (mode == KeyCollectionMode::kIncludePrototypes) {
18071  is_shadowing_key = true;
18072  } else {
18073  continue;
18074  }
18075  }
18076  if (is_shadowing_key) {
18077  accumulator->AddShadowingKey(key);
18078  continue;
18079  } else {
18080  storage->set(properties, Smi::FromInt(i));
18081  }
18082  properties++;
18083  if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
18084  }
18085 
18086  CHECK_EQ(length, properties);
18087  DisallowHeapAllocation no_gc;
18088  Derived raw_dictionary = *dictionary;
18089  FixedArray raw_storage = *storage;
18090  EnumIndexComparator<Derived> cmp(raw_dictionary);
18091  // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
18092  // store operations that are safe for concurrent marking.
18093  AtomicSlot start(storage->GetFirstElementAddress());
18094  std::sort(start, start + length, cmp);
18095  for (int i = 0; i < length; i++) {
18096  int index = Smi::ToInt(raw_storage->get(i));
18097  raw_storage->set(i, raw_dictionary->NameAt(index));
18098  }
18099 }
18100 
18101 template <typename Derived, typename Shape>
18102 Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
18103  Isolate* isolate, Handle<Derived> dictionary) {
18104  int capacity = dictionary->Capacity();
18105  int length = dictionary->NumberOfElements();
18106  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
18107  ReadOnlyRoots roots(isolate);
18108  int array_size = 0;
18109  {
18110  DisallowHeapAllocation no_gc;
18111  Derived raw_dictionary = *dictionary;
18112  for (int i = 0; i < capacity; i++) {
18113  Object* k;
18114  if (!raw_dictionary->ToKey(roots, i, &k)) continue;
18115  array->set(array_size++, Smi::FromInt(i));
18116  }
18117 
18118  DCHECK_EQ(array_size, length);
18119 
18120  EnumIndexComparator<Derived> cmp(raw_dictionary);
18121  // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
18122  // store operations that are safe for concurrent marking.
18123  AtomicSlot start(array->GetFirstElementAddress());
18124  std::sort(start, start + array_size, cmp);
18125  }
18126  return FixedArray::ShrinkOrEmpty(isolate, array, array_size);
18127 }
18128 
18129 template <typename Derived, typename Shape>
18130 void BaseNameDictionary<Derived, Shape>::CollectKeysTo(
18131  Handle<Derived> dictionary, KeyAccumulator* keys) {
18132  Isolate* isolate = keys->isolate();
18133  ReadOnlyRoots roots(isolate);
18134  int capacity = dictionary->Capacity();
18135  Handle<FixedArray> array =
18136  isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
18137  int array_size = 0;
18138  PropertyFilter filter = keys->filter();
18139  {
18140  DisallowHeapAllocation no_gc;
18141  Derived raw_dictionary = *dictionary;
18142  for (int i = 0; i < capacity; i++) {
18143  Object* k;
18144  if (!raw_dictionary->ToKey(roots, i, &k)) continue;
18145  if (k->FilterKey(filter)) continue;
18146  PropertyDetails details = raw_dictionary->DetailsAt(i);
18147  if ((details.attributes() & filter) != 0) {
18148  keys->AddShadowingKey(k);
18149  continue;
18150  }
18151  if (filter & ONLY_ALL_CAN_READ) {
18152  if (details.kind() != kAccessor) continue;
18153  Object* accessors = raw_dictionary->ValueAt(i);
18154  if (!accessors->IsAccessorInfo()) continue;
18155  if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
18156  }
18157  array->set(array_size++, Smi::FromInt(i));
18158  }
18159 
18160  EnumIndexComparator<Derived> cmp(raw_dictionary);
18161  // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
18162  // store operations that are safe for concurrent marking.
18163  AtomicSlot start(array->GetFirstElementAddress());
18164  std::sort(start, start + array_size, cmp);
18165  }
18166 
18167  bool has_seen_symbol = false;
18168  for (int i = 0; i < array_size; i++) {
18169  int index = Smi::ToInt(array->get(i));
18170  Object* key = dictionary->NameAt(index);
18171  if (key->IsSymbol()) {
18172  has_seen_symbol = true;
18173  continue;
18174  }
18175  keys->AddKey(key, DO_NOT_CONVERT);
18176  }
18177  if (has_seen_symbol) {
18178  for (int i = 0; i < array_size; i++) {
18179  int index = Smi::ToInt(array->get(i));
18180  Object* key = dictionary->NameAt(index);
18181  if (!key->IsSymbol()) continue;
18182  keys->AddKey(key, DO_NOT_CONVERT);
18183  }
18184  }
18185 }
18186 
18187 // Backwards lookup (slow).
18188 template <typename Derived, typename Shape>
18189 Object* Dictionary<Derived, Shape>::SlowReverseLookup(Object* value) {
18190  Derived dictionary = Derived::cast(*this);
18191  ReadOnlyRoots roots = dictionary->GetReadOnlyRoots();
18192  int capacity = dictionary->Capacity();
18193  for (int i = 0; i < capacity; i++) {
18194  Object* k;
18195  if (!dictionary->ToKey(roots, i, &k)) continue;
18196  Object* e = dictionary->ValueAt(i);
18197  if (e == value) return k;
18198  }
18199  return roots.undefined_value();
18200 }
18201 
18202 template <typename Derived, typename Shape>
18203 void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
18204  Handle<Derived> table) {
18205  int length = table->length();
18206  for (int i = Derived::EntryToIndex(0); i < length; i++) {
18207  table->set_the_hole(i);
18208  }
18209 }
18210 
18211 template <typename Derived, typename Shape>
18212 Object* ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
18213  Handle<Object> key,
18214  int32_t hash) {
18215  DisallowHeapAllocation no_gc;
18216  DCHECK(this->IsKey(roots, *key));
18217 
18218  int entry = this->FindEntry(roots, key, hash);
18219  if (entry == kNotFound) return roots.the_hole_value();
18220  return this->get(Derived::EntryToIndex(entry) + 1);
18221 }
18222 
18223 template <typename Derived, typename Shape>
18224 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key) {
18225  DisallowHeapAllocation no_gc;
18226 
18227  ReadOnlyRoots roots = this->GetReadOnlyRoots();
18228  DCHECK(this->IsKey(roots, *key));
18229 
18230  // If the object does not have an identity hash, it was never used as a key.
18231  Object* hash = key->GetHash();
18232  if (hash->IsUndefined(roots)) {
18233  return roots.the_hole_value();
18234  }
18235  return Lookup(roots, key, Smi::ToInt(hash));
18236 }
18237 
18238 template <typename Derived, typename Shape>
18239 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
18240  int32_t hash) {
18241  return Lookup(this->GetReadOnlyRoots(), key, hash);
18242 }
18243 
18244 template <typename Derived, typename Shape>
18245 Object* ObjectHashTableBase<Derived, Shape>::ValueAt(int entry) {
18246  return this->get(EntryToValueIndex(entry));
18247 }
18248 
18249 template <typename Derived, typename Shape>
18250 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Handle<Derived> table,
18251  Handle<Object> key,
18252  Handle<Object> value) {
18253  Isolate* isolate = Heap::FromWritableHeapObject(*table)->isolate();
18254  DCHECK(table->IsKey(ReadOnlyRoots(isolate), *key));
18255  DCHECK(!value->IsTheHole(ReadOnlyRoots(isolate)));
18256 
18257  // Make sure the key object has an identity hash code.
18258  int32_t hash = key->GetOrCreateHash(isolate)->value();
18259 
18260  return ObjectHashTableBase<Derived, Shape>::Put(isolate, table, key, value,
18261  hash);
18262 }
18263 
18264 template <typename Derived, typename Shape>
18265 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
18266  Handle<Derived> table,
18267  Handle<Object> key,
18268  Handle<Object> value,
18269  int32_t hash) {
18270  ReadOnlyRoots roots(isolate);
18271  DCHECK(table->IsKey(roots, *key));
18272  DCHECK(!value->IsTheHole(roots));
18273 
18274  int entry = table->FindEntry(roots, key, hash);
18275 
18276  // Key is already in table, just overwrite value.
18277  if (entry != kNotFound) {
18278  table->set(Derived::EntryToIndex(entry) + 1, *value);
18279  return table;
18280  }
18281 
18282  // Rehash if more than 33% of the entries are deleted entries.
18283  // TODO(jochen): Consider to shrink the fixed array in place.
18284  if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
18285  table->Rehash(isolate);
18286  }
18287  // If we're out of luck, we didn't get a GC recently, and so rehashing
18288  // isn't enough to avoid a crash.
18289  if (!table->HasSufficientCapacityToAdd(1)) {
18290  int nof = table->NumberOfElements() + 1;
18291  int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
18292  if (capacity > ObjectHashTable::kMaxCapacity) {
18293  for (size_t i = 0; i < 2; ++i) {
18294  isolate->heap()->CollectAllGarbage(
18295  Heap::kNoGCFlags, GarbageCollectionReason::kFullHashtable);
18296  }
18297  table->Rehash(isolate);
18298  }
18299  }
18300 
18301  // Check whether the hash table should be extended.
18302  table = Derived::EnsureCapacity(isolate, table, 1);
18303  table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
18304  return table;
18305 }
18306 
18307 template <typename Derived, typename Shape>
18308 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
18309  Isolate* isolate, Handle<Derived> table, Handle<Object> key,
18310  bool* was_present) {
18311  DCHECK(table->IsKey(table->GetReadOnlyRoots(), *key));
18312 
18313  Object* hash = key->GetHash();
18314  if (hash->IsUndefined()) {
18315  *was_present = false;
18316  return table;
18317  }
18318 
18319  return Remove(isolate, table, key, was_present, Smi::ToInt(hash));
18320 }
18321 
18322 template <typename Derived, typename Shape>
18323 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
18324  Isolate* isolate, Handle<Derived> table, Handle<Object> key,
18325  bool* was_present, int32_t hash) {
18326  ReadOnlyRoots roots = table->GetReadOnlyRoots();
18327  DCHECK(table->IsKey(roots, *key));
18328 
18329  int entry = table->FindEntry(roots, key, hash);
18330  if (entry == kNotFound) {
18331  *was_present = false;
18332  return table;
18333  }
18334 
18335  *was_present = true;
18336  table->RemoveEntry(entry);
18337  return Derived::Shrink(isolate, table);
18338 }
18339 
18340 template <typename Derived, typename Shape>
18341 void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object* key,
18342  Object* value) {
18343  this->set(Derived::EntryToIndex(entry), key);
18344  this->set(Derived::EntryToIndex(entry) + 1, value);
18345  this->ElementAdded();
18346 }
18347 
18348 template <typename Derived, typename Shape>
18349 void ObjectHashTableBase<Derived, Shape>::RemoveEntry(int entry) {
18350  this->set_the_hole(Derived::EntryToIndex(entry));
18351  this->set_the_hole(Derived::EntryToIndex(entry) + 1);
18352  this->ElementRemoved();
18353 }
18354 
18355 
18356 void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
18357  Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
18358  set->set_table(*table);
18359 }
18360 
18361 void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) {
18362  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
18363  table = OrderedHashSet::Clear(isolate, table);
18364  set->set_table(*table);
18365 }
18366 
18367 
18368 void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
18369  Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
18370  map->set_table(*table);
18371 }
18372 
18373 void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
18374  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
18375  table = OrderedHashMap::Clear(isolate, table);
18376  map->set_table(*table);
18377 }
18378 
18379 
18380 void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
18381  Isolate* isolate) {
18382  Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);
18383  weak_collection->set_table(*table);
18384 }
18385 
18386 
18387 void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
18388  Handle<Object> key, Handle<Object> value,
18389  int32_t hash) {
18390  DCHECK(key->IsJSReceiver() || key->IsSymbol());
18391  Handle<EphemeronHashTable> table(
18392  EphemeronHashTable::cast(weak_collection->table()),
18393  weak_collection->GetIsolate());
18394  DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
18395  Handle<EphemeronHashTable> new_table = EphemeronHashTable::Put(
18396  weak_collection->GetIsolate(), table, key, value, hash);
18397  weak_collection->set_table(*new_table);
18398  if (*table != *new_table) {
18399  // Zap the old table since we didn't record slots for its elements.
18400  EphemeronHashTable::FillEntriesWithHoles(table);
18401  }
18402 }
18403 
18404 
18405 bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
18406  Handle<Object> key, int32_t hash) {
18407  DCHECK(key->IsJSReceiver() || key->IsSymbol());
18408  Handle<EphemeronHashTable> table(
18409  EphemeronHashTable::cast(weak_collection->table()),
18410  weak_collection->GetIsolate());
18411  DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
18412  bool was_present = false;
18413  Handle<EphemeronHashTable> new_table = EphemeronHashTable::Remove(
18414  weak_collection->GetIsolate(), table, key, &was_present, hash);
18415  weak_collection->set_table(*new_table);
18416  if (*table != *new_table) {
18417  // Zap the old table since we didn't record slots for its elements.
18418  EphemeronHashTable::FillEntriesWithHoles(table);
18419  }
18420  return was_present;
18421 }
18422 
18423 Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
18424  int max_entries) {
18425  Isolate* isolate = holder->GetIsolate();
18426  Handle<EphemeronHashTable> table(EphemeronHashTable::cast(holder->table()),
18427  isolate);
18428  if (max_entries == 0 || max_entries > table->NumberOfElements()) {
18429  max_entries = table->NumberOfElements();
18430  }
18431  int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
18432  Handle<FixedArray> entries =
18433  isolate->factory()->NewFixedArray(max_entries * values_per_entry);
18434  // Recompute max_values because GC could have removed elements from the table.
18435  if (max_entries > table->NumberOfElements()) {
18436  max_entries = table->NumberOfElements();
18437  }
18438 
18439  {
18440  DisallowHeapAllocation no_gc;
18441  ReadOnlyRoots roots = ReadOnlyRoots(isolate);
18442  int count = 0;
18443  for (int i = 0;
18444  count / values_per_entry < max_entries && i < table->Capacity(); i++) {
18445  Object* key;
18446  if (table->ToKey(roots, i, &key)) {
18447  entries->set(count++, key);
18448  if (values_per_entry > 1) {
18449  Object* value = table->Lookup(handle(key, isolate));
18450  entries->set(count++, value);
18451  }
18452  }
18453  }
18454  DCHECK_EQ(max_entries * values_per_entry, count);
18455  }
18456  return isolate->factory()->NewJSArrayWithElements(entries);
18457 }
18458 
18459 // static
18460 MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
18461  Handle<JSReceiver> new_target, double tv) {
18462  Isolate* const isolate = constructor->GetIsolate();
18463  Handle<JSObject> result;
18464  ASSIGN_RETURN_ON_EXCEPTION(
18465  isolate, result,
18466  JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
18467  JSDate);
18468  if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
18469  tv = DoubleToInteger(tv) + 0.0;
18470  } else {
18471  tv = std::numeric_limits<double>::quiet_NaN();
18472  }
18473  Handle<Object> value = isolate->factory()->NewNumber(tv);
18474  Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
18475  return Handle<JSDate>::cast(result);
18476 }
18477 
18478 
18479 // static
18480 double JSDate::CurrentTimeValue(Isolate* isolate) {
18481  if (FLAG_log_internal_timer_events) LOG(isolate, CurrentTimeEvent());
18482 
18483  // According to ECMA-262, section 15.9.1, page 117, the precision of
18484  // the number in a Date object representing a particular instant in
18485  // time is milliseconds. Therefore, we floor the result of getting
18486  // the OS time.
18487  return Floor(V8::GetCurrentPlatform()->CurrentClockTimeMillis());
18488 }
18489 
18490 
18491 // static
18492 Object* JSDate::GetField(Object* object, Address smi_index) {
18493  Smi index(smi_index);
18494  return JSDate::cast(object)->DoGetField(
18495  static_cast<FieldIndex>(index->value()));
18496 }
18497 
18498 
18499 Object* JSDate::DoGetField(FieldIndex index) {
18500  DCHECK_NE(index, kDateValue);
18501 
18502  DateCache* date_cache = GetIsolate()->date_cache();
18503 
18504  if (index < kFirstUncachedField) {
18505  Object* stamp = cache_stamp();
18506  if (stamp != date_cache->stamp() && stamp->IsSmi()) {
18507  // Since the stamp is not NaN, the value is also not NaN.
18508  int64_t local_time_ms =
18509  date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
18510  SetCachedFields(local_time_ms, date_cache);
18511  }
18512  switch (index) {
18513  case kYear: return year();
18514  case kMonth: return month();
18515  case kDay: return day();
18516  case kWeekday: return weekday();
18517  case kHour: return hour();
18518  case kMinute: return min();
18519  case kSecond: return sec();
18520  default: UNREACHABLE();
18521  }
18522  }
18523 
18524  if (index >= kFirstUTCField) {
18525  return GetUTCField(index, value()->Number(), date_cache);
18526  }
18527 
18528  double time = value()->Number();
18529  if (std::isnan(time)) return GetReadOnlyRoots().nan_value();
18530 
18531  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
18532  int days = DateCache::DaysFromTime(local_time_ms);
18533 
18534  if (index == kDays) return Smi::FromInt(days);
18535 
18536  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18537  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
18538  DCHECK_EQ(index, kTimeInDay);
18539  return Smi::FromInt(time_in_day_ms);
18540 }
18541 
18542 
18543 Object* JSDate::GetUTCField(FieldIndex index,
18544  double value,
18545  DateCache* date_cache) {
18546  DCHECK_GE(index, kFirstUTCField);
18547 
18548  if (std::isnan(value)) return GetReadOnlyRoots().nan_value();
18549 
18550  int64_t time_ms = static_cast<int64_t>(value);
18551 
18552  if (index == kTimezoneOffset) {
18553  return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
18554  }
18555 
18556  int days = DateCache::DaysFromTime(time_ms);
18557 
18558  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
18559 
18560  if (index <= kDayUTC) {
18561  int year, month, day;
18562  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18563  if (index == kYearUTC) return Smi::FromInt(year);
18564  if (index == kMonthUTC) return Smi::FromInt(month);
18565  DCHECK_EQ(index, kDayUTC);
18566  return Smi::FromInt(day);
18567  }
18568 
18569  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
18570  switch (index) {
18571  case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
18572  case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
18573  case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
18574  case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
18575  case kDaysUTC: return Smi::FromInt(days);
18576  case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
18577  default: UNREACHABLE();
18578  }
18579 
18580  UNREACHABLE();
18581 }
18582 
18583 
18584 // static
18585 Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
18586  Isolate* const isolate = date->GetIsolate();
18587  Handle<Object> value = isolate->factory()->NewNumber(v);
18588  bool value_is_nan = std::isnan(v);
18589  date->SetValue(*value, value_is_nan);
18590  return value;
18591 }
18592 
18593 
18594 void JSDate::SetValue(Object* value, bool is_value_nan) {
18595  set_value(value);
18596  if (is_value_nan) {
18597  HeapNumber* nan = GetReadOnlyRoots().nan_value();
18598  set_cache_stamp(nan, SKIP_WRITE_BARRIER);
18599  set_year(nan, SKIP_WRITE_BARRIER);
18600  set_month(nan, SKIP_WRITE_BARRIER);
18601  set_day(nan, SKIP_WRITE_BARRIER);
18602  set_hour(nan, SKIP_WRITE_BARRIER);
18603  set_min(nan, SKIP_WRITE_BARRIER);
18604  set_sec(nan, SKIP_WRITE_BARRIER);
18605  set_weekday(nan, SKIP_WRITE_BARRIER);
18606  } else {
18607  set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
18608  }
18609 }
18610 
18611 
18612 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
18613  int days = DateCache::DaysFromTime(local_time_ms);
18614  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18615  int year, month, day;
18616  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18617  int weekday = date_cache->Weekday(days);
18618  int hour = time_in_day_ms / (60 * 60 * 1000);
18619  int min = (time_in_day_ms / (60 * 1000)) % 60;
18620  int sec = (time_in_day_ms / 1000) % 60;
18621  set_cache_stamp(date_cache->stamp());
18622  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
18623  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
18624  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
18625  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
18626  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
18627  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
18628  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
18629 }
18630 
18631 int JSMessageObject::GetLineNumber() const {
18632  if (start_position() == -1) return Message::kNoLineNumberInfo;
18633 
18634  Handle<Script> the_script(script(), GetIsolate());
18635 
18636  Script::PositionInfo info;
18637  const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18638  if (!Script::GetPositionInfo(the_script, start_position(), &info,
18639  offset_flag)) {
18640  return Message::kNoLineNumberInfo;
18641  }
18642 
18643  return info.line + 1;
18644 }
18645 
18646 int JSMessageObject::GetColumnNumber() const {
18647  if (start_position() == -1) return -1;
18648 
18649  Handle<Script> the_script(script(), GetIsolate());
18650 
18651  Script::PositionInfo info;
18652  const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18653  if (!Script::GetPositionInfo(the_script, start_position(), &info,
18654  offset_flag)) {
18655  return -1;
18656  }
18657 
18658  return info.column; // Note: No '+1' in contrast to GetLineNumber.
18659 }
18660 
18661 Handle<String> JSMessageObject::GetSourceLine() const {
18662  Isolate* isolate = GetIsolate();
18663  Handle<Script> the_script(script(), isolate);
18664 
18665  if (the_script->type() == Script::TYPE_WASM) {
18666  return isolate->factory()->empty_string();
18667  }
18668 
18669  Script::PositionInfo info;
18670  const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
18671  if (!Script::GetPositionInfo(the_script, start_position(), &info,
18672  offset_flag)) {
18673  return isolate->factory()->empty_string();
18674  }
18675 
18676  Handle<String> src = handle(String::cast(the_script->source()), isolate);
18677  return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
18678 }
18679 
18680 Handle<PropertyCell> PropertyCell::InvalidateEntry(
18681  Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry) {
18682  // Swap with a copy.
18683  Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
18684  Handle<Name> name(cell->name(), isolate);
18685  Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(name);
18686  new_cell->set_value(cell->value());
18687  dictionary->ValueAtPut(entry, *new_cell);
18688  bool is_the_hole = cell->value()->IsTheHole(isolate);
18689  // Cell is officially mutable henceforth.
18690  PropertyDetails details = cell->property_details();
18691  details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
18692  : PropertyCellType::kMutable);
18693  new_cell->set_property_details(details);
18694  // Old cell is ready for invalidation.
18695  if (is_the_hole) {
18696  cell->set_value(ReadOnlyRoots(isolate).undefined_value());
18697  } else {
18698  cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
18699  }
18700  details = details.set_cell_type(PropertyCellType::kInvalidated);
18701  cell->set_property_details(details);
18702  cell->dependent_code()->DeoptimizeDependentCodeGroup(
18703  isolate, DependentCode::kPropertyCellChangedGroup);
18704  return new_cell;
18705 }
18706 
18707 
18708 PropertyCellConstantType PropertyCell::GetConstantType() {
18709  if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
18710  return PropertyCellConstantType::kStableMap;
18711 }
18712 
18713 
18714 static bool RemainsConstantType(Handle<PropertyCell> cell,
18715  Handle<Object> value) {
18716  // TODO(dcarney): double->smi and smi->double transition from kConstant
18717  if (cell->value()->IsSmi() && value->IsSmi()) {
18718  return true;
18719  } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
18720  return HeapObject::cast(cell->value())->map() ==
18721  HeapObject::cast(*value)->map() &&
18722  HeapObject::cast(*value)->map()->is_stable();
18723  }
18724  return false;
18725 }
18726 
18727 PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
18728  Handle<PropertyCell> cell,
18729  Handle<Object> value,
18730  PropertyDetails details) {
18731  PropertyCellType type = details.cell_type();
18732  DCHECK(!value->IsTheHole(isolate));
18733  if (cell->value()->IsTheHole(isolate)) {
18734  switch (type) {
18735  // Only allow a cell to transition once into constant state.
18736  case PropertyCellType::kUninitialized:
18737  if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
18738  return PropertyCellType::kConstant;
18739  case PropertyCellType::kInvalidated:
18740  return PropertyCellType::kMutable;
18741  default:
18742  UNREACHABLE();
18743  }
18744  }
18745  switch (type) {
18746  case PropertyCellType::kUndefined:
18747  return PropertyCellType::kConstant;
18748  case PropertyCellType::kConstant:
18749  if (*value == cell->value()) return PropertyCellType::kConstant;
18750  V8_FALLTHROUGH;
18751  case PropertyCellType::kConstantType:
18752  if (RemainsConstantType(cell, value)) {
18753  return PropertyCellType::kConstantType;
18754  }
18755  V8_FALLTHROUGH;
18756  case PropertyCellType::kMutable:
18757  return PropertyCellType::kMutable;
18758  }
18759  UNREACHABLE();
18760 }
18761 
18762 Handle<PropertyCell> PropertyCell::PrepareForValue(
18763  Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
18764  Handle<Object> value, PropertyDetails details) {
18765  DCHECK(!value->IsTheHole(isolate));
18766  Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
18767  const PropertyDetails original_details = cell->property_details();
18768  // Data accesses could be cached in ics or optimized code.
18769  bool invalidate =
18770  (original_details.kind() == kData && details.kind() == kAccessor) ||
18771  (!original_details.IsReadOnly() && details.IsReadOnly());
18772  int index;
18773  PropertyCellType old_type = original_details.cell_type();
18774  // Preserve the enumeration index unless the property was deleted or never
18775  // initialized.
18776  if (cell->value()->IsTheHole(isolate)) {
18777  index = dictionary->NextEnumerationIndex();
18778  dictionary->SetNextEnumerationIndex(index + 1);
18779  } else {
18780  index = original_details.dictionary_index();
18781  }
18782  DCHECK_LT(0, index);
18783  details = details.set_index(index);
18784 
18785  PropertyCellType new_type =
18786  UpdatedType(isolate, cell, value, original_details);
18787  if (invalidate) {
18788  cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
18789  }
18790 
18791  // Install new property details.
18792  details = details.set_cell_type(new_type);
18793  cell->set_property_details(details);
18794 
18795  if (new_type == PropertyCellType::kConstant ||
18796  new_type == PropertyCellType::kConstantType) {
18797  // Store the value now to ensure that the cell contains the constant or
18798  // type information. Otherwise subsequent store operation will turn
18799  // the cell to mutable.
18800  cell->set_value(*value);
18801  }
18802 
18803  // Deopt when transitioning from a constant type.
18804  if (!invalidate && (old_type != new_type ||
18805  original_details.IsReadOnly() != details.IsReadOnly())) {
18806  cell->dependent_code()->DeoptimizeDependentCodeGroup(
18807  isolate, DependentCode::kPropertyCellChangedGroup);
18808  }
18809  return cell;
18810 }
18811 
18812 
18813 // static
18814 void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
18815  Handle<PropertyCell> cell,
18816  Handle<Object> new_value) {
18817  if (cell->value() != *new_value) {
18818  cell->set_value(*new_value);
18819  cell->dependent_code()->DeoptimizeDependentCodeGroup(
18820  isolate, DependentCode::kPropertyCellChangedGroup);
18821  }
18822 }
18823 
18824 int JSGeneratorObject::source_position() const {
18825  CHECK(is_suspended());
18826  DCHECK(function()->shared()->HasBytecodeArray());
18827 
18828  int code_offset = Smi::ToInt(input_or_debug_pos());
18829 
18830  // The stored bytecode offset is relative to a different base than what
18831  // is used in the source position table, hence the subtraction.
18832  code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
18833  AbstractCode code =
18834  AbstractCode::cast(function()->shared()->GetBytecodeArray());
18835  return code->SourcePosition(code_offset);
18836 }
18837 
18838 // static
18839 AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
18840  Handle<JSObject> receiver) {
18841  DisallowHeapAllocation no_gc;
18842  DCHECK(receiver->map()->is_access_check_needed());
18843  Object* maybe_constructor = receiver->map()->GetConstructor();
18844  if (maybe_constructor->IsFunctionTemplateInfo()) {
18845  Object* data_obj =
18846  FunctionTemplateInfo::cast(maybe_constructor)->GetAccessCheckInfo();
18847  if (data_obj->IsUndefined(isolate)) return nullptr;
18848  return AccessCheckInfo::cast(data_obj);
18849  }
18850  // Might happen for a detached context.
18851  if (!maybe_constructor->IsJSFunction()) return nullptr;
18852  JSFunction* constructor = JSFunction::cast(maybe_constructor);
18853  // Might happen for the debug context.
18854  if (!constructor->shared()->IsApiFunction()) return nullptr;
18855 
18856  Object* data_obj =
18857  constructor->shared()->get_api_func_data()->GetAccessCheckInfo();
18858  if (data_obj->IsUndefined(isolate)) return nullptr;
18859 
18860  return AccessCheckInfo::cast(data_obj);
18861 }
18862 
18863 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
18864  for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
18865  PrototypeIterator::END_AT_NULL);
18866  !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
18867  if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
18868  }
18869  return false;
18870 }
18871 
18872 bool JSReceiver::HasComplexElements() {
18873  if (IsJSProxy()) return true;
18874  JSObject* this_object = JSObject::cast(this);
18875  if (this_object->HasIndexedInterceptor()) {
18876  return true;
18877  }
18878  if (!this_object->HasDictionaryElements()) return false;
18879  return this_object->element_dictionary()->HasComplexElements();
18880 }
18881 
18882 MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
18883  Isolate* isolate, Handle<Object> getter) {
18884  if (getter->IsFunctionTemplateInfo()) {
18885  Handle<FunctionTemplateInfo> fti =
18886  Handle<FunctionTemplateInfo>::cast(getter);
18887  // Check if the accessor uses a cached property.
18888  if (!fti->cached_property_name()->IsTheHole(isolate)) {
18889  return handle(Name::cast(fti->cached_property_name()), isolate);
18890  }
18891  }
18892  return MaybeHandle<Name>();
18893 }
18894 
18895 Address Smi::LexicographicCompare(Isolate* isolate, Smi x, Smi y) {
18896  DisallowHeapAllocation no_allocation;
18897  DisallowJavascriptExecution no_js(isolate);
18898 
18899  int x_value = Smi::ToInt(x);
18900  int y_value = Smi::ToInt(y);
18901 
18902  // If the integers are equal so are the string representations.
18903  if (x_value == y_value) return Smi::FromInt(0).ptr();
18904 
18905  // If one of the integers is zero the normal integer order is the
18906  // same as the lexicographic order of the string representations.
18907  if (x_value == 0 || y_value == 0) {
18908  return Smi::FromInt(x_value < y_value ? -1 : 1).ptr();
18909  }
18910 
18911  // If only one of the integers is negative the negative number is
18912  // smallest because the char code of '-' is less than the char code
18913  // of any digit. Otherwise, we make both values positive.
18914 
18915  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
18916  // architectures using 32-bit Smis.
18917  uint32_t x_scaled = x_value;
18918  uint32_t y_scaled = y_value;
18919  if (x_value < 0 || y_value < 0) {
18920  if (y_value >= 0) return Smi::FromInt(-1).ptr();
18921  if (x_value >= 0) return Smi::FromInt(1).ptr();
18922  x_scaled = -x_value;
18923  y_scaled = -y_value;
18924  }
18925 
18926  // clang-format off
18927  static const uint32_t kPowersOf10[] = {
18928  1, 10, 100, 1000,
18929  10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000,
18930  100 * 1000 * 1000, 1000 * 1000 * 1000};
18931  // clang-format on
18932 
18933  // If the integers have the same number of decimal digits they can be
18934  // compared directly as the numeric order is the same as the
18935  // lexicographic order. If one integer has fewer digits, it is scaled
18936  // by some power of 10 to have the same number of digits as the longer
18937  // integer. If the scaled integers are equal it means the shorter
18938  // integer comes first in the lexicographic order.
18939 
18940  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
18941  int x_log2 = 31 - base::bits::CountLeadingZeros(x_scaled);
18942  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
18943  x_log10 -= x_scaled < kPowersOf10[x_log10];
18944 
18945  int y_log2 = 31 - base::bits::CountLeadingZeros(y_scaled);
18946  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
18947  y_log10 -= y_scaled < kPowersOf10[y_log10];
18948 
18949  int tie = 0;
18950 
18951  if (x_log10 < y_log10) {
18952  // X has fewer digits. We would like to simply scale up X but that
18953  // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
18954  // be scaled up to 9_000_000_000. So we scale up by the next
18955  // smallest power and scale down Y to drop one digit. It is OK to
18956  // drop one digit from the longer integer since the final digit is
18957  // past the length of the shorter integer.
18958  x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
18959  y_scaled /= 10;
18960  tie = -1;
18961  } else if (y_log10 < x_log10) {
18962  y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
18963  x_scaled /= 10;
18964  tie = 1;
18965  }
18966 
18967  if (x_scaled < y_scaled) return Smi::FromInt(-1).ptr();
18968  if (x_scaled > y_scaled) return Smi::FromInt(1).ptr();
18969  return Smi::FromInt(tie).ptr();
18970 }
18971 
18972 // Force instantiation of template instances class.
18973 // Please note this list is compiler dependent.
18974 // Keep this at the end of this file
18975 
18976 template class HashTable<StringTable, StringTableShape>;
18977 
18978 template class HashTable<CompilationCacheTable, CompilationCacheShape>;
18979 
18980 template class HashTable<ObjectHashTable, ObjectHashTableShape>;
18981 
18982 template class HashTable<EphemeronHashTable, EphemeronHashTableShape>;
18983 
18984 template class ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>;
18985 
18986 template class ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
18987 
18988 template class Dictionary<NameDictionary, NameDictionaryShape>;
18989 
18990 template class Dictionary<GlobalDictionary, GlobalDictionaryShape>;
18991 
18992 template class EXPORT_TEMPLATE_DEFINE(
18993  V8_EXPORT_PRIVATE) HashTable<NumberDictionary, NumberDictionaryShape>;
18994 
18995 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
18996  Dictionary<NumberDictionary, NumberDictionaryShape>;
18997 
18998 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
18999  HashTable<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
19000 
19001 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
19002  Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
19003 
19004 template Handle<NameDictionary>
19005 BaseNameDictionary<NameDictionary, NameDictionaryShape>::New(
19006  Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
19007 
19008 template Handle<GlobalDictionary>
19009 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::New(
19010  Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
19011 
19012 template Handle<NameDictionary>
19013 HashTable<NameDictionary, NameDictionaryShape>::New(Isolate*, int,
19014  PretenureFlag,
19015  MinimumCapacity);
19016 
19017 template Handle<ObjectHashSet>
19018 HashTable<ObjectHashSet, ObjectHashSetShape>::New(Isolate*, int n,
19019  PretenureFlag,
19020  MinimumCapacity);
19021 
19022 template Handle<NameDictionary>
19023 HashTable<NameDictionary, NameDictionaryShape>::Shrink(Isolate* isolate,
19024  Handle<NameDictionary>,
19025  int additionalCapacity);
19026 
19027 template Handle<NameDictionary>
19028 BaseNameDictionary<NameDictionary, NameDictionaryShape>::Add(
19029  Isolate* isolate, Handle<NameDictionary>, Handle<Name>, Handle<Object>,
19030  PropertyDetails, int*);
19031 
19032 template Handle<GlobalDictionary>
19033 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::Add(
19034  Isolate* isolate, Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
19035  PropertyDetails, int*);
19036 
19037 template void HashTable<GlobalDictionary, GlobalDictionaryShape>::Rehash(
19038  Isolate* isolate);
19039 
19040 template Handle<NameDictionary>
19041 BaseNameDictionary<NameDictionary, NameDictionaryShape>::EnsureCapacity(
19042  Isolate* isolate, Handle<NameDictionary>, int);
19043 
19044 template void
19045 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CopyEnumKeysTo(
19046  Isolate* isolate, Handle<GlobalDictionary> dictionary,
19047  Handle<FixedArray> storage, KeyCollectionMode mode,
19048  KeyAccumulator* accumulator);
19049 
19050 template void
19051 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CopyEnumKeysTo(
19052  Isolate* isolate, Handle<NameDictionary> dictionary,
19053  Handle<FixedArray> storage, KeyCollectionMode mode,
19054  KeyAccumulator* accumulator);
19055 
19056 template Handle<FixedArray>
19057 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::IterationIndices(
19058  Isolate* isolate, Handle<GlobalDictionary> dictionary);
19059 template void
19060 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CollectKeysTo(
19061  Handle<GlobalDictionary> dictionary, KeyAccumulator* keys);
19062 
19063 template Handle<FixedArray>
19064 BaseNameDictionary<NameDictionary, NameDictionaryShape>::IterationIndices(
19065  Isolate* isolate, Handle<NameDictionary> dictionary);
19066 template void
19067 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CollectKeysTo(
19068  Handle<NameDictionary> dictionary, KeyAccumulator* keys);
19069 
19070 void JSWeakFactory::Cleanup(Handle<JSWeakFactory> weak_factory,
19071  Isolate* isolate) {
19072  // It's possible that the cleared_cells list is empty, since
19073  // WeakCell.clear() was called on all its elements before this task ran. In
19074  // that case, don't call the cleanup function.
19075  if (!weak_factory->cleared_cells()->IsUndefined(isolate)) {
19076  // Construct the iterator.
19077  Handle<JSWeakFactoryCleanupIterator> iterator;
19078  {
19079  Handle<Map> cleanup_iterator_map(
19080  isolate->native_context()->js_weak_factory_cleanup_iterator_map(),
19081  isolate);
19082  iterator = Handle<JSWeakFactoryCleanupIterator>::cast(
19083  isolate->factory()->NewJSObjectFromMap(
19084  cleanup_iterator_map, NOT_TENURED,
19085  Handle<AllocationSite>::null()));
19086  iterator->set_factory(*weak_factory);
19087  }
19088  Handle<Object> cleanup(weak_factory->cleanup(), isolate);
19089 
19090  v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
19091  v8::Local<v8::Value> result;
19092  MaybeHandle<Object> exception;
19093  Handle<Object> args[] = {iterator};
19094  bool has_pending_exception = !ToLocal<Value>(
19095  Execution::TryCall(
19096  isolate, cleanup,
19097  handle(ReadOnlyRoots(isolate).undefined_value(), isolate), 1, args,
19098  Execution::MessageHandling::kReport, &exception,
19099  Execution::Target::kCallable),
19100  &result);
19101  // TODO(marja): (spec): What if there's an exception?
19102  USE(has_pending_exception);
19103 
19104  // TODO(marja): (spec): Should the iterator be invalidated after the
19105  // function returns?
19106  }
19107 }
19108 
19109 } // namespace internal
19110 } // namespace v8
IntegrityLevel
Definition: v8.h:3234
virtual const uint16_t * data() const =0
virtual bool IsCacheable() const
Definition: v8.h:2648
KeyCollectionMode
Definition: v8.h:3217
Definition: v8.h:85
virtual const char * data() const =0
Definition: libplatform.h:13
PromiseState
Definition: v8.h:4104
PropertyFilter
Definition: v8.h:3185
Definition: v8.h:3704
virtual size_t length() const =0