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 <sstream>
10
11#include "src/objects-inl.h"
12
13#include "src/accessors.h"
14#include "src/allocation-site-scopes.h"
15#include "src/api-arguments-inl.h"
16#include "src/api-natives.h"
17#include "src/api.h"
18#include "src/base/bits.h"
19#include "src/base/utils/random-number-generator.h"
20#include "src/bootstrapper.h"
21#include "src/code-stubs.h"
22#include "src/codegen.h"
23#include "src/compilation-dependencies.h"
24#include "src/compiler.h"
25#include "src/counters-inl.h"
26#include "src/counters.h"
27#include "src/date.h"
28#include "src/debug/debug.h"
29#include "src/deoptimizer.h"
30#include "src/elements.h"
31#include "src/execution.h"
32#include "src/field-index-inl.h"
33#include "src/field-index.h"
34#include "src/field-type.h"
35#include "src/frames-inl.h"
36#include "src/full-codegen/full-codegen.h"
37#include "src/ic/ic.h"
38#include "src/identity-map.h"
39#include "src/interpreter/bytecode-array-iterator.h"
40#include "src/interpreter/interpreter.h"
41#include "src/interpreter/source-position-table.h"
42#include "src/isolate-inl.h"
43#include "src/keys.h"
44#include "src/list.h"
45#include "src/log.h"
46#include "src/lookup.h"
47#include "src/macro-assembler.h"
48#include "src/messages.h"
49#include "src/objects-body-descriptors-inl.h"
50#include "src/property-descriptor.h"
51#include "src/prototype.h"
52#include "src/regexp/jsregexp.h"
53#include "src/safepoint-table.h"
54#include "src/string-builder.h"
55#include "src/string-search.h"
56#include "src/string-stream.h"
57#include "src/utils.h"
58#include "src/zone.h"
59
60#ifdef ENABLE_DISASSEMBLER
61#include "src/disasm.h"
62#include "src/disassembler.h"
63#endif
64
65namespace v8 {
66namespace internal {
67
68std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
69  switch (instance_type) {
70#define WRITE_TYPE(TYPE) \
71  case TYPE:             \
72    return os << #TYPE;
73    INSTANCE_TYPE_LIST(WRITE_TYPE)
74#undef WRITE_TYPE
75  }
76  UNREACHABLE();
77  return os << "UNKNOWN";  // Keep the compiler happy.
78}
79
80Handle<FieldType> Object::OptimalType(Isolate* isolate,
81                                      Representation representation) {
82  if (representation.IsNone()) return FieldType::None(isolate);
83  if (FLAG_track_field_types) {
84    if (representation.IsHeapObject() && IsHeapObject()) {
85      // We can track only JavaScript objects with stable maps.
86      Handle<Map> map(HeapObject::cast(this)->map(), isolate);
87      if (map->is_stable() && map->IsJSReceiverMap()) {
88        return FieldType::Class(map, isolate);
89      }
90    }
91  }
92  return FieldType::Any(isolate);
93}
94
95
96MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
97                                         Handle<Object> object,
98                                         Handle<Context> native_context) {
99  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
100  Handle<JSFunction> constructor;
101  if (object->IsSmi()) {
102    constructor = handle(native_context->number_function(), isolate);
103  } else {
104    int constructor_function_index =
105        Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
106    if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
107      THROW_NEW_ERROR(isolate,
108                      NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
109                      JSReceiver);
110    }
111    constructor = handle(
112        JSFunction::cast(native_context->get(constructor_function_index)),
113        isolate);
114  }
115  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
116  Handle<JSValue>::cast(result)->set_value(*object);
117  return result;
118}
119
120// ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
121// static
122MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
123                                                Handle<Object> object) {
124  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
125  if (*object == isolate->heap()->null_value() ||
126      object->IsUndefined(isolate)) {
127    return isolate->global_proxy();
128  }
129  return Object::ToObject(isolate, object);
130}
131
132// static
133MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
134  while (true) {
135    if (input->IsNumber()) {
136      return input;
137    }
138    if (input->IsString()) {
139      return String::ToNumber(Handle<String>::cast(input));
140    }
141    if (input->IsOddball()) {
142      return Oddball::ToNumber(Handle<Oddball>::cast(input));
143    }
144    Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
145    if (input->IsSymbol()) {
146      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
147                      Object);
148    }
149    if (input->IsSimd128Value()) {
150      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber),
151                      Object);
152    }
153    ASSIGN_RETURN_ON_EXCEPTION(
154        isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
155                                                ToPrimitiveHint::kNumber),
156        Object);
157  }
158}
159
160
161// static
162MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
163  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
164  return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
165}
166
167
168// static
169MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
170  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
171  return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
172}
173
174
175// static
176MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
177  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
178  return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
179}
180
181
182// static
183MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
184                                        Handle<Object> input) {
185  ASSIGN_RETURN_ON_EXCEPTION(
186      isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
187      Name);
188  if (input->IsName()) return Handle<Name>::cast(input);
189  return ToString(isolate, input);
190}
191
192// static
193MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
194  while (true) {
195    if (input->IsString()) {
196      return Handle<String>::cast(input);
197    }
198    if (input->IsOddball()) {
199      return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
200    }
201    if (input->IsNumber()) {
202      return isolate->factory()->NumberToString(input);
203    }
204    if (input->IsSymbol()) {
205      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
206                      String);
207    }
208    if (input->IsSimd128Value()) {
209      return Simd128Value::ToString(Handle<Simd128Value>::cast(input));
210    }
211    ASSIGN_RETURN_ON_EXCEPTION(
212        isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
213                                                ToPrimitiveHint::kString),
214        String);
215  }
216}
217
218
219// static
220MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
221  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
222  double len = DoubleToInteger(input->Number());
223  if (len <= 0.0) {
224    len = 0.0;
225  } else if (len >= kMaxSafeInteger) {
226    len = kMaxSafeInteger;
227  }
228  return isolate->factory()->NewNumber(len);
229}
230
231
232bool Object::BooleanValue() {
233  if (IsSmi()) return Smi::cast(this)->value() != 0;
234  DCHECK(IsHeapObject());
235  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
236  if (IsBoolean()) return IsTrue(isolate);
237  if (IsUndefined(isolate) || IsNull(isolate)) return false;
238  if (IsUndetectable()) return false;  // Undetectable object is false.
239  if (IsString()) return String::cast(this)->length() != 0;
240  if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
241  return true;
242}
243
244
245namespace {
246
247// TODO(bmeurer): Maybe we should introduce a marker interface Number,
248// where we put all these methods at some point?
249ComparisonResult NumberCompare(double x, double y) {
250  if (std::isnan(x) || std::isnan(y)) {
251    return ComparisonResult::kUndefined;
252  } else if (x < y) {
253    return ComparisonResult::kLessThan;
254  } else if (x > y) {
255    return ComparisonResult::kGreaterThan;
256  } else {
257    return ComparisonResult::kEqual;
258  }
259}
260
261
262bool NumberEquals(double x, double y) {
263  // Must check explicitly for NaN's on Windows, but -0 works fine.
264  if (std::isnan(x)) return false;
265  if (std::isnan(y)) return false;
266  return x == y;
267}
268
269
270bool NumberEquals(const Object* x, const Object* y) {
271  return NumberEquals(x->Number(), y->Number());
272}
273
274
275bool NumberEquals(Handle<Object> x, Handle<Object> y) {
276  return NumberEquals(*x, *y);
277}
278
279}  // namespace
280
281
282// static
283Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
284  // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
285  if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
286      !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
287    return Nothing<ComparisonResult>();
288  }
289  if (x->IsString() && y->IsString()) {
290    // ES6 section 7.2.11 Abstract Relational Comparison step 5.
291    return Just(
292        String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
293  }
294  // ES6 section 7.2.11 Abstract Relational Comparison step 6.
295  if (!Object::ToNumber(x).ToHandle(&x) || !Object::ToNumber(y).ToHandle(&y)) {
296    return Nothing<ComparisonResult>();
297  }
298  return Just(NumberCompare(x->Number(), y->Number()));
299}
300
301
302// static
303Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
304  // This is the generic version of Abstract Equality Comparison; a version in
305  // JavaScript land is available in the EqualStub and NotEqualStub. Whenever
306  // you change something functionality wise in here, remember to update the
307  // TurboFan code stubs as well.
308  while (true) {
309    if (x->IsNumber()) {
310      if (y->IsNumber()) {
311        return Just(NumberEquals(x, y));
312      } else if (y->IsBoolean()) {
313        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
314      } else if (y->IsString()) {
315        return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
316      } else if (y->IsJSReceiver()) {
317        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
318                 .ToHandle(&y)) {
319          return Nothing<bool>();
320        }
321      } else {
322        return Just(false);
323      }
324    } else if (x->IsString()) {
325      if (y->IsString()) {
326        return Just(
327            String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
328      } else if (y->IsNumber()) {
329        x = String::ToNumber(Handle<String>::cast(x));
330        return Just(NumberEquals(x, y));
331      } else if (y->IsBoolean()) {
332        x = String::ToNumber(Handle<String>::cast(x));
333        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
334      } else if (y->IsJSReceiver()) {
335        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
336                 .ToHandle(&y)) {
337          return Nothing<bool>();
338        }
339      } else {
340        return Just(false);
341      }
342    } else if (x->IsBoolean()) {
343      if (y->IsOddball()) {
344        return Just(x.is_identical_to(y));
345      } else if (y->IsNumber()) {
346        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
347      } else if (y->IsString()) {
348        y = String::ToNumber(Handle<String>::cast(y));
349        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
350      } else if (y->IsJSReceiver()) {
351        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
352                 .ToHandle(&y)) {
353          return Nothing<bool>();
354        }
355        x = Oddball::ToNumber(Handle<Oddball>::cast(x));
356      } else {
357        return Just(false);
358      }
359    } else if (x->IsSymbol()) {
360      if (y->IsSymbol()) {
361        return Just(x.is_identical_to(y));
362      } else if (y->IsJSReceiver()) {
363        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
364                 .ToHandle(&y)) {
365          return Nothing<bool>();
366        }
367      } else {
368        return Just(false);
369      }
370    } else if (x->IsSimd128Value()) {
371      if (y->IsSimd128Value()) {
372        return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
373                                         Handle<Simd128Value>::cast(y)));
374      } else if (y->IsJSReceiver()) {
375        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
376                 .ToHandle(&y)) {
377          return Nothing<bool>();
378        }
379      } else {
380        return Just(false);
381      }
382    } else if (x->IsJSReceiver()) {
383      if (y->IsJSReceiver()) {
384        return Just(x.is_identical_to(y));
385      } else if (y->IsUndetectable()) {
386        return Just(x->IsUndetectable());
387      } else if (y->IsBoolean()) {
388        y = Oddball::ToNumber(Handle<Oddball>::cast(y));
389      } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
390                      .ToHandle(&x)) {
391        return Nothing<bool>();
392      }
393    } else {
394      return Just(x->IsUndetectable() && y->IsUndetectable());
395    }
396  }
397}
398
399
400bool Object::StrictEquals(Object* that) {
401  if (this->IsNumber()) {
402    if (!that->IsNumber()) return false;
403    return NumberEquals(this, that);
404  } else if (this->IsString()) {
405    if (!that->IsString()) return false;
406    return String::cast(this)->Equals(String::cast(that));
407  } else if (this->IsSimd128Value()) {
408    if (!that->IsSimd128Value()) return false;
409    return Simd128Value::cast(this)->Equals(Simd128Value::cast(that));
410  }
411  return this == that;
412}
413
414
415// static
416Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
417  if (object->IsNumber()) return isolate->factory()->number_string();
418  if (object->IsOddball()) return handle(Oddball::cast(*object)->type_of());
419  if (object->IsUndetectable()) {
420    return isolate->factory()->undefined_string();
421  }
422  if (object->IsString()) return isolate->factory()->string_string();
423  if (object->IsSymbol()) return isolate->factory()->symbol_string();
424  if (object->IsString()) return isolate->factory()->string_string();
425#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
426  if (object->Is##Type()) return isolate->factory()->type##_string();
427  SIMD128_TYPES(SIMD128_TYPE)
428#undef SIMD128_TYPE
429  if (object->IsCallable()) return isolate->factory()->function_string();
430  return isolate->factory()->object_string();
431}
432
433
434// static
435MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
436                                     Handle<Object> rhs) {
437  if (!lhs->IsNumber() || !rhs->IsNumber()) {
438    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
439    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
440  }
441  return isolate->factory()->NewNumber(lhs->Number() * rhs->Number());
442}
443
444
445// static
446MaybeHandle<Object> Object::Divide(Isolate* isolate, Handle<Object> lhs,
447                                   Handle<Object> rhs) {
448  if (!lhs->IsNumber() || !rhs->IsNumber()) {
449    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
450    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
451  }
452  return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
453}
454
455
456// static
457MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
458                                    Handle<Object> rhs) {
459  if (!lhs->IsNumber() || !rhs->IsNumber()) {
460    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
461    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
462  }
463  return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
464}
465
466
467// static
468MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
469                                Handle<Object> rhs) {
470  if (lhs->IsNumber() && rhs->IsNumber()) {
471    return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
472  } else if (lhs->IsString() && rhs->IsString()) {
473    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
474                                             Handle<String>::cast(rhs));
475  }
476  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
477  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
478  if (lhs->IsString() || rhs->IsString()) {
479    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
480                               Object);
481    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
482                               Object);
483    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
484                                             Handle<String>::cast(rhs));
485  }
486  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
487  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
488  return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
489}
490
491
492// static
493MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
494                                     Handle<Object> rhs) {
495  if (!lhs->IsNumber() || !rhs->IsNumber()) {
496    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
497    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
498  }
499  return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
500}
501
502
503// static
504MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
505                                      Handle<Object> rhs) {
506  if (!lhs->IsNumber() || !rhs->IsNumber()) {
507    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
508    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
509  }
510  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
511                                              << (NumberToUint32(*rhs) & 0x1F));
512}
513
514
515// static
516MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
517                                       Handle<Object> rhs) {
518  if (!lhs->IsNumber() || !rhs->IsNumber()) {
519    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
520    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
521  }
522  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
523                                              (NumberToUint32(*rhs) & 0x1F));
524}
525
526
527// static
528MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
529                                              Handle<Object> lhs,
530                                              Handle<Object> rhs) {
531  if (!lhs->IsNumber() || !rhs->IsNumber()) {
532    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
533    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
534  }
535  return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
536                                               (NumberToUint32(*rhs) & 0x1F));
537}
538
539
540// static
541MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
542                                       Handle<Object> rhs) {
543  if (!lhs->IsNumber() || !rhs->IsNumber()) {
544    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
545    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
546  }
547  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
548                                              NumberToInt32(*rhs));
549}
550
551
552// static
553MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
554                                      Handle<Object> rhs) {
555  if (!lhs->IsNumber() || !rhs->IsNumber()) {
556    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
557    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
558  }
559  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
560                                              NumberToInt32(*rhs));
561}
562
563
564// static
565MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
566                                       Handle<Object> rhs) {
567  if (!lhs->IsNumber() || !rhs->IsNumber()) {
568    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
569    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
570  }
571  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
572                                              NumberToInt32(*rhs));
573}
574
575// static
576MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
577                                                Handle<Object> callable,
578                                                Handle<Object> object) {
579  // The {callable} must have a [[Call]] internal method.
580  if (!callable->IsCallable()) return isolate->factory()->false_value();
581
582  // Check if {callable} is a bound function, and if so retrieve its
583  // [[BoundTargetFunction]] and use that instead of {callable}.
584  if (callable->IsJSBoundFunction()) {
585    Handle<Object> bound_callable(
586        Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
587        isolate);
588    return Object::InstanceOf(isolate, object, bound_callable);
589  }
590
591  // If {object} is not a receiver, return false.
592  if (!object->IsJSReceiver()) return isolate->factory()->false_value();
593
594  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
595  Handle<Object> prototype;
596  ASSIGN_RETURN_ON_EXCEPTION(
597      isolate, prototype,
598      Object::GetProperty(callable, isolate->factory()->prototype_string()),
599      Object);
600  if (!prototype->IsJSReceiver()) {
601    THROW_NEW_ERROR(
602        isolate,
603        NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
604        Object);
605  }
606
607  // Return whether or not {prototype} is in the prototype chain of {object}.
608  Maybe<bool> result = JSReceiver::HasInPrototypeChain(
609      isolate, Handle<JSReceiver>::cast(object), prototype);
610  if (result.IsNothing()) return MaybeHandle<Object>();
611  return isolate->factory()->ToBoolean(result.FromJust());
612}
613
614// static
615MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
616                                       Handle<Object> callable) {
617  // The {callable} must be a receiver.
618  if (!callable->IsJSReceiver()) {
619    THROW_NEW_ERROR(isolate,
620                    NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
621                    Object);
622  }
623
624  // Lookup the @@hasInstance method on {callable}.
625  Handle<Object> inst_of_handler;
626  ASSIGN_RETURN_ON_EXCEPTION(
627      isolate, inst_of_handler,
628      JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
629                            isolate->factory()->has_instance_symbol()),
630      Object);
631  if (!inst_of_handler->IsUndefined(isolate)) {
632    // Call the {inst_of_handler} on the {callable}.
633    Handle<Object> result;
634    ASSIGN_RETURN_ON_EXCEPTION(
635        isolate, result,
636        Execution::Call(isolate, inst_of_handler, callable, 1, &object),
637        Object);
638    return isolate->factory()->ToBoolean(result->BooleanValue());
639  }
640
641  // The {callable} must have a [[Call]] internal method.
642  if (!callable->IsCallable()) {
643    THROW_NEW_ERROR(
644        isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
645        Object);
646  }
647
648  // Fall back to OrdinaryHasInstance with {callable} and {object}.
649  Handle<Object> result;
650  ASSIGN_RETURN_ON_EXCEPTION(
651      isolate, result,
652      JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
653  return result;
654}
655
656Maybe<bool> Object::IsArray(Handle<Object> object) {
657  if (object->IsJSArray()) return Just(true);
658  if (object->IsJSProxy()) {
659    Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
660    Isolate* isolate = proxy->GetIsolate();
661    if (proxy->IsRevoked()) {
662      isolate->Throw(*isolate->factory()->NewTypeError(
663          MessageTemplate::kProxyRevoked,
664          isolate->factory()->NewStringFromAsciiChecked("IsArray")));
665      return Nothing<bool>();
666    }
667    return Object::IsArray(handle(proxy->target(), isolate));
668  }
669  return Just(false);
670}
671
672
673// static
674MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
675                                      Handle<Name> name) {
676  Handle<Object> func;
677  Isolate* isolate = receiver->GetIsolate();
678  ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
679                             JSReceiver::GetProperty(receiver, name), Object);
680  if (func->IsNull(isolate) || func->IsUndefined(isolate)) {
681    return isolate->factory()->undefined_value();
682  }
683  if (!func->IsCallable()) {
684    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
685                                          func, name, receiver),
686                    Object);
687  }
688  return func;
689}
690
691
692// static
693MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
694    Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
695  // 1. ReturnIfAbrupt(object).
696  // 2. (default elementTypes -- not applicable.)
697  // 3. If Type(obj) is not Object, throw a TypeError exception.
698  if (!object->IsJSReceiver()) {
699    THROW_NEW_ERROR(isolate,
700                    NewTypeError(MessageTemplate::kCalledOnNonObject,
701                                 isolate->factory()->NewStringFromAsciiChecked(
702                                     "CreateListFromArrayLike")),
703                    FixedArray);
704  }
705  // 4. Let len be ? ToLength(? Get(obj, "length")).
706  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
707  Handle<Object> raw_length_number;
708  ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
709                             Object::GetLengthFromArrayLike(isolate, receiver),
710                             FixedArray);
711  uint32_t len;
712  if (!raw_length_number->ToUint32(&len) ||
713      len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
714    THROW_NEW_ERROR(isolate,
715                    NewRangeError(MessageTemplate::kInvalidArrayLength),
716                    FixedArray);
717  }
718  // 5. Let list be an empty List.
719  Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
720  // 6. Let index be 0.
721  // 7. Repeat while index < len:
722  for (uint32_t index = 0; index < len; ++index) {
723    // 7a. Let indexName be ToString(index).
724    // 7b. Let next be ? Get(obj, indexName).
725    Handle<Object> next;
726    ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
727                               JSReceiver::GetElement(isolate, receiver, index),
728                               FixedArray);
729    switch (element_types) {
730      case ElementTypes::kAll:
731        // Nothing to do.
732        break;
733      case ElementTypes::kStringAndSymbol: {
734        // 7c. If Type(next) is not an element of elementTypes, throw a
735        //     TypeError exception.
736        if (!next->IsName()) {
737          THROW_NEW_ERROR(isolate,
738                          NewTypeError(MessageTemplate::kNotPropertyName, next),
739                          FixedArray);
740        }
741        // 7d. Append next as the last element of list.
742        // Internalize on the fly so we can use pointer identity later.
743        next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
744        break;
745      }
746    }
747    list->set(index, *next);
748    // 7e. Set index to index + 1. (See loop header.)
749  }
750  // 8. Return list.
751  return list;
752}
753
754
755// static
756MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
757                                                   Handle<Object> object) {
758  Handle<Object> val;
759  Handle<Object> key = isolate->factory()->length_string();
760  ASSIGN_RETURN_ON_EXCEPTION(
761      isolate, val, Runtime::GetObjectProperty(isolate, object, key), Object);
762  return Object::ToLength(isolate, val);
763}
764
765// static
766Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
767  for (; it->IsFound(); it->Next()) {
768    switch (it->state()) {
769      case LookupIterator::NOT_FOUND:
770      case LookupIterator::TRANSITION:
771        UNREACHABLE();
772      case LookupIterator::JSPROXY:
773        return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
774                                    it->GetName());
775      case LookupIterator::INTERCEPTOR: {
776        Maybe<PropertyAttributes> result =
777            JSObject::GetPropertyAttributesWithInterceptor(it);
778        if (result.IsNothing()) return Nothing<bool>();
779        if (result.FromJust() != ABSENT) return Just(true);
780        break;
781      }
782      case LookupIterator::ACCESS_CHECK: {
783        if (it->HasAccess()) break;
784        Maybe<PropertyAttributes> result =
785            JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
786        if (result.IsNothing()) return Nothing<bool>();
787        return Just(result.FromJust() != ABSENT);
788      }
789      case LookupIterator::INTEGER_INDEXED_EXOTIC:
790        // TypedArray out-of-bounds access.
791        return Just(false);
792      case LookupIterator::ACCESSOR:
793      case LookupIterator::DATA:
794        return Just(true);
795    }
796  }
797  return Just(false);
798}
799
800
801// static
802MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
803  for (; it->IsFound(); it->Next()) {
804    switch (it->state()) {
805      case LookupIterator::NOT_FOUND:
806      case LookupIterator::TRANSITION:
807        UNREACHABLE();
808      case LookupIterator::JSPROXY: {
809        bool was_found;
810        MaybeHandle<Object> result =
811            JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
812                                 it->GetName(), it->GetReceiver(), &was_found);
813        if (!was_found) it->NotFound();
814        return result;
815      }
816      case LookupIterator::INTERCEPTOR: {
817        bool done;
818        Handle<Object> result;
819        ASSIGN_RETURN_ON_EXCEPTION(
820            it->isolate(), result,
821            JSObject::GetPropertyWithInterceptor(it, &done), Object);
822        if (done) return result;
823        break;
824      }
825      case LookupIterator::ACCESS_CHECK:
826        if (it->HasAccess()) break;
827        return JSObject::GetPropertyWithFailedAccessCheck(it);
828      case LookupIterator::ACCESSOR:
829        return GetPropertyWithAccessor(it);
830      case LookupIterator::INTEGER_INDEXED_EXOTIC:
831        return ReadAbsentProperty(it);
832      case LookupIterator::DATA:
833        return it->GetDataValue();
834    }
835  }
836  return ReadAbsentProperty(it);
837}
838
839
840// static
841MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
842                                         Handle<JSProxy> proxy,
843                                         Handle<Name> name,
844                                         Handle<Object> receiver,
845                                         bool* was_found) {
846  *was_found = true;
847  if (receiver->IsJSGlobalObject()) {
848    THROW_NEW_ERROR(
849        isolate,
850        NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
851        Object);
852  }
853
854  DCHECK(!name->IsPrivate());
855  STACK_CHECK(isolate, MaybeHandle<Object>());
856  Handle<Name> trap_name = isolate->factory()->get_string();
857  // 1. Assert: IsPropertyKey(P) is true.
858  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
859  Handle<Object> handler(proxy->handler(), isolate);
860  // 3. If handler is null, throw a TypeError exception.
861  // 4. Assert: Type(handler) is Object.
862  if (proxy->IsRevoked()) {
863    THROW_NEW_ERROR(isolate,
864                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
865                    Object);
866  }
867  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
868  Handle<JSReceiver> target(proxy->target(), isolate);
869  // 6. Let trap be ? GetMethod(handler, "get").
870  Handle<Object> trap;
871  ASSIGN_RETURN_ON_EXCEPTION(
872      isolate, trap,
873      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
874  // 7. If trap is undefined, then
875  if (trap->IsUndefined(isolate)) {
876    // 7.a Return target.[[Get]](P, Receiver).
877    LookupIterator it =
878        LookupIterator::PropertyOrElement(isolate, receiver, name, target);
879    MaybeHandle<Object> result = Object::GetProperty(&it);
880    *was_found = it.IsFound();
881    return result;
882  }
883  // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
884  Handle<Object> trap_result;
885  Handle<Object> args[] = {target, name, receiver};
886  ASSIGN_RETURN_ON_EXCEPTION(
887      isolate, trap_result,
888      Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
889  // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
890  PropertyDescriptor target_desc;
891  Maybe<bool> target_found =
892      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
893  MAYBE_RETURN_NULL(target_found);
894  // 10. If targetDesc is not undefined, then
895  if (target_found.FromJust()) {
896    // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
897    //       false and targetDesc.[[Writable]] is false, then
898    // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
899    //        throw a TypeError exception.
900    bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
901                        !target_desc.configurable() &&
902                        !target_desc.writable() &&
903                        !trap_result->SameValue(*target_desc.value());
904    if (inconsistent) {
905      THROW_NEW_ERROR(
906          isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
907                                name, target_desc.value(), trap_result),
908          Object);
909    }
910    // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
911    //       is false and targetDesc.[[Get]] is undefined, then
912    // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
913    inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
914                   !target_desc.configurable() &&
915                   target_desc.get()->IsUndefined(isolate) &&
916                   !trap_result->IsUndefined(isolate);
917    if (inconsistent) {
918      THROW_NEW_ERROR(
919          isolate,
920          NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
921                       trap_result),
922          Object);
923    }
924  }
925  // 11. Return trap_result
926  return trap_result;
927}
928
929
930Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
931  for (; it->IsFound(); it->Next()) {
932    switch (it->state()) {
933      case LookupIterator::INTERCEPTOR:
934      case LookupIterator::NOT_FOUND:
935      case LookupIterator::TRANSITION:
936        UNREACHABLE();
937      case LookupIterator::ACCESS_CHECK:
938        // Support calling this method without an active context, but refuse
939        // access to access-checked objects in that case.
940        if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
941      // Fall through.
942      case LookupIterator::JSPROXY:
943        it->NotFound();
944        return it->isolate()->factory()->undefined_value();
945      case LookupIterator::ACCESSOR:
946        // TODO(verwaest): For now this doesn't call into AccessorInfo, since
947        // clients don't need it. Update once relevant.
948        it->NotFound();
949        return it->isolate()->factory()->undefined_value();
950      case LookupIterator::INTEGER_INDEXED_EXOTIC:
951        return it->isolate()->factory()->undefined_value();
952      case LookupIterator::DATA:
953        return it->GetDataValue();
954    }
955  }
956  return it->isolate()->factory()->undefined_value();
957}
958
959
960bool Object::ToInt32(int32_t* value) {
961  if (IsSmi()) {
962    *value = Smi::cast(this)->value();
963    return true;
964  }
965  if (IsHeapNumber()) {
966    double num = HeapNumber::cast(this)->value();
967    if (FastI2D(FastD2I(num)) == num) {
968      *value = FastD2I(num);
969      return true;
970    }
971  }
972  return false;
973}
974
975Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
976    Isolate* isolate, Handle<FunctionTemplateInfo> info) {
977  Object* current_info = info->shared_function_info();
978  if (current_info->IsSharedFunctionInfo()) {
979    return handle(SharedFunctionInfo::cast(current_info), isolate);
980  }
981
982  Handle<Object> class_name(info->class_name(), isolate);
983  Handle<String> name = class_name->IsString()
984                            ? Handle<String>::cast(class_name)
985                            : isolate->factory()->empty_string();
986  Handle<Code> code;
987  if (info->call_code()->IsCallHandlerInfo() &&
988      CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
989    code = isolate->builtins()->HandleFastApiCall();
990  } else {
991    code = isolate->builtins()->HandleApiCall();
992  }
993  bool is_constructor = !info->remove_prototype();
994  Handle<SharedFunctionInfo> result =
995      isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
996  if (is_constructor) {
997    result->set_construct_stub(*isolate->builtins()->JSConstructStubApi());
998  }
999
1000  result->set_length(info->length());
1001  if (class_name->IsString()) result->set_instance_class_name(*class_name);
1002  result->set_api_func_data(*info);
1003  result->DontAdaptArguments();
1004  DCHECK(result->IsApiFunction());
1005
1006  info->set_shared_function_info(*result);
1007  return result;
1008}
1009
1010bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
1011  // There is a constraint on the object; check.
1012  if (!map->IsJSObjectMap()) return false;
1013  // Fetch the constructor function of the object.
1014  Object* cons_obj = map->GetConstructor();
1015  if (!cons_obj->IsJSFunction()) return false;
1016  JSFunction* fun = JSFunction::cast(cons_obj);
1017  // Iterate through the chain of inheriting function templates to
1018  // see if the required one occurs.
1019  for (Object* type = fun->shared()->function_data();
1020       type->IsFunctionTemplateInfo();
1021       type = FunctionTemplateInfo::cast(type)->parent_template()) {
1022    if (type == this) return true;
1023  }
1024  // Didn't find the required type in the inheritance chain.
1025  return false;
1026}
1027
1028
1029// static
1030MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
1031                                    Handle<JSReceiver> new_target,
1032                                    Handle<AllocationSite> site) {
1033  // If called through new, new.target can be:
1034  // - a subclass of constructor,
1035  // - a proxy wrapper around constructor, or
1036  // - the constructor itself.
1037  // If called through Reflect.construct, it's guaranteed to be a constructor.
1038  Isolate* const isolate = constructor->GetIsolate();
1039  DCHECK(constructor->IsConstructor());
1040  DCHECK(new_target->IsConstructor());
1041  DCHECK(!constructor->has_initial_map() ||
1042         constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
1043
1044  Handle<Map> initial_map;
1045  ASSIGN_RETURN_ON_EXCEPTION(
1046      isolate, initial_map,
1047      JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
1048  Handle<JSObject> result =
1049      isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
1050  isolate->counters()->constructed_objects()->Increment();
1051  isolate->counters()->constructed_objects_runtime()->Increment();
1052  return result;
1053}
1054
1055void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
1056  DCHECK(object->HasFastSmiOrObjectElements() ||
1057         object->HasFastStringWrapperElements());
1058  FixedArray* raw_elems = FixedArray::cast(object->elements());
1059  Heap* heap = object->GetHeap();
1060  if (raw_elems->map() != heap->fixed_cow_array_map()) return;
1061  Isolate* isolate = heap->isolate();
1062  Handle<FixedArray> elems(raw_elems, isolate);
1063  Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
1064      elems, isolate->factory()->fixed_array_map());
1065  object->set_elements(*writable_elems);
1066  isolate->counters()->cow_arrays_converted()->Increment();
1067}
1068
1069
1070// ES6 9.5.1
1071// static
1072MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1073  Isolate* isolate = proxy->GetIsolate();
1074  Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1075
1076  STACK_CHECK(isolate, MaybeHandle<Object>());
1077
1078  // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1079  // 2. If handler is null, throw a TypeError exception.
1080  // 3. Assert: Type(handler) is Object.
1081  // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1082  if (proxy->IsRevoked()) {
1083    THROW_NEW_ERROR(isolate,
1084                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1085                    Object);
1086  }
1087  Handle<JSReceiver> target(proxy->target(), isolate);
1088  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1089
1090  // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1091  Handle<Object> trap;
1092  ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
1093                             Object);
1094  // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1095  if (trap->IsUndefined(isolate)) {
1096    return JSReceiver::GetPrototype(isolate, target);
1097  }
1098  // 7. Let handlerProto be ? Call(trap, handler, «target»).
1099  Handle<Object> argv[] = {target};
1100  Handle<Object> handler_proto;
1101  ASSIGN_RETURN_ON_EXCEPTION(
1102      isolate, handler_proto,
1103      Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
1104  // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1105  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1106    THROW_NEW_ERROR(isolate,
1107                    NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1108                    Object);
1109  }
1110  // 9. Let extensibleTarget be ? IsExtensible(target).
1111  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1112  MAYBE_RETURN_NULL(is_extensible);
1113  // 10. If extensibleTarget is true, return handlerProto.
1114  if (is_extensible.FromJust()) return handler_proto;
1115  // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1116  Handle<Object> target_proto;
1117  ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1118                             JSReceiver::GetPrototype(isolate, target), Object);
1119  // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1120  if (!handler_proto->SameValue(*target_proto)) {
1121    THROW_NEW_ERROR(
1122        isolate,
1123        NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1124        Object);
1125  }
1126  // 13. Return handlerProto.
1127  return handler_proto;
1128}
1129
1130MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1131  Isolate* isolate = it->isolate();
1132  Handle<Object> structure = it->GetAccessors();
1133  Handle<Object> receiver = it->GetReceiver();
1134
1135  // We should never get here to initialize a const with the hole value since a
1136  // const declaration would conflict with the getter.
1137  DCHECK(!structure->IsForeign());
1138
1139  // API style callbacks.
1140  if (structure->IsAccessorInfo()) {
1141    Handle<JSObject> holder = it->GetHolder<JSObject>();
1142    Handle<Name> name = it->GetName();
1143    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1144    if (!info->IsCompatibleReceiver(*receiver)) {
1145      THROW_NEW_ERROR(isolate,
1146                      NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1147                                   name, receiver),
1148                      Object);
1149    }
1150
1151    v8::AccessorNameGetterCallback call_fun =
1152        v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
1153    if (call_fun == nullptr) return isolate->factory()->undefined_value();
1154
1155    if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1156      ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1157                                 Object::ConvertReceiver(isolate, receiver),
1158                                 Object);
1159    }
1160
1161    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1162                                   Object::DONT_THROW);
1163    Handle<Object> result = args.Call(call_fun, name);
1164    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1165    if (result.is_null()) return ReadAbsentProperty(isolate, receiver, name);
1166    // Rebox handle before return.
1167    return handle(*result, isolate);
1168  }
1169
1170  // Regular accessor.
1171  Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1172  if (getter->IsFunctionTemplateInfo()) {
1173    return Builtins::InvokeApiFunction(
1174        isolate, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1175        nullptr);
1176  } else if (getter->IsCallable()) {
1177    // TODO(rossberg): nicer would be to cast to some JSCallable here...
1178    return Object::GetPropertyWithDefinedGetter(
1179        receiver, Handle<JSReceiver>::cast(getter));
1180  }
1181  // Getter is not a function.
1182  return ReadAbsentProperty(isolate, receiver, it->GetName());
1183}
1184
1185// static
1186Address AccessorInfo::redirect(Isolate* isolate, Address address,
1187                               AccessorComponent component) {
1188  ApiFunction fun(address);
1189  DCHECK_EQ(ACCESSOR_GETTER, component);
1190  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1191  return ExternalReference(&fun, type, isolate).address();
1192}
1193
1194Address AccessorInfo::redirected_getter() const {
1195  Address accessor = v8::ToCData<Address>(getter());
1196  if (accessor == nullptr) return nullptr;
1197  return redirect(GetIsolate(), accessor, ACCESSOR_GETTER);
1198}
1199
1200bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
1201                                           Handle<AccessorInfo> info,
1202                                           Handle<Map> map) {
1203  if (!info->HasExpectedReceiverType()) return true;
1204  if (!map->IsJSObjectMap()) return false;
1205  return FunctionTemplateInfo::cast(info->expected_receiver_type())
1206      ->IsTemplateFor(*map);
1207}
1208
1209Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
1210                                            Handle<Object> value,
1211                                            ShouldThrow should_throw) {
1212  Isolate* isolate = it->isolate();
1213  Handle<Object> structure = it->GetAccessors();
1214  Handle<Object> receiver = it->GetReceiver();
1215
1216  // We should never get here to initialize a const with the hole value since a
1217  // const declaration would conflict with the setter.
1218  DCHECK(!structure->IsForeign());
1219
1220  // API style callbacks.
1221  if (structure->IsAccessorInfo()) {
1222    Handle<JSObject> holder = it->GetHolder<JSObject>();
1223    Handle<Name> name = it->GetName();
1224    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1225    if (!info->IsCompatibleReceiver(*receiver)) {
1226      isolate->Throw(*isolate->factory()->NewTypeError(
1227          MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1228      return Nothing<bool>();
1229    }
1230
1231    v8::AccessorNameSetterCallback call_fun =
1232        v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
1233    // TODO(verwaest): We should not get here anymore once all AccessorInfos are
1234    // marked as special_data_property. They cannot both be writable and not
1235    // have a setter.
1236    if (call_fun == nullptr) return Just(true);
1237
1238    if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1239      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1240          isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1241          Nothing<bool>());
1242    }
1243
1244    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1245                                   should_throw);
1246    args.Call(call_fun, name, value);
1247    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1248    return Just(true);
1249  }
1250
1251  // Regular accessor.
1252  Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1253  if (setter->IsFunctionTemplateInfo()) {
1254    Handle<Object> argv[] = {value};
1255    RETURN_ON_EXCEPTION_VALUE(
1256        isolate, Builtins::InvokeApiFunction(
1257                     isolate, Handle<FunctionTemplateInfo>::cast(setter),
1258                     receiver, arraysize(argv), argv),
1259        Nothing<bool>());
1260    return Just(true);
1261  } else if (setter->IsCallable()) {
1262    // TODO(rossberg): nicer would be to cast to some JSCallable here...
1263    return SetPropertyWithDefinedSetter(
1264        receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
1265  }
1266
1267  RETURN_FAILURE(isolate, should_throw,
1268                 NewTypeError(MessageTemplate::kNoSetterInCallback,
1269                              it->GetName(), it->GetHolder<JSObject>()));
1270}
1271
1272
1273MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1274    Handle<Object> receiver,
1275    Handle<JSReceiver> getter) {
1276  Isolate* isolate = getter->GetIsolate();
1277
1278  // Platforms with simulators like arm/arm64 expose a funny issue. If the
1279  // simulator has a separate JS stack pointer from the C++ stack pointer, it
1280  // can miss C++ stack overflows in the stack guard at the start of JavaScript
1281  // functions. It would be very expensive to check the C++ stack pointer at
1282  // that location. The best solution seems to be to break the impasse by
1283  // adding checks at possible recursion points. What's more, we don't put
1284  // this stack check behind the USE_SIMULATOR define in order to keep
1285  // behavior the same between hardware and simulators.
1286  StackLimitCheck check(isolate);
1287  if (check.JsHasOverflowed()) {
1288    isolate->StackOverflow();
1289    return MaybeHandle<Object>();
1290  }
1291
1292  return Execution::Call(isolate, getter, receiver, 0, NULL);
1293}
1294
1295
1296Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
1297                                                 Handle<JSReceiver> setter,
1298                                                 Handle<Object> value,
1299                                                 ShouldThrow should_throw) {
1300  Isolate* isolate = setter->GetIsolate();
1301
1302  Handle<Object> argv[] = { value };
1303  RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1304                                                     arraysize(argv), argv),
1305                            Nothing<bool>());
1306  return Just(true);
1307}
1308
1309
1310// static
1311bool JSObject::AllCanRead(LookupIterator* it) {
1312  // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
1313  // which have already been checked.
1314  DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
1315         it->state() == LookupIterator::INTERCEPTOR);
1316  for (it->Next(); it->IsFound(); it->Next()) {
1317    if (it->state() == LookupIterator::ACCESSOR) {
1318      auto accessors = it->GetAccessors();
1319      if (accessors->IsAccessorInfo()) {
1320        if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
1321      }
1322    } else if (it->state() == LookupIterator::INTERCEPTOR) {
1323      if (it->GetInterceptor()->all_can_read()) return true;
1324    } else if (it->state() == LookupIterator::JSPROXY) {
1325      // Stop lookupiterating. And no, AllCanNotRead.
1326      return false;
1327    }
1328  }
1329  return false;
1330}
1331
1332namespace {
1333
1334MaybeHandle<Object> GetPropertyWithInterceptorInternal(
1335    LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
1336  *done = false;
1337  Isolate* isolate = it->isolate();
1338  // Make sure that the top context does not change when doing callbacks or
1339  // interceptor calls.
1340  AssertNoContextChange ncc(isolate);
1341
1342  if (interceptor->getter()->IsUndefined(isolate)) {
1343    return isolate->factory()->undefined_value();
1344  }
1345
1346  Handle<JSObject> holder = it->GetHolder<JSObject>();
1347  Handle<Object> result;
1348  Handle<Object> receiver = it->GetReceiver();
1349  if (!receiver->IsJSReceiver()) {
1350    ASSIGN_RETURN_ON_EXCEPTION(
1351        isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
1352  }
1353  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1354                                 *holder, Object::DONT_THROW);
1355
1356  if (it->IsElement()) {
1357    uint32_t index = it->index();
1358    v8::IndexedPropertyGetterCallback getter =
1359        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
1360    result = args.Call(getter, index);
1361  } else {
1362    Handle<Name> name = it->name();
1363    DCHECK(!name->IsPrivate());
1364
1365    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
1366      return isolate->factory()->undefined_value();
1367    }
1368
1369    v8::GenericNamedPropertyGetterCallback getter =
1370        v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
1371            interceptor->getter());
1372    result = args.Call(getter, name);
1373  }
1374
1375  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1376  if (result.is_null()) return isolate->factory()->undefined_value();
1377  *done = true;
1378  // Rebox handle before return
1379  return handle(*result, isolate);
1380}
1381
1382Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
1383    LookupIterator* it, Handle<InterceptorInfo> interceptor) {
1384  Isolate* isolate = it->isolate();
1385  // Make sure that the top context does not change when doing
1386  // callbacks or interceptor calls.
1387  AssertNoContextChange ncc(isolate);
1388  HandleScope scope(isolate);
1389
1390  Handle<JSObject> holder = it->GetHolder<JSObject>();
1391  if (!it->IsElement() && it->name()->IsSymbol() &&
1392      !interceptor->can_intercept_symbols()) {
1393    return Just(ABSENT);
1394  }
1395  Handle<Object> receiver = it->GetReceiver();
1396  if (!receiver->IsJSReceiver()) {
1397    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1398                                     Object::ConvertReceiver(isolate, receiver),
1399                                     Nothing<PropertyAttributes>());
1400  }
1401  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1402                                 *holder, Object::DONT_THROW);
1403  if (!interceptor->query()->IsUndefined(isolate)) {
1404    Handle<Object> result;
1405    if (it->IsElement()) {
1406      uint32_t index = it->index();
1407      v8::IndexedPropertyQueryCallback query =
1408          v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
1409      result = args.Call(query, index);
1410    } else {
1411      Handle<Name> name = it->name();
1412      DCHECK(!name->IsPrivate());
1413      v8::GenericNamedPropertyQueryCallback query =
1414          v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
1415              interceptor->query());
1416      result = args.Call(query, name);
1417    }
1418    if (!result.is_null()) {
1419      int32_t value;
1420      CHECK(result->ToInt32(&value));
1421      return Just(static_cast<PropertyAttributes>(value));
1422    }
1423  } else if (!interceptor->getter()->IsUndefined(isolate)) {
1424    // TODO(verwaest): Use GetPropertyWithInterceptor?
1425    Handle<Object> result;
1426    if (it->IsElement()) {
1427      uint32_t index = it->index();
1428      v8::IndexedPropertyGetterCallback getter =
1429          v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
1430      result = args.Call(getter, index);
1431    } else {
1432      Handle<Name> name = it->name();
1433      DCHECK(!name->IsPrivate());
1434      v8::GenericNamedPropertyGetterCallback getter =
1435          v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
1436              interceptor->getter());
1437      result = args.Call(getter, name);
1438    }
1439    if (!result.is_null()) return Just(DONT_ENUM);
1440  }
1441
1442  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
1443  return Just(ABSENT);
1444}
1445
1446Maybe<bool> SetPropertyWithInterceptorInternal(
1447    LookupIterator* it, Handle<InterceptorInfo> interceptor,
1448    Object::ShouldThrow should_throw, Handle<Object> value) {
1449  Isolate* isolate = it->isolate();
1450  // Make sure that the top context does not change when doing callbacks or
1451  // interceptor calls.
1452  AssertNoContextChange ncc(isolate);
1453
1454  if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
1455
1456  Handle<JSObject> holder = it->GetHolder<JSObject>();
1457  bool result;
1458  Handle<Object> receiver = it->GetReceiver();
1459  if (!receiver->IsJSReceiver()) {
1460    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
1461                                     Object::ConvertReceiver(isolate, receiver),
1462                                     Nothing<bool>());
1463  }
1464  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1465                                 *holder, should_throw);
1466
1467  if (it->IsElement()) {
1468    uint32_t index = it->index();
1469    v8::IndexedPropertySetterCallback setter =
1470        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
1471    // TODO(neis): In the future, we may want to actually return the
1472    // interceptor's result, which then should be a boolean.
1473    result = !args.Call(setter, index, value).is_null();
1474  } else {
1475    Handle<Name> name = it->name();
1476    DCHECK(!name->IsPrivate());
1477
1478    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
1479      return Just(false);
1480    }
1481
1482    v8::GenericNamedPropertySetterCallback setter =
1483        v8::ToCData<v8::GenericNamedPropertySetterCallback>(
1484            interceptor->setter());
1485    result = !args.Call(setter, name, value).is_null();
1486  }
1487
1488  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
1489  return Just(result);
1490}
1491
1492}  // namespace
1493
1494MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
1495    LookupIterator* it) {
1496  Isolate* isolate = it->isolate();
1497  Handle<JSObject> checked = it->GetHolder<JSObject>();
1498  Handle<InterceptorInfo> interceptor =
1499      it->GetInterceptorForFailedAccessCheck();
1500  if (interceptor.is_null()) {
1501    while (AllCanRead(it)) {
1502      if (it->state() == LookupIterator::ACCESSOR) {
1503        return GetPropertyWithAccessor(it);
1504      }
1505      DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
1506      bool done;
1507      Handle<Object> result;
1508      ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
1509                                 GetPropertyWithInterceptor(it, &done), Object);
1510      if (done) return result;
1511    }
1512  } else {
1513    MaybeHandle<Object> result;
1514    bool done;
1515    result = GetPropertyWithInterceptorInternal(it, interceptor, &done);
1516    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1517    if (done) return result;
1518  }
1519
1520  // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
1521  // undefined.
1522  Handle<Name> name = it->GetName();
1523  if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
1524    return it->factory()->undefined_value();
1525  }
1526
1527  isolate->ReportFailedAccessCheck(checked);
1528  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1529  return it->factory()->undefined_value();
1530}
1531
1532
1533Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
1534    LookupIterator* it) {
1535  Isolate* isolate = it->isolate();
1536  Handle<JSObject> checked = it->GetHolder<JSObject>();
1537  Handle<InterceptorInfo> interceptor =
1538      it->GetInterceptorForFailedAccessCheck();
1539  if (interceptor.is_null()) {
1540    while (AllCanRead(it)) {
1541      if (it->state() == LookupIterator::ACCESSOR) {
1542        return Just(it->property_attributes());
1543      }
1544      DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
1545      auto result = GetPropertyAttributesWithInterceptor(it);
1546      if (isolate->has_scheduled_exception()) break;
1547      if (result.IsJust() && result.FromJust() != ABSENT) return result;
1548    }
1549  } else {
1550    Maybe<PropertyAttributes> result =
1551        GetPropertyAttributesWithInterceptorInternal(it, interceptor);
1552    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
1553    if (result.FromMaybe(ABSENT) != ABSENT) return result;
1554  }
1555  isolate->ReportFailedAccessCheck(checked);
1556  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
1557  return Just(ABSENT);
1558}
1559
1560
1561// static
1562bool JSObject::AllCanWrite(LookupIterator* it) {
1563  for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
1564    if (it->state() == LookupIterator::ACCESSOR) {
1565      Handle<Object> accessors = it->GetAccessors();
1566      if (accessors->IsAccessorInfo()) {
1567        if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
1568      }
1569    }
1570  }
1571  return false;
1572}
1573
1574
1575Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
1576    LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
1577  Isolate* isolate = it->isolate();
1578  Handle<JSObject> checked = it->GetHolder<JSObject>();
1579  Handle<InterceptorInfo> interceptor =
1580      it->GetInterceptorForFailedAccessCheck();
1581  if (interceptor.is_null()) {
1582    if (AllCanWrite(it)) {
1583      return SetPropertyWithAccessor(it, value, should_throw);
1584    }
1585  } else {
1586    Maybe<bool> result = SetPropertyWithInterceptorInternal(
1587        it, interceptor, should_throw, value);
1588    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1589    if (result.IsJust()) return result;
1590  }
1591
1592  isolate->ReportFailedAccessCheck(checked);
1593  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1594  return Just(true);
1595}
1596
1597
1598void JSObject::SetNormalizedProperty(Handle<JSObject> object,
1599                                     Handle<Name> name,
1600                                     Handle<Object> value,
1601                                     PropertyDetails details) {
1602  DCHECK(!object->HasFastProperties());
1603  if (!name->IsUniqueName()) {
1604    name = object->GetIsolate()->factory()->InternalizeString(
1605        Handle<String>::cast(name));
1606  }
1607
1608  if (object->IsJSGlobalObject()) {
1609    Handle<GlobalDictionary> property_dictionary(object->global_dictionary());
1610
1611    int entry = property_dictionary->FindEntry(name);
1612    if (entry == GlobalDictionary::kNotFound) {
1613      Isolate* isolate = object->GetIsolate();
1614      auto cell = isolate->factory()->NewPropertyCell();
1615      cell->set_value(*value);
1616      auto cell_type = value->IsUndefined(isolate)
1617                           ? PropertyCellType::kUndefined
1618                           : PropertyCellType::kConstant;
1619      details = details.set_cell_type(cell_type);
1620      value = cell;
1621      property_dictionary =
1622          GlobalDictionary::Add(property_dictionary, name, value, details);
1623      object->set_properties(*property_dictionary);
1624    } else {
1625      PropertyCell::UpdateCell(property_dictionary, entry, value, details);
1626    }
1627  } else {
1628    Handle<NameDictionary> property_dictionary(object->property_dictionary());
1629
1630    int entry = property_dictionary->FindEntry(name);
1631    if (entry == NameDictionary::kNotFound) {
1632      property_dictionary =
1633          NameDictionary::Add(property_dictionary, name, value, details);
1634      object->set_properties(*property_dictionary);
1635    } else {
1636      PropertyDetails original_details = property_dictionary->DetailsAt(entry);
1637      int enumeration_index = original_details.dictionary_index();
1638      DCHECK(enumeration_index > 0);
1639      details = details.set_index(enumeration_index);
1640      property_dictionary->SetEntry(entry, name, value, details);
1641    }
1642  }
1643}
1644
1645// static
1646Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
1647                                            Handle<JSReceiver> object,
1648                                            Handle<Object> proto) {
1649  PrototypeIterator iter(isolate, object, kStartAtReceiver);
1650  while (true) {
1651    if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
1652    if (iter.IsAtEnd()) return Just(false);
1653    if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
1654      return Just(true);
1655    }
1656  }
1657}
1658
1659Map* Object::GetRootMap(Isolate* isolate) {
1660  DisallowHeapAllocation no_alloc;
1661  if (IsSmi()) {
1662    Context* native_context = isolate->context()->native_context();
1663    return native_context->number_function()->initial_map();
1664  }
1665
1666  // The object is either a number, a string, a symbol, a boolean, a SIMD value,
1667  // a real JS object, or a Harmony proxy.
1668  HeapObject* heap_object = HeapObject::cast(this);
1669  if (heap_object->IsJSReceiver()) {
1670    return heap_object->map();
1671  }
1672  int constructor_function_index =
1673      heap_object->map()->GetConstructorFunctionIndex();
1674  if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
1675    Context* native_context = isolate->context()->native_context();
1676    JSFunction* constructor_function =
1677        JSFunction::cast(native_context->get(constructor_function_index));
1678    return constructor_function->initial_map();
1679  }
1680  return isolate->heap()->null_value()->map();
1681}
1682
1683namespace {
1684
1685// Returns a non-SMI for JSObjects, but returns the hash code for simple
1686// objects.  This avoids a double lookup in the cases where we know we will
1687// add the hash to the JSObject if it does not already exist.
1688Object* GetSimpleHash(Object* object) {
1689  // The object is either a Smi, a HeapNumber, a name, an odd-ball,
1690  // a SIMD value type, a real JS object, or a Harmony proxy.
1691  if (object->IsSmi()) {
1692    uint32_t hash =
1693        ComputeIntegerHash(Smi::cast(object)->value(), kZeroHashSeed);
1694    return Smi::FromInt(hash & Smi::kMaxValue);
1695  }
1696  if (object->IsHeapNumber()) {
1697    double num = HeapNumber::cast(object)->value();
1698    if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
1699    if (i::IsMinusZero(num)) num = 0;
1700    if (IsSmiDouble(num)) {
1701      return Smi::FromInt(FastD2I(num))->GetHash();
1702    }
1703    uint32_t hash = ComputeLongHash(double_to_uint64(num));
1704    return Smi::FromInt(hash & Smi::kMaxValue);
1705  }
1706  if (object->IsName()) {
1707    uint32_t hash = Name::cast(object)->Hash();
1708    return Smi::FromInt(hash);
1709  }
1710  if (object->IsOddball()) {
1711    uint32_t hash = Oddball::cast(object)->to_string()->Hash();
1712    return Smi::FromInt(hash);
1713  }
1714  if (object->IsSimd128Value()) {
1715    uint32_t hash = Simd128Value::cast(object)->Hash();
1716    return Smi::FromInt(hash & Smi::kMaxValue);
1717  }
1718  DCHECK(object->IsJSReceiver());
1719  // Simply return the receiver as it is guaranteed to not be a SMI.
1720  return object;
1721}
1722
1723}  // namespace
1724
1725Object* Object::GetHash() {
1726  Object* hash = GetSimpleHash(this);
1727  if (hash->IsSmi()) return hash;
1728
1729  DisallowHeapAllocation no_gc;
1730  DCHECK(IsJSReceiver());
1731  JSReceiver* receiver = JSReceiver::cast(this);
1732  Isolate* isolate = receiver->GetIsolate();
1733  return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
1734}
1735
1736Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
1737  Object* hash = GetSimpleHash(*object);
1738  if (hash->IsSmi()) return Smi::cast(hash);
1739
1740  DCHECK(object->IsJSReceiver());
1741  return JSReceiver::GetOrCreateIdentityHash(isolate,
1742                                             Handle<JSReceiver>::cast(object));
1743}
1744
1745
1746bool Object::SameValue(Object* other) {
1747  if (other == this) return true;
1748
1749  // The object is either a number, a name, an odd-ball,
1750  // a real JS object, or a Harmony proxy.
1751  if (IsNumber() && other->IsNumber()) {
1752    double this_value = Number();
1753    double other_value = other->Number();
1754    // SameValue(NaN, NaN) is true.
1755    if (this_value != other_value) {
1756      return std::isnan(this_value) && std::isnan(other_value);
1757    }
1758    // SameValue(0.0, -0.0) is false.
1759    return (std::signbit(this_value) == std::signbit(other_value));
1760  }
1761  if (IsString() && other->IsString()) {
1762    return String::cast(this)->Equals(String::cast(other));
1763  }
1764  if (IsFloat32x4() && other->IsFloat32x4()) {
1765    Float32x4* a = Float32x4::cast(this);
1766    Float32x4* b = Float32x4::cast(other);
1767    for (int i = 0; i < 4; i++) {
1768      float x = a->get_lane(i);
1769      float y = b->get_lane(i);
1770      // Implements the ES5 SameValue operation for floating point types.
1771      // http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
1772      if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
1773      if (std::signbit(x) != std::signbit(y)) return false;
1774    }
1775    return true;
1776  } else if (IsSimd128Value() && other->IsSimd128Value()) {
1777    Simd128Value* a = Simd128Value::cast(this);
1778    Simd128Value* b = Simd128Value::cast(other);
1779    return a->map() == b->map() && a->BitwiseEquals(b);
1780  }
1781  return false;
1782}
1783
1784
1785bool Object::SameValueZero(Object* other) {
1786  if (other == this) return true;
1787
1788  // The object is either a number, a name, an odd-ball,
1789  // a real JS object, or a Harmony proxy.
1790  if (IsNumber() && other->IsNumber()) {
1791    double this_value = Number();
1792    double other_value = other->Number();
1793    // +0 == -0 is true
1794    return this_value == other_value ||
1795           (std::isnan(this_value) && std::isnan(other_value));
1796  }
1797  if (IsString() && other->IsString()) {
1798    return String::cast(this)->Equals(String::cast(other));
1799  }
1800  if (IsFloat32x4() && other->IsFloat32x4()) {
1801    Float32x4* a = Float32x4::cast(this);
1802    Float32x4* b = Float32x4::cast(other);
1803    for (int i = 0; i < 4; i++) {
1804      float x = a->get_lane(i);
1805      float y = b->get_lane(i);
1806      // Implements the ES6 SameValueZero operation for floating point types.
1807      // http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
1808      if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
1809      // SameValueZero doesn't distinguish between 0 and -0.
1810    }
1811    return true;
1812  } else if (IsSimd128Value() && other->IsSimd128Value()) {
1813    Simd128Value* a = Simd128Value::cast(this);
1814    Simd128Value* b = Simd128Value::cast(other);
1815    return a->map() == b->map() && a->BitwiseEquals(b);
1816  }
1817  return false;
1818}
1819
1820
1821MaybeHandle<Object> Object::ArraySpeciesConstructor(
1822    Isolate* isolate, Handle<Object> original_array) {
1823  Handle<Object> default_species = isolate->array_function();
1824  if (original_array->IsJSArray() &&
1825      Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
1826      isolate->IsArraySpeciesLookupChainIntact()) {
1827    return default_species;
1828  }
1829  Handle<Object> constructor = isolate->factory()->undefined_value();
1830  Maybe<bool> is_array = Object::IsArray(original_array);
1831  MAYBE_RETURN_NULL(is_array);
1832  if (is_array.FromJust()) {
1833    ASSIGN_RETURN_ON_EXCEPTION(
1834        isolate, constructor,
1835        Object::GetProperty(original_array,
1836                            isolate->factory()->constructor_string()),
1837        Object);
1838    if (constructor->IsConstructor()) {
1839      Handle<Context> constructor_context;
1840      ASSIGN_RETURN_ON_EXCEPTION(
1841          isolate, constructor_context,
1842          JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
1843          Object);
1844      if (*constructor_context != *isolate->native_context() &&
1845          *constructor == constructor_context->array_function()) {
1846        constructor = isolate->factory()->undefined_value();
1847      }
1848    }
1849    if (constructor->IsJSReceiver()) {
1850      ASSIGN_RETURN_ON_EXCEPTION(
1851          isolate, constructor,
1852          JSReceiver::GetProperty(Handle<JSReceiver>::cast(constructor),
1853                                  isolate->factory()->species_symbol()),
1854          Object);
1855      if (constructor->IsNull(isolate)) {
1856        constructor = isolate->factory()->undefined_value();
1857      }
1858    }
1859  }
1860  if (constructor->IsUndefined(isolate)) {
1861    return default_species;
1862  } else {
1863    if (!constructor->IsConstructor()) {
1864      THROW_NEW_ERROR(isolate,
1865          NewTypeError(MessageTemplate::kSpeciesNotConstructor),
1866          Object);
1867    }
1868    return constructor;
1869  }
1870}
1871
1872
1873void Object::ShortPrint(FILE* out) {
1874  OFStream os(out);
1875  os << Brief(this);
1876}
1877
1878
1879void Object::ShortPrint(StringStream* accumulator) {
1880  std::ostringstream os;
1881  os << Brief(this);
1882  accumulator->Add(os.str().c_str());
1883}
1884
1885
1886void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
1887
1888
1889std::ostream& operator<<(std::ostream& os, const Brief& v) {
1890  if (v.value->IsSmi()) {
1891    Smi::cast(v.value)->SmiPrint(os);
1892  } else {
1893    // TODO(svenpanne) Const-correct HeapObjectShortPrint!
1894    HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
1895    obj->HeapObjectShortPrint(os);
1896  }
1897  return os;
1898}
1899
1900
1901void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
1902  os << value();
1903}
1904
1905
1906// Should a word be prefixed by 'a' or 'an' in order to read naturally in
1907// English?  Returns false for non-ASCII or words that don't start with
1908// a capital letter.  The a/an rule follows pronunciation in English.
1909// We don't use the BBC's overcorrect "an historic occasion" though if
1910// you speak a dialect you may well say "an 'istoric occasion".
1911static bool AnWord(String* str) {
1912  if (str->length() == 0) return false;  // A nothing.
1913  int c0 = str->Get(0);
1914  int c1 = str->length() > 1 ? str->Get(1) : 0;
1915  if (c0 == 'U') {
1916    if (c1 > 'Z') {
1917      return true;  // An Umpire, but a UTF8String, a U.
1918    }
1919  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
1920    return true;    // An Ape, an ABCBook.
1921  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
1922           (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
1923            c0 == 'S' || c0 == 'X')) {
1924    return true;    // An MP3File, an M.
1925  }
1926  return false;
1927}
1928
1929
1930Handle<String> String::SlowFlatten(Handle<ConsString> cons,
1931                                   PretenureFlag pretenure) {
1932  DCHECK(AllowHeapAllocation::IsAllowed());
1933  DCHECK(cons->second()->length() != 0);
1934  Isolate* isolate = cons->GetIsolate();
1935  int length = cons->length();
1936  PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
1937                                                            : TENURED;
1938  Handle<SeqString> result;
1939  if (cons->IsOneByteRepresentation()) {
1940    Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
1941        length, tenure).ToHandleChecked();
1942    DisallowHeapAllocation no_gc;
1943    WriteToFlat(*cons, flat->GetChars(), 0, length);
1944    result = flat;
1945  } else {
1946    Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
1947        length, tenure).ToHandleChecked();
1948    DisallowHeapAllocation no_gc;
1949    WriteToFlat(*cons, flat->GetChars(), 0, length);
1950    result = flat;
1951  }
1952  cons->set_first(*result);
1953  cons->set_second(isolate->heap()->empty_string());
1954  DCHECK(result->IsFlat());
1955  return result;
1956}
1957
1958
1959
1960bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1961  // Externalizing twice leaks the external resource, so it's
1962  // prohibited by the API.
1963  DCHECK(!this->IsExternalString());
1964  DCHECK(!resource->IsCompressible());
1965#ifdef ENABLE_SLOW_DCHECKS
1966  if (FLAG_enable_slow_asserts) {
1967    // Assert that the resource and the string are equivalent.
1968    DCHECK(static_cast<size_t>(this->length()) == resource->length());
1969    ScopedVector<uc16> smart_chars(this->length());
1970    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1971    DCHECK(memcmp(smart_chars.start(),
1972                  resource->data(),
1973                  resource->length() * sizeof(smart_chars[0])) == 0);
1974  }
1975#endif  // DEBUG
1976  int size = this->Size();  // Byte size of the original string.
1977  // Abort if size does not allow in-place conversion.
1978  if (size < ExternalString::kShortSize) return false;
1979  Heap* heap = GetHeap();
1980  bool is_one_byte = this->IsOneByteRepresentation();
1981  bool is_internalized = this->IsInternalizedString();
1982
1983  // Morph the string to an external string by replacing the map and
1984  // reinitializing the fields.  This won't work if the space the existing
1985  // string occupies is too small for a regular  external string.
1986  // Instead, we resort to a short external string instead, omitting
1987  // the field caching the address of the backing store.  When we encounter
1988  // short external strings in generated code, we need to bailout to runtime.
1989  Map* new_map;
1990  if (size < ExternalString::kSize) {
1991    new_map = is_internalized
1992        ? (is_one_byte
1993           ? heap->short_external_internalized_string_with_one_byte_data_map()
1994           : heap->short_external_internalized_string_map())
1995        : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
1996                       : heap->short_external_string_map());
1997  } else {
1998    new_map = is_internalized
1999        ? (is_one_byte
2000           ? heap->external_internalized_string_with_one_byte_data_map()
2001           : heap->external_internalized_string_map())
2002        : (is_one_byte ? heap->external_string_with_one_byte_data_map()
2003                       : heap->external_string_map());
2004  }
2005
2006  // Byte size of the external String object.
2007  int new_size = this->SizeFromMap(new_map);
2008  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2009                             ClearRecordedSlots::kNo);
2010
2011  // We are storing the new map using release store after creating a filler for
2012  // the left-over space to avoid races with the sweeper thread.
2013  this->synchronized_set_map(new_map);
2014
2015  ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
2016  self->set_resource(resource);
2017  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
2018
2019  heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
2020  return true;
2021}
2022
2023
2024bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
2025  // Externalizing twice leaks the external resource, so it's
2026  // prohibited by the API.
2027  DCHECK(!this->IsExternalString());
2028  DCHECK(!resource->IsCompressible());
2029#ifdef ENABLE_SLOW_DCHECKS
2030  if (FLAG_enable_slow_asserts) {
2031    // Assert that the resource and the string are equivalent.
2032    DCHECK(static_cast<size_t>(this->length()) == resource->length());
2033    if (this->IsTwoByteRepresentation()) {
2034      ScopedVector<uint16_t> smart_chars(this->length());
2035      String::WriteToFlat(this, smart_chars.start(), 0, this->length());
2036      DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
2037    }
2038    ScopedVector<char> smart_chars(this->length());
2039    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
2040    DCHECK(memcmp(smart_chars.start(),
2041                  resource->data(),
2042                  resource->length() * sizeof(smart_chars[0])) == 0);
2043  }
2044#endif  // DEBUG
2045  int size = this->Size();  // Byte size of the original string.
2046  // Abort if size does not allow in-place conversion.
2047  if (size < ExternalString::kShortSize) return false;
2048  Heap* heap = GetHeap();
2049  bool is_internalized = this->IsInternalizedString();
2050
2051  // Morph the string to an external string by replacing the map and
2052  // reinitializing the fields.  This won't work if the space the existing
2053  // string occupies is too small for a regular  external string.
2054  // Instead, we resort to a short external string instead, omitting
2055  // the field caching the address of the backing store.  When we encounter
2056  // short external strings in generated code, we need to bailout to runtime.
2057  Map* new_map;
2058  if (size < ExternalString::kSize) {
2059    new_map = is_internalized
2060                  ? heap->short_external_one_byte_internalized_string_map()
2061                  : heap->short_external_one_byte_string_map();
2062  } else {
2063    new_map = is_internalized
2064                  ? heap->external_one_byte_internalized_string_map()
2065                  : heap->external_one_byte_string_map();
2066  }
2067
2068  // Byte size of the external String object.
2069  int new_size = this->SizeFromMap(new_map);
2070  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
2071                             ClearRecordedSlots::kNo);
2072
2073  // We are storing the new map using release store after creating a filler for
2074  // the left-over space to avoid races with the sweeper thread.
2075  this->synchronized_set_map(new_map);
2076
2077  ExternalOneByteString* self = ExternalOneByteString::cast(this);
2078  self->set_resource(resource);
2079  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
2080
2081  heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
2082  return true;
2083}
2084
2085void String::StringShortPrint(StringStream* accumulator, bool show_details) {
2086  int len = length();
2087  if (len > kMaxShortPrintLength) {
2088    accumulator->Add("<Very long string[%u]>", len);
2089    return;
2090  }
2091
2092  if (!LooksValid()) {
2093    accumulator->Add("<Invalid String>");
2094    return;
2095  }
2096
2097  StringCharacterStream stream(this);
2098
2099  bool truncated = false;
2100  if (len > kMaxShortPrintLength) {
2101    len = kMaxShortPrintLength;
2102    truncated = true;
2103  }
2104  bool one_byte = true;
2105  for (int i = 0; i < len; i++) {
2106    uint16_t c = stream.GetNext();
2107
2108    if (c < 32 || c >= 127) {
2109      one_byte = false;
2110    }
2111  }
2112  stream.Reset(this);
2113  if (one_byte) {
2114    if (show_details) accumulator->Add("<String[%u]: ", length());
2115    for (int i = 0; i < len; i++) {
2116      accumulator->Put(static_cast<char>(stream.GetNext()));
2117    }
2118    if (show_details) accumulator->Put('>');
2119  } else {
2120    // Backslash indicates that the string contains control
2121    // characters and that backslashes are therefore escaped.
2122    if (show_details) accumulator->Add("<String[%u]\\: ", length());
2123    for (int i = 0; i < len; i++) {
2124      uint16_t c = stream.GetNext();
2125      if (c == '\n') {
2126        accumulator->Add("\\n");
2127      } else if (c == '\r') {
2128        accumulator->Add("\\r");
2129      } else if (c == '\\') {
2130        accumulator->Add("\\\\");
2131      } else if (c < 32 || c > 126) {
2132        accumulator->Add("\\x%02x", c);
2133      } else {
2134        accumulator->Put(static_cast<char>(c));
2135      }
2136    }
2137    if (truncated) {
2138      accumulator->Put('.');
2139      accumulator->Put('.');
2140      accumulator->Put('.');
2141    }
2142    if (show_details) accumulator->Put('>');
2143  }
2144  return;
2145}
2146
2147
2148void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
2149  if (end < 0) end = length();
2150  StringCharacterStream stream(this, start);
2151  for (int i = start; i < end && stream.HasMore(); i++) {
2152    os << AsUC16(stream.GetNext());
2153  }
2154}
2155
2156
2157void JSObject::JSObjectShortPrint(StringStream* accumulator) {
2158  switch (map()->instance_type()) {
2159    case JS_ARRAY_TYPE: {
2160      double length = JSArray::cast(this)->length()->IsUndefined(GetIsolate())
2161                          ? 0
2162                          : JSArray::cast(this)->length()->Number();
2163      accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
2164      break;
2165    }
2166    case JS_BOUND_FUNCTION_TYPE: {
2167      JSBoundFunction* bound_function = JSBoundFunction::cast(this);
2168      accumulator->Add("<JS BoundFunction");
2169      accumulator->Add(
2170          " (BoundTargetFunction %p)>",
2171          reinterpret_cast<void*>(bound_function->bound_target_function()));
2172      break;
2173    }
2174    case JS_WEAK_MAP_TYPE: {
2175      accumulator->Add("<JS WeakMap>");
2176      break;
2177    }
2178    case JS_WEAK_SET_TYPE: {
2179      accumulator->Add("<JS WeakSet>");
2180      break;
2181    }
2182    case JS_REGEXP_TYPE: {
2183      accumulator->Add("<JS RegExp>");
2184      break;
2185    }
2186    case JS_FUNCTION_TYPE: {
2187      JSFunction* function = JSFunction::cast(this);
2188      Object* fun_name = function->shared()->DebugName();
2189      bool printed = false;
2190      if (fun_name->IsString()) {
2191        String* str = String::cast(fun_name);
2192        if (str->length() > 0) {
2193          accumulator->Add("<JS Function ");
2194          accumulator->Put(str);
2195          printed = true;
2196        }
2197      }
2198      if (!printed) {
2199        accumulator->Add("<JS Function");
2200      }
2201      if (FLAG_trace_file_names) {
2202        Object* source_name =
2203            Script::cast(function->shared()->script())->name();
2204        if (source_name->IsString()) {
2205          String* str = String::cast(source_name);
2206          if (str->length() > 0) {
2207            accumulator->Add(" <");
2208            accumulator->Put(str);
2209            accumulator->Add(">");
2210          }
2211        }
2212      }
2213      accumulator->Add(" (SharedFunctionInfo %p)",
2214                       reinterpret_cast<void*>(function->shared()));
2215      accumulator->Put('>');
2216      break;
2217    }
2218    case JS_GENERATOR_OBJECT_TYPE: {
2219      accumulator->Add("<JS Generator>");
2220      break;
2221    }
2222    case JS_MODULE_TYPE: {
2223      accumulator->Add("<JS Module>");
2224      break;
2225    }
2226    // All other JSObjects are rather similar to each other (JSObject,
2227    // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
2228    default: {
2229      Map* map_of_this = map();
2230      Heap* heap = GetHeap();
2231      Object* constructor = map_of_this->GetConstructor();
2232      bool printed = false;
2233      if (constructor->IsHeapObject() &&
2234          !heap->Contains(HeapObject::cast(constructor))) {
2235        accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
2236      } else {
2237        bool global_object = IsJSGlobalProxy();
2238        if (constructor->IsJSFunction()) {
2239          if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
2240            accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
2241          } else {
2242            Object* constructor_name =
2243                JSFunction::cast(constructor)->shared()->name();
2244            if (constructor_name->IsString()) {
2245              String* str = String::cast(constructor_name);
2246              if (str->length() > 0) {
2247                bool vowel = AnWord(str);
2248                accumulator->Add("<%sa%s ",
2249                       global_object ? "Global Object: " : "",
2250                       vowel ? "n" : "");
2251                accumulator->Put(str);
2252                accumulator->Add(" with %smap %p",
2253                    map_of_this->is_deprecated() ? "deprecated " : "",
2254                    map_of_this);
2255                printed = true;
2256              }
2257            }
2258          }
2259        }
2260        if (!printed) {
2261          accumulator->Add("<JS %sObject", global_object ? "Global " : "");
2262        }
2263      }
2264      if (IsJSValue()) {
2265        accumulator->Add(" value = ");
2266        JSValue::cast(this)->value()->ShortPrint(accumulator);
2267      }
2268      accumulator->Put('>');
2269      break;
2270    }
2271  }
2272}
2273
2274
2275void JSObject::PrintElementsTransition(
2276    FILE* file, Handle<JSObject> object,
2277    ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
2278    ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
2279  if (from_kind != to_kind) {
2280    OFStream os(file);
2281    os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
2282       << ElementsKindToString(to_kind) << "] in ";
2283    JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
2284    PrintF(file, " for ");
2285    object->ShortPrint(file);
2286    PrintF(file, " from ");
2287    from_elements->ShortPrint(file);
2288    PrintF(file, " to ");
2289    to_elements->ShortPrint(file);
2290    PrintF(file, "\n");
2291  }
2292}
2293
2294
2295// static
2296MaybeHandle<JSFunction> Map::GetConstructorFunction(
2297    Handle<Map> map, Handle<Context> native_context) {
2298  if (map->IsPrimitiveMap()) {
2299    int const constructor_function_index = map->GetConstructorFunctionIndex();
2300    if (constructor_function_index != kNoConstructorFunctionIndex) {
2301      return handle(
2302          JSFunction::cast(native_context->get(constructor_function_index)));
2303    }
2304  }
2305  return MaybeHandle<JSFunction>();
2306}
2307
2308
2309void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
2310                               PropertyAttributes attributes) {
2311  OFStream os(file);
2312  os << "[reconfiguring]";
2313  Name* name = instance_descriptors()->GetKey(modify_index);
2314  if (name->IsString()) {
2315    String::cast(name)->PrintOn(file);
2316  } else {
2317    os << "{symbol " << static_cast<void*>(name) << "}";
2318  }
2319  os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
2320  os << attributes << " [";
2321  JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
2322  os << "]\n";
2323}
2324
2325void Map::PrintGeneralization(
2326    FILE* file, const char* reason, int modify_index, int split,
2327    int descriptors, bool constant_to_field, Representation old_representation,
2328    Representation new_representation, MaybeHandle<FieldType> old_field_type,
2329    MaybeHandle<Object> old_value, MaybeHandle<FieldType> new_field_type,
2330    MaybeHandle<Object> new_value) {
2331  OFStream os(file);
2332  os << "[generalizing]";
2333  Name* name = instance_descriptors()->GetKey(modify_index);
2334  if (name->IsString()) {
2335    String::cast(name)->PrintOn(file);
2336  } else {
2337    os << "{symbol " << static_cast<void*>(name) << "}";
2338  }
2339  os << ":";
2340  if (constant_to_field) {
2341    os << "c";
2342  } else {
2343    os << old_representation.Mnemonic() << "{";
2344    if (old_field_type.is_null()) {
2345      os << Brief(*(old_value.ToHandleChecked()));
2346    } else {
2347      old_field_type.ToHandleChecked()->PrintTo(os);
2348    }
2349    os << "}";
2350  }
2351  os << "->" << new_representation.Mnemonic() << "{";
2352  if (new_field_type.is_null()) {
2353    os << Brief(*(new_value.ToHandleChecked()));
2354  } else {
2355    new_field_type.ToHandleChecked()->PrintTo(os);
2356  }
2357  os << "} (";
2358  if (strlen(reason) > 0) {
2359    os << reason;
2360  } else {
2361    os << "+" << (descriptors - split) << " maps";
2362  }
2363  os << ") [";
2364  JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
2365  os << "]\n";
2366}
2367
2368
2369void JSObject::PrintInstanceMigration(FILE* file,
2370                                      Map* original_map,
2371                                      Map* new_map) {
2372  PrintF(file, "[migrating]");
2373  DescriptorArray* o = original_map->instance_descriptors();
2374  DescriptorArray* n = new_map->instance_descriptors();
2375  for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
2376    Representation o_r = o->GetDetails(i).representation();
2377    Representation n_r = n->GetDetails(i).representation();
2378    if (!o_r.Equals(n_r)) {
2379      String::cast(o->GetKey(i))->PrintOn(file);
2380      PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
2381    } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
2382               n->GetDetails(i).type() == DATA) {
2383      Name* name = o->GetKey(i);
2384      if (name->IsString()) {
2385        String::cast(name)->PrintOn(file);
2386      } else {
2387        PrintF(file, "{symbol %p}", static_cast<void*>(name));
2388      }
2389      PrintF(file, " ");
2390    }
2391  }
2392  PrintF(file, "\n");
2393}
2394
2395
2396void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
2397  Heap* heap = GetHeap();
2398  Isolate* isolate = heap->isolate();
2399  if (!heap->Contains(this)) {
2400    os << "!!!INVALID POINTER!!!";
2401    return;
2402  }
2403  if (!heap->Contains(map())) {
2404    os << "!!!INVALID MAP!!!";
2405    return;
2406  }
2407
2408  os << this << " ";
2409
2410  if (IsString()) {
2411    HeapStringAllocator allocator;
2412    StringStream accumulator(&allocator);
2413    String::cast(this)->StringShortPrint(&accumulator);
2414    os << accumulator.ToCString().get();
2415    return;
2416  }
2417  if (IsJSObject()) {
2418    HeapStringAllocator allocator;
2419    StringStream accumulator(&allocator);
2420    JSObject::cast(this)->JSObjectShortPrint(&accumulator);
2421    os << accumulator.ToCString().get();
2422    return;
2423  }
2424  switch (map()->instance_type()) {
2425    case MAP_TYPE:
2426      os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
2427         << ")>";
2428      break;
2429    case FIXED_ARRAY_TYPE:
2430      os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
2431      break;
2432    case FIXED_DOUBLE_ARRAY_TYPE:
2433      os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
2434         << "]>";
2435      break;
2436    case BYTE_ARRAY_TYPE:
2437      os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
2438      break;
2439    case BYTECODE_ARRAY_TYPE:
2440      os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
2441      break;
2442    case TRANSITION_ARRAY_TYPE:
2443      os << "<TransitionArray[" << TransitionArray::cast(this)->length()
2444         << "]>";
2445      break;
2446    case FREE_SPACE_TYPE:
2447      os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
2448      break;
2449#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
2450  case FIXED_##TYPE##_ARRAY_TYPE:                                             \
2451    os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
2452       << "]>";                                                               \
2453    break;
2454
2455    TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
2456#undef TYPED_ARRAY_SHORT_PRINT
2457
2458    case SHARED_FUNCTION_INFO_TYPE: {
2459      SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
2460      base::SmartArrayPointer<char> debug_name =
2461          shared->DebugName()->ToCString();
2462      if (debug_name[0] != 0) {
2463        os << "<SharedFunctionInfo " << debug_name.get() << ">";
2464      } else {
2465        os << "<SharedFunctionInfo>";
2466      }
2467      break;
2468    }
2469    case JS_MESSAGE_OBJECT_TYPE:
2470      os << "<JSMessageObject>";
2471      break;
2472#define MAKE_STRUCT_CASE(NAME, Name, name) \
2473  case NAME##_TYPE:                        \
2474    os << "<" #Name ">";                   \
2475    break;
2476  STRUCT_LIST(MAKE_STRUCT_CASE)
2477#undef MAKE_STRUCT_CASE
2478    case CODE_TYPE: {
2479      Code* code = Code::cast(this);
2480      os << "<Code: " << Code::Kind2String(code->kind()) << ">";
2481      break;
2482    }
2483    case ODDBALL_TYPE: {
2484      if (IsUndefined(isolate)) {
2485        os << "<undefined>";
2486      } else if (IsTheHole(isolate)) {
2487        os << "<the hole>";
2488      } else if (IsNull(isolate)) {
2489        os << "<null>";
2490      } else if (IsTrue(isolate)) {
2491        os << "<true>";
2492      } else if (IsFalse(isolate)) {
2493        os << "<false>";
2494      } else {
2495        os << "<Odd Oddball: ";
2496        os << Oddball::cast(this)->to_string()->ToCString().get();
2497        os << ">";
2498      }
2499      break;
2500    }
2501    case SYMBOL_TYPE: {
2502      Symbol* symbol = Symbol::cast(this);
2503      symbol->SymbolShortPrint(os);
2504      break;
2505    }
2506    case HEAP_NUMBER_TYPE: {
2507      os << "<Number: ";
2508      HeapNumber::cast(this)->HeapNumberPrint(os);
2509      os << ">";
2510      break;
2511    }
2512    case MUTABLE_HEAP_NUMBER_TYPE: {
2513      os << "<MutableNumber: ";
2514      HeapNumber::cast(this)->HeapNumberPrint(os);
2515      os << '>';
2516      break;
2517    }
2518    case SIMD128_VALUE_TYPE: {
2519#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
2520  if (Is##Type()) {                                           \
2521    os << "<" #Type ">";                                      \
2522    break;                                                    \
2523  }
2524      SIMD128_TYPES(SIMD128_TYPE)
2525#undef SIMD128_TYPE
2526      UNREACHABLE();
2527      break;
2528    }
2529    case JS_PROXY_TYPE:
2530      os << "<JSProxy>";
2531      break;
2532    case FOREIGN_TYPE:
2533      os << "<Foreign>";
2534      break;
2535    case CELL_TYPE: {
2536      os << "Cell for ";
2537      HeapStringAllocator allocator;
2538      StringStream accumulator(&allocator);
2539      Cell::cast(this)->value()->ShortPrint(&accumulator);
2540      os << accumulator.ToCString().get();
2541      break;
2542    }
2543    case PROPERTY_CELL_TYPE: {
2544      os << "PropertyCell for ";
2545      HeapStringAllocator allocator;
2546      StringStream accumulator(&allocator);
2547      PropertyCell* cell = PropertyCell::cast(this);
2548      cell->value()->ShortPrint(&accumulator);
2549      os << accumulator.ToCString().get();
2550      break;
2551    }
2552    case WEAK_CELL_TYPE: {
2553      os << "WeakCell for ";
2554      HeapStringAllocator allocator;
2555      StringStream accumulator(&allocator);
2556      WeakCell::cast(this)->value()->ShortPrint(&accumulator);
2557      os << accumulator.ToCString().get();
2558      break;
2559    }
2560    default:
2561      os << "<Other heap object (" << map()->instance_type() << ")>";
2562      break;
2563  }
2564}
2565
2566
2567void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
2568
2569
2570void HeapObject::IterateBody(ObjectVisitor* v) {
2571  Map* m = map();
2572  IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
2573}
2574
2575
2576void HeapObject::IterateBody(InstanceType type, int object_size,
2577                             ObjectVisitor* v) {
2578  IterateBodyFast<ObjectVisitor>(type, object_size, v);
2579}
2580
2581
2582struct CallIsValidSlot {
2583  template <typename BodyDescriptor>
2584  static bool apply(HeapObject* obj, int offset, int) {
2585    return BodyDescriptor::IsValidSlot(obj, offset);
2586  }
2587};
2588
2589
2590bool HeapObject::IsValidSlot(int offset) {
2591  DCHECK_NE(0, offset);
2592  return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
2593                                                    this, offset, 0);
2594}
2595
2596
2597bool HeapNumber::HeapNumberBooleanValue() {
2598  return DoubleToBoolean(value());
2599}
2600
2601
2602void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
2603  os << value();
2604}
2605
2606
2607#define FIELD_ADDR_CONST(p, offset) \
2608  (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
2609
2610#define READ_INT32_FIELD(p, offset) \
2611  (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
2612
2613#define READ_INT64_FIELD(p, offset) \
2614  (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
2615
2616#define READ_BYTE_FIELD(p, offset) \
2617  (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
2618
2619
2620// static
2621Handle<String> Simd128Value::ToString(Handle<Simd128Value> input) {
2622#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
2623  if (input->Is##Type()) return Type::ToString(Handle<Type>::cast(input));
2624  SIMD128_TYPES(SIMD128_TYPE)
2625#undef SIMD128_TYPE
2626  UNREACHABLE();
2627  return Handle<String>::null();
2628}
2629
2630
2631// static
2632Handle<String> Float32x4::ToString(Handle<Float32x4> input) {
2633  Isolate* const isolate = input->GetIsolate();
2634  char arr[100];
2635  Vector<char> buffer(arr, arraysize(arr));
2636  std::ostringstream os;
2637  os << "SIMD.Float32x4("
2638     << std::string(DoubleToCString(input->get_lane(0), buffer)) << ", "
2639     << std::string(DoubleToCString(input->get_lane(1), buffer)) << ", "
2640     << std::string(DoubleToCString(input->get_lane(2), buffer)) << ", "
2641     << std::string(DoubleToCString(input->get_lane(3), buffer)) << ")";
2642  return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str());
2643}
2644
2645
2646#define SIMD128_BOOL_TO_STRING(Type, lane_count)                            \
2647  Handle<String> Type::ToString(Handle<Type> input) {                       \
2648    Isolate* const isolate = input->GetIsolate();                           \
2649    std::ostringstream os;                                                  \
2650    os << "SIMD." #Type "(";                                                \
2651    os << (input->get_lane(0) ? "true" : "false");                          \
2652    for (int i = 1; i < lane_count; i++) {                                  \
2653      os << ", " << (input->get_lane(i) ? "true" : "false");                \
2654    }                                                                       \
2655    os << ")";                                                              \
2656    return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
2657  }
2658SIMD128_BOOL_TO_STRING(Bool32x4, 4)
2659SIMD128_BOOL_TO_STRING(Bool16x8, 8)
2660SIMD128_BOOL_TO_STRING(Bool8x16, 16)
2661#undef SIMD128_BOOL_TO_STRING
2662
2663
2664#define SIMD128_INT_TO_STRING(Type, lane_count)                             \
2665  Handle<String> Type::ToString(Handle<Type> input) {                       \
2666    Isolate* const isolate = input->GetIsolate();                           \
2667    char arr[100];                                                          \
2668    Vector<char> buffer(arr, arraysize(arr));                               \
2669    std::ostringstream os;                                                  \
2670    os << "SIMD." #Type "(";                                                \
2671    os << IntToCString(input->get_lane(0), buffer);                         \
2672    for (int i = 1; i < lane_count; i++) {                                  \
2673      os << ", " << IntToCString(input->get_lane(i), buffer);               \
2674    }                                                                       \
2675    os << ")";                                                              \
2676    return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
2677  }
2678SIMD128_INT_TO_STRING(Int32x4, 4)
2679SIMD128_INT_TO_STRING(Uint32x4, 4)
2680SIMD128_INT_TO_STRING(Int16x8, 8)
2681SIMD128_INT_TO_STRING(Uint16x8, 8)
2682SIMD128_INT_TO_STRING(Int8x16, 16)
2683SIMD128_INT_TO_STRING(Uint8x16, 16)
2684#undef SIMD128_INT_TO_STRING
2685
2686
2687bool Simd128Value::BitwiseEquals(const Simd128Value* other) const {
2688  return READ_INT64_FIELD(this, kValueOffset) ==
2689             READ_INT64_FIELD(other, kValueOffset) &&
2690         READ_INT64_FIELD(this, kValueOffset + kInt64Size) ==
2691             READ_INT64_FIELD(other, kValueOffset + kInt64Size);
2692}
2693
2694
2695uint32_t Simd128Value::Hash() const {
2696  uint32_t seed = v8::internal::kZeroHashSeed;
2697  uint32_t hash;
2698  hash = ComputeIntegerHash(READ_INT32_FIELD(this, kValueOffset), seed);
2699  hash = ComputeIntegerHash(
2700      READ_INT32_FIELD(this, kValueOffset + 1 * kInt32Size), hash * 31);
2701  hash = ComputeIntegerHash(
2702      READ_INT32_FIELD(this, kValueOffset + 2 * kInt32Size), hash * 31);
2703  hash = ComputeIntegerHash(
2704      READ_INT32_FIELD(this, kValueOffset + 3 * kInt32Size), hash * 31);
2705  return hash;
2706}
2707
2708
2709void Simd128Value::CopyBits(void* destination) const {
2710  memcpy(destination, &READ_BYTE_FIELD(this, kValueOffset), kSimd128Size);
2711}
2712
2713
2714String* JSReceiver::class_name() {
2715  if (IsFunction()) {
2716    return GetHeap()->Function_string();
2717  }
2718  Object* maybe_constructor = map()->GetConstructor();
2719  if (maybe_constructor->IsJSFunction()) {
2720    JSFunction* constructor = JSFunction::cast(maybe_constructor);
2721    return String::cast(constructor->shared()->instance_class_name());
2722  }
2723  // If the constructor is not present, return "Object".
2724  return GetHeap()->Object_string();
2725}
2726
2727
2728// static
2729Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
2730  Isolate* isolate = receiver->GetIsolate();
2731
2732  // If the object was instantiated simply with base == new.target, the
2733  // constructor on the map provides the most accurate name.
2734  // Don't provide the info for prototypes, since their constructors are
2735  // reclaimed and replaced by Object in OptimizeAsPrototype.
2736  if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
2737      !receiver->map()->is_prototype_map()) {
2738    Object* maybe_constructor = receiver->map()->GetConstructor();
2739    if (maybe_constructor->IsJSFunction()) {
2740      JSFunction* constructor = JSFunction::cast(maybe_constructor);
2741      String* name = String::cast(constructor->shared()->name());
2742      if (name->length() == 0) name = constructor->shared()->inferred_name();
2743      if (name->length() != 0 &&
2744          !name->Equals(isolate->heap()->Object_string())) {
2745        return handle(name, isolate);
2746      }
2747    }
2748  }
2749
2750  Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
2751      receiver, isolate->factory()->to_string_tag_symbol());
2752  if (maybe_tag->IsString()) return Handle<String>::cast(maybe_tag);
2753
2754  PrototypeIterator iter(isolate, receiver);
2755  if (iter.IsAtEnd()) return handle(receiver->class_name());
2756  Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
2757  LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
2758                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
2759  Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
2760  Handle<String> result = isolate->factory()->Object_string();
2761  if (maybe_constructor->IsJSFunction()) {
2762    JSFunction* constructor = JSFunction::cast(*maybe_constructor);
2763    String* name = String::cast(constructor->shared()->name());
2764    if (name->length() == 0) name = constructor->shared()->inferred_name();
2765    if (name->length() > 0) result = handle(name, isolate);
2766  }
2767
2768  return result.is_identical_to(isolate->factory()->Object_string())
2769             ? handle(receiver->class_name())
2770             : result;
2771}
2772
2773
2774Context* JSReceiver::GetCreationContext() {
2775  JSReceiver* receiver = this;
2776  while (receiver->IsJSBoundFunction()) {
2777    receiver = JSBoundFunction::cast(receiver)->bound_target_function();
2778  }
2779  Object* constructor = receiver->map()->GetConstructor();
2780  JSFunction* function;
2781  if (constructor->IsJSFunction()) {
2782    function = JSFunction::cast(constructor);
2783  } else {
2784    // Functions have null as a constructor,
2785    // but any JSFunction knows its context immediately.
2786    CHECK(receiver->IsJSFunction());
2787    function = JSFunction::cast(receiver);
2788  }
2789
2790  return function->context()->native_context();
2791}
2792
2793static Handle<Object> WrapType(Handle<FieldType> type) {
2794  if (type->IsClass()) return Map::WeakCellForMap(type->AsClass());
2795  return type;
2796}
2797
2798MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name,
2799                                    Handle<FieldType> type,
2800                                    PropertyAttributes attributes,
2801                                    Representation representation,
2802                                    TransitionFlag flag) {
2803  DCHECK(DescriptorArray::kNotFound ==
2804         map->instance_descriptors()->Search(
2805             *name, map->NumberOfOwnDescriptors()));
2806
2807  // Ensure the descriptor array does not get too big.
2808  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
2809    return MaybeHandle<Map>();
2810  }
2811
2812  Isolate* isolate = map->GetIsolate();
2813
2814  // Compute the new index for new field.
2815  int index = map->NextFreePropertyIndex();
2816
2817  if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
2818    representation = Representation::Tagged();
2819    type = FieldType::Any(isolate);
2820  }
2821
2822  Handle<Object> wrapped_type(WrapType(type));
2823
2824  DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
2825                                representation);
2826  Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
2827  int unused_property_fields = new_map->unused_property_fields() - 1;
2828  if (unused_property_fields < 0) {
2829    unused_property_fields += JSObject::kFieldsAdded;
2830  }
2831  new_map->set_unused_property_fields(unused_property_fields);
2832  return new_map;
2833}
2834
2835
2836MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
2837                                       Handle<Name> name,
2838                                       Handle<Object> constant,
2839                                       PropertyAttributes attributes,
2840                                       TransitionFlag flag) {
2841  // Ensure the descriptor array does not get too big.
2842  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
2843    return MaybeHandle<Map>();
2844  }
2845
2846  // Allocate new instance descriptors with (name, constant) added.
2847  DataConstantDescriptor new_constant_desc(name, constant, attributes);
2848  return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
2849}
2850
2851
2852void JSObject::AddSlowProperty(Handle<JSObject> object,
2853                               Handle<Name> name,
2854                               Handle<Object> value,
2855                               PropertyAttributes attributes) {
2856  DCHECK(!object->HasFastProperties());
2857  Isolate* isolate = object->GetIsolate();
2858  if (object->IsJSGlobalObject()) {
2859    Handle<GlobalDictionary> dict(object->global_dictionary());
2860    PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
2861    int entry = dict->FindEntry(name);
2862    // If there's a cell there, just invalidate and set the property.
2863    if (entry != GlobalDictionary::kNotFound) {
2864      PropertyCell::UpdateCell(dict, entry, value, details);
2865      // TODO(ishell): move this to UpdateCell.
2866      // Need to adjust the details.
2867      int index = dict->NextEnumerationIndex();
2868      dict->SetNextEnumerationIndex(index + 1);
2869      PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
2870      details = cell->property_details().set_index(index);
2871      cell->set_property_details(details);
2872
2873    } else {
2874      auto cell = isolate->factory()->NewPropertyCell();
2875      cell->set_value(*value);
2876      auto cell_type = value->IsUndefined(isolate)
2877                           ? PropertyCellType::kUndefined
2878                           : PropertyCellType::kConstant;
2879      details = details.set_cell_type(cell_type);
2880      value = cell;
2881
2882      Handle<GlobalDictionary> result =
2883          GlobalDictionary::Add(dict, name, value, details);
2884      if (*dict != *result) object->set_properties(*result);
2885    }
2886  } else {
2887    Handle<NameDictionary> dict(object->property_dictionary());
2888    PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
2889    Handle<NameDictionary> result =
2890        NameDictionary::Add(dict, name, value, details);
2891    if (*dict != *result) object->set_properties(*result);
2892  }
2893}
2894
2895
2896const char* Representation::Mnemonic() const {
2897  switch (kind_) {
2898    case kNone: return "v";
2899    case kTagged: return "t";
2900    case kSmi: return "s";
2901    case kDouble: return "d";
2902    case kInteger32: return "i";
2903    case kHeapObject: return "h";
2904    case kExternal: return "x";
2905    default:
2906      UNREACHABLE();
2907      return NULL;
2908  }
2909}
2910
2911bool Map::InstancesNeedRewriting(Map* target) {
2912  int target_number_of_fields = target->NumberOfFields();
2913  int target_inobject = target->GetInObjectProperties();
2914  int target_unused = target->unused_property_fields();
2915  int old_number_of_fields;
2916
2917  return InstancesNeedRewriting(target, target_number_of_fields,
2918                                target_inobject, target_unused,
2919                                &old_number_of_fields);
2920}
2921
2922bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
2923                                 int target_inobject, int target_unused,
2924                                 int* old_number_of_fields) {
2925  // If fields were added (or removed), rewrite the instance.
2926  *old_number_of_fields = NumberOfFields();
2927  DCHECK(target_number_of_fields >= *old_number_of_fields);
2928  if (target_number_of_fields != *old_number_of_fields) return true;
2929
2930  // If smi descriptors were replaced by double descriptors, rewrite.
2931  DescriptorArray* old_desc = instance_descriptors();
2932  DescriptorArray* new_desc = target->instance_descriptors();
2933  int limit = NumberOfOwnDescriptors();
2934  for (int i = 0; i < limit; i++) {
2935    if (new_desc->GetDetails(i).representation().IsDouble() !=
2936        old_desc->GetDetails(i).representation().IsDouble()) {
2937      return true;
2938    }
2939  }
2940
2941  // If no fields were added, and no inobject properties were removed, setting
2942  // the map is sufficient.
2943  if (target_inobject == GetInObjectProperties()) return false;
2944  // In-object slack tracking may have reduced the object size of the new map.
2945  // In that case, succeed if all existing fields were inobject, and they still
2946  // fit within the new inobject size.
2947  DCHECK(target_inobject < GetInObjectProperties());
2948  if (target_number_of_fields <= target_inobject) {
2949    DCHECK(target_number_of_fields + target_unused == target_inobject);
2950    return false;
2951  }
2952  // Otherwise, properties will need to be moved to the backing store.
2953  return true;
2954}
2955
2956
2957// static
2958void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
2959                                               Handle<Map> new_map,
2960                                               Isolate* isolate) {
2961  if (!old_map->is_prototype_map()) return;
2962  DCHECK(new_map->is_prototype_map());
2963  bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
2964  new_map->set_prototype_info(old_map->prototype_info());
2965  old_map->set_prototype_info(Smi::FromInt(0));
2966  if (FLAG_trace_prototype_users) {
2967    PrintF("Moving prototype_info %p from map %p to map %p.\n",
2968           reinterpret_cast<void*>(new_map->prototype_info()),
2969           reinterpret_cast<void*>(*old_map),
2970           reinterpret_cast<void*>(*new_map));
2971  }
2972  if (was_registered) {
2973    if (new_map->prototype_info()->IsPrototypeInfo()) {
2974      // The new map isn't registered with its prototype yet; reflect this fact
2975      // in the PrototypeInfo it just inherited from the old map.
2976      PrototypeInfo::cast(new_map->prototype_info())
2977          ->set_registry_slot(PrototypeInfo::UNREGISTERED);
2978    }
2979    JSObject::LazyRegisterPrototypeUser(new_map, isolate);
2980  }
2981}
2982
2983namespace {
2984// To migrate a fast instance to a fast map:
2985// - First check whether the instance needs to be rewritten. If not, simply
2986//   change the map.
2987// - Otherwise, allocate a fixed array large enough to hold all fields, in
2988//   addition to unused space.
2989// - Copy all existing properties in, in the following order: backing store
2990//   properties, unused fields, inobject properties.
2991// - If all allocation succeeded, commit the state atomically:
2992//   * Copy inobject properties from the backing store back into the object.
2993//   * Trim the difference in instance size of the object. This also cleanly
2994//     frees inobject properties that moved to the backing store.
2995//   * If there are properties left in the backing store, trim of the space used
2996//     to temporarily store the inobject properties.
2997//   * If there are properties left in the backing store, install the backing
2998//     store.
2999void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
3000  Isolate* isolate = object->GetIsolate();
3001  Handle<Map> old_map(object->map());
3002  // In case of a regular transition.
3003  if (new_map->GetBackPointer() == *old_map) {
3004    // If the map does not add named properties, simply set the map.
3005    if (old_map->NumberOfOwnDescriptors() ==
3006        new_map->NumberOfOwnDescriptors()) {
3007      object->synchronized_set_map(*new_map);
3008      return;
3009    }
3010
3011    PropertyDetails details = new_map->GetLastDescriptorDetails();
3012    // Either new_map adds an kDescriptor property, or a kField property for
3013    // which there is still space, and which does not require a mutable double
3014    // box (an out-of-object double).
3015    if (details.location() == kDescriptor ||
3016        (old_map->unused_property_fields() > 0 &&
3017         ((FLAG_unbox_double_fields && object->properties()->length() == 0) ||
3018          !details.representation().IsDouble()))) {
3019      object->synchronized_set_map(*new_map);
3020      return;
3021    }
3022
3023    // If there is still space in the object, we need to allocate a mutable
3024    // double box.
3025    if (old_map->unused_property_fields() > 0) {
3026      FieldIndex index =
3027          FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
3028      DCHECK(details.representation().IsDouble());
3029      DCHECK(!new_map->IsUnboxedDoubleField(index));
3030      Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
3031      object->RawFastPropertyAtPut(index, *value);
3032      object->synchronized_set_map(*new_map);
3033      return;
3034    }
3035
3036    // This migration is a transition from a map that has run out of property
3037    // space. Extend the backing store.
3038    int grow_by = new_map->unused_property_fields() + 1;
3039    Handle<FixedArray> old_storage = handle(object->properties(), isolate);
3040    Handle<FixedArray> new_storage =
3041        isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
3042
3043    // Properly initialize newly added property.
3044    Handle<Object> value;
3045    if (details.representation().IsDouble()) {
3046      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
3047    } else {
3048      value = isolate->factory()->uninitialized_value();
3049    }
3050    DCHECK_EQ(DATA, details.type());
3051    int target_index = details.field_index() - new_map->GetInObjectProperties();
3052    DCHECK(target_index >= 0);  // Must be a backing store index.
3053    new_storage->set(target_index, *value);
3054
3055    // From here on we cannot fail and we shouldn't GC anymore.
3056    DisallowHeapAllocation no_allocation;
3057
3058    // Set the new property value and do the map transition.
3059    object->set_properties(*new_storage);
3060    object->synchronized_set_map(*new_map);
3061    return;
3062  }
3063
3064  int old_number_of_fields;
3065  int number_of_fields = new_map->NumberOfFields();
3066  int inobject = new_map->GetInObjectProperties();
3067  int unused = new_map->unused_property_fields();
3068
3069  // Nothing to do if no functions were converted to fields and no smis were
3070  // converted to doubles.
3071  if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
3072                                       unused, &old_number_of_fields)) {
3073    object->synchronized_set_map(*new_map);
3074    return;
3075  }
3076
3077  int total_size = number_of_fields + unused;
3078  int external = total_size - inobject;
3079
3080  Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
3081
3082  Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
3083  Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
3084  int old_nof = old_map->NumberOfOwnDescriptors();
3085  int new_nof = new_map->NumberOfOwnDescriptors();
3086
3087  // This method only supports generalizing instances to at least the same
3088  // number of properties.
3089  DCHECK(old_nof <= new_nof);
3090
3091  for (int i = 0; i < old_nof; i++) {
3092    PropertyDetails details = new_descriptors->GetDetails(i);
3093    if (details.type() != DATA) continue;
3094    PropertyDetails old_details = old_descriptors->GetDetails(i);
3095    Representation old_representation = old_details.representation();
3096    Representation representation = details.representation();
3097    Handle<Object> value;
3098    if (old_details.type() == ACCESSOR_CONSTANT) {
3099      // In case of kAccessor -> kData property reconfiguration, the property
3100      // must already be prepared for data or certain type.
3101      DCHECK(!details.representation().IsNone());
3102      if (details.representation().IsDouble()) {
3103        value = isolate->factory()->NewHeapNumber(0, MUTABLE);
3104      } else {
3105        value = isolate->factory()->uninitialized_value();
3106      }
3107    } else if (old_details.type() == DATA_CONSTANT) {
3108      value = handle(old_descriptors->GetValue(i), isolate);
3109      DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
3110    } else {
3111      FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
3112      if (object->IsUnboxedDoubleField(index)) {
3113        double old = object->RawFastDoublePropertyAt(index);
3114        value = isolate->factory()->NewHeapNumber(
3115            old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
3116
3117      } else {
3118        value = handle(object->RawFastPropertyAt(index), isolate);
3119        if (!old_representation.IsDouble() && representation.IsDouble()) {
3120          if (old_representation.IsNone()) {
3121            value = handle(Smi::FromInt(0), isolate);
3122          }
3123          value = Object::NewStorageFor(isolate, value, representation);
3124        } else if (old_representation.IsDouble() &&
3125                   !representation.IsDouble()) {
3126          value = Object::WrapForRead(isolate, value, old_representation);
3127        }
3128      }
3129    }
3130    DCHECK(!(representation.IsDouble() && value->IsSmi()));
3131    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
3132    if (target_index < 0) target_index += total_size;
3133    array->set(target_index, *value);
3134  }
3135
3136  for (int i = old_nof; i < new_nof; i++) {
3137    PropertyDetails details = new_descriptors->GetDetails(i);
3138    if (details.type() != DATA) continue;
3139    Handle<Object> value;
3140    if (details.representation().IsDouble()) {
3141      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
3142    } else {
3143      value = isolate->factory()->uninitialized_value();
3144    }
3145    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
3146    if (target_index < 0) target_index += total_size;
3147    array->set(target_index, *value);
3148  }
3149
3150  // From here on we cannot fail and we shouldn't GC anymore.
3151  DisallowHeapAllocation no_allocation;
3152
3153  Heap* heap = isolate->heap();
3154
3155  // Copy (real) inobject properties. If necessary, stop at number_of_fields to
3156  // avoid overwriting |one_pointer_filler_map|.
3157  int limit = Min(inobject, number_of_fields);
3158  for (int i = 0; i < limit; i++) {
3159    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
3160    Object* value = array->get(external + i);
3161    // Can't use JSObject::FastPropertyAtPut() because proper map was not set
3162    // yet.
3163    if (new_map->IsUnboxedDoubleField(index)) {
3164      DCHECK(value->IsMutableHeapNumber());
3165      object->RawFastDoublePropertyAtPut(index,
3166                                         HeapNumber::cast(value)->value());
3167      if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
3168        // Transition from tagged to untagged slot.
3169        heap->ClearRecordedSlot(*object,
3170                                HeapObject::RawField(*object, index.offset()));
3171      }
3172    } else {
3173      object->RawFastPropertyAtPut(index, value);
3174    }
3175  }
3176
3177
3178  // If there are properties in the new backing store, trim it to the correct
3179  // size and install the backing store into the object.
3180  if (external > 0) {
3181    heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
3182    object->set_properties(*array);
3183  }
3184
3185  // Create filler object past the new instance size.
3186  int new_instance_size = new_map->instance_size();
3187  int instance_size_delta = old_map->instance_size() - new_instance_size;
3188  DCHECK(instance_size_delta >= 0);
3189
3190  if (instance_size_delta > 0) {
3191    Address address = object->address();
3192    heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
3193                               ClearRecordedSlots::kYes);
3194    heap->AdjustLiveBytes(*object, -instance_size_delta,
3195                          Heap::CONCURRENT_TO_SWEEPER);
3196  }
3197
3198  // We are storing the new map using release store after creating a filler for
3199  // the left-over space to avoid races with the sweeper thread.
3200  object->synchronized_set_map(*new_map);
3201}
3202
3203void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
3204                       int expected_additional_properties) {
3205  // The global object is always normalized.
3206  DCHECK(!object->IsJSGlobalObject());
3207  // JSGlobalProxy must never be normalized
3208  DCHECK(!object->IsJSGlobalProxy());
3209
3210  Isolate* isolate = object->GetIsolate();
3211  HandleScope scope(isolate);
3212  Handle<Map> map(object->map());
3213
3214  // Allocate new content.
3215  int real_size = map->NumberOfOwnDescriptors();
3216  int property_count = real_size;
3217  if (expected_additional_properties > 0) {
3218    property_count += expected_additional_properties;
3219  } else {
3220    property_count += 2;  // Make space for two more properties.
3221  }
3222  Handle<NameDictionary> dictionary =
3223      NameDictionary::New(isolate, property_count);
3224
3225  Handle<DescriptorArray> descs(map->instance_descriptors());
3226  for (int i = 0; i < real_size; i++) {
3227    PropertyDetails details = descs->GetDetails(i);
3228    Handle<Name> key(descs->GetKey(i));
3229    switch (details.type()) {
3230      case DATA_CONSTANT: {
3231        Handle<Object> value(descs->GetConstant(i), isolate);
3232        PropertyDetails d(details.attributes(), DATA, i + 1,
3233                          PropertyCellType::kNoCell);
3234        dictionary = NameDictionary::Add(dictionary, key, value, d);
3235        break;
3236      }
3237      case DATA: {
3238        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
3239        Handle<Object> value;
3240        if (object->IsUnboxedDoubleField(index)) {
3241          double old_value = object->RawFastDoublePropertyAt(index);
3242          value = isolate->factory()->NewHeapNumber(old_value);
3243        } else {
3244          value = handle(object->RawFastPropertyAt(index), isolate);
3245          if (details.representation().IsDouble()) {
3246            DCHECK(value->IsMutableHeapNumber());
3247            Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
3248            value = isolate->factory()->NewHeapNumber(old->value());
3249          }
3250        }
3251        PropertyDetails d(details.attributes(), DATA, i + 1,
3252                          PropertyCellType::kNoCell);
3253        dictionary = NameDictionary::Add(dictionary, key, value, d);
3254        break;
3255      }
3256      case ACCESSOR: {
3257        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
3258        Handle<Object> value(object->RawFastPropertyAt(index), isolate);
3259        PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
3260                          PropertyCellType::kNoCell);
3261        dictionary = NameDictionary::Add(dictionary, key, value, d);
3262        break;
3263      }
3264      case ACCESSOR_CONSTANT: {
3265        Handle<Object> value(descs->GetCallbacksObject(i), isolate);
3266        PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
3267                          PropertyCellType::kNoCell);
3268        dictionary = NameDictionary::Add(dictionary, key, value, d);
3269        break;
3270      }
3271    }
3272  }
3273
3274  // Copy the next enumeration index from instance descriptor.
3275  dictionary->SetNextEnumerationIndex(real_size + 1);
3276
3277  // From here on we cannot fail and we shouldn't GC anymore.
3278  DisallowHeapAllocation no_allocation;
3279
3280  // Resize the object in the heap if necessary.
3281  int new_instance_size = new_map->instance_size();
3282  int instance_size_delta = map->instance_size() - new_instance_size;
3283  DCHECK(instance_size_delta >= 0);
3284
3285  if (instance_size_delta > 0) {
3286    Heap* heap = isolate->heap();
3287    heap->CreateFillerObjectAt(object->address() + new_instance_size,
3288                               instance_size_delta, ClearRecordedSlots::kYes);
3289    heap->AdjustLiveBytes(*object, -instance_size_delta,
3290                          Heap::CONCURRENT_TO_SWEEPER);
3291  }
3292
3293  // We are storing the new map using release store after creating a filler for
3294  // the left-over space to avoid races with the sweeper thread.
3295  object->synchronized_set_map(*new_map);
3296
3297  object->set_properties(*dictionary);
3298
3299  // Ensure that in-object space of slow-mode object does not contain random
3300  // garbage.
3301  int inobject_properties = new_map->GetInObjectProperties();
3302  for (int i = 0; i < inobject_properties; i++) {
3303    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
3304    object->RawFastPropertyAtPut(index, Smi::FromInt(0));
3305  }
3306
3307  isolate->counters()->props_to_dictionary()->Increment();
3308
3309#ifdef DEBUG
3310  if (FLAG_trace_normalization) {
3311    OFStream os(stdout);
3312    os << "Object properties have been normalized:\n";
3313    object->Print(os);
3314  }
3315#endif
3316}
3317
3318}  // namespace
3319
3320void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
3321                            int expected_additional_properties) {
3322  if (object->map() == *new_map) return;
3323  Handle<Map> old_map(object->map());
3324  if (old_map->is_prototype_map()) {
3325    // If this object is a prototype (the callee will check), invalidate any
3326    // prototype chains involving it.
3327    InvalidatePrototypeChains(object->map());
3328
3329    // If the map was registered with its prototype before, ensure that it
3330    // registers with its new prototype now. This preserves the invariant that
3331    // when a map on a prototype chain is registered with its prototype, then
3332    // all prototypes further up the chain are also registered with their
3333    // respective prototypes.
3334    UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate());
3335  }
3336
3337  if (old_map->is_dictionary_map()) {
3338    // For slow-to-fast migrations JSObject::MigrateSlowToFast()
3339    // must be used instead.
3340    CHECK(new_map->is_dictionary_map());
3341
3342    // Slow-to-slow migration is trivial.
3343    object->set_map(*new_map);
3344  } else if (!new_map->is_dictionary_map()) {
3345    MigrateFastToFast(object, new_map);
3346    if (old_map->is_prototype_map()) {
3347      DCHECK(!old_map->is_stable());
3348      DCHECK(new_map->is_stable());
3349      // Clear out the old descriptor array to avoid problems to sharing
3350      // the descriptor array without using an explicit.
3351      old_map->InitializeDescriptors(
3352          old_map->GetHeap()->empty_descriptor_array(),
3353          LayoutDescriptor::FastPointerLayout());
3354      // Ensure that no transition was inserted for prototype migrations.
3355      DCHECK_EQ(
3356          0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
3357      DCHECK(new_map->GetBackPointer()->IsUndefined(new_map->GetIsolate()));
3358    }
3359  } else {
3360    MigrateFastToSlow(object, new_map, expected_additional_properties);
3361  }
3362
3363  // Careful: Don't allocate here!
3364  // For some callers of this method, |object| might be in an inconsistent
3365  // state now: the new map might have a new elements_kind, but the object's
3366  // elements pointer hasn't been updated yet. Callers will fix this, but in
3367  // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
3368  // When adding code here, add a DisallowHeapAllocation too.
3369}
3370
3371int Map::NumberOfFields() {
3372  DescriptorArray* descriptors = instance_descriptors();
3373  int result = 0;
3374  for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
3375    if (descriptors->GetDetails(i).location() == kField) result++;
3376  }
3377  return result;
3378}
3379
3380Handle<Map> Map::CopyGeneralizeAllRepresentations(
3381    Handle<Map> map, ElementsKind elements_kind, int modify_index,
3382    StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
3383    const char* reason) {
3384  Isolate* isolate = map->GetIsolate();
3385  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3386  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3387  Handle<DescriptorArray> descriptors =
3388      DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3389
3390  for (int i = 0; i < number_of_own_descriptors; i++) {
3391    descriptors->SetRepresentation(i, Representation::Tagged());
3392    if (descriptors->GetDetails(i).type() == DATA) {
3393      descriptors->SetValue(i, FieldType::Any());
3394    }
3395  }
3396
3397  Handle<LayoutDescriptor> new_layout_descriptor(
3398      LayoutDescriptor::FastPointerLayout(), isolate);
3399  Handle<Map> new_map = CopyReplaceDescriptors(
3400      map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
3401      MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
3402
3403  // Unless the instance is being migrated, ensure that modify_index is a field.
3404  if (modify_index >= 0) {
3405    PropertyDetails details = descriptors->GetDetails(modify_index);
3406    if (store_mode == FORCE_FIELD &&
3407        (details.type() != DATA || details.attributes() != attributes)) {
3408      int field_index = details.type() == DATA ? details.field_index()
3409                                               : new_map->NumberOfFields();
3410      DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
3411                       field_index, attributes, Representation::Tagged());
3412      descriptors->Replace(modify_index, &d);
3413      if (details.type() != DATA) {
3414        int unused_property_fields = new_map->unused_property_fields() - 1;
3415        if (unused_property_fields < 0) {
3416          unused_property_fields += JSObject::kFieldsAdded;
3417        }
3418        new_map->set_unused_property_fields(unused_property_fields);
3419      }
3420    } else {
3421      DCHECK(details.attributes() == attributes);
3422    }
3423
3424    if (FLAG_trace_generalization) {
3425      MaybeHandle<FieldType> field_type = FieldType::None(isolate);
3426      if (details.type() == DATA) {
3427        field_type = handle(
3428            map->instance_descriptors()->GetFieldType(modify_index), isolate);
3429      }
3430      map->PrintGeneralization(
3431          stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
3432          new_map->NumberOfOwnDescriptors(),
3433          details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
3434          details.representation(), Representation::Tagged(), field_type,
3435          MaybeHandle<Object>(), FieldType::Any(isolate),
3436          MaybeHandle<Object>());
3437    }
3438  }
3439  new_map->set_elements_kind(elements_kind);
3440  return new_map;
3441}
3442
3443
3444void Map::DeprecateTransitionTree() {
3445  if (is_deprecated()) return;
3446  Object* transitions = raw_transitions();
3447  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3448  for (int i = 0; i < num_transitions; ++i) {
3449    TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
3450  }
3451  deprecate();
3452  dependent_code()->DeoptimizeDependentCodeGroup(
3453      GetIsolate(), DependentCode::kTransitionGroup);
3454  NotifyLeafMapLayoutChange();
3455}
3456
3457
3458static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
3459  if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
3460  // TODO(ishell): compare AccessorPairs.
3461  return false;
3462}
3463
3464
3465// Installs |new_descriptors| over the current instance_descriptors to ensure
3466// proper sharing of descriptor arrays.
3467void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
3468                             LayoutDescriptor* new_layout_descriptor) {
3469  Isolate* isolate = GetIsolate();
3470  // Don't overwrite the empty descriptor array or initial map's descriptors.
3471  if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
3472    return;
3473  }
3474
3475  DescriptorArray* to_replace = instance_descriptors();
3476  isolate->heap()->incremental_marking()->IterateBlackObject(to_replace);
3477  Map* current = this;
3478  while (current->instance_descriptors() == to_replace) {
3479    Object* next = current->GetBackPointer();
3480    if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
3481    current->SetEnumLength(kInvalidEnumCacheSentinel);
3482    current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
3483    current = Map::cast(next);
3484  }
3485  set_owns_descriptors(false);
3486}
3487
3488
3489Map* Map::FindRootMap() {
3490  Map* result = this;
3491  Isolate* isolate = GetIsolate();
3492  while (true) {
3493    Object* back = result->GetBackPointer();
3494    if (back->IsUndefined(isolate)) {
3495      // Initial map always owns descriptors and doesn't have unused entries
3496      // in the descriptor array.
3497      DCHECK(result->owns_descriptors());
3498      DCHECK_EQ(result->NumberOfOwnDescriptors(),
3499                result->instance_descriptors()->number_of_descriptors());
3500      return result;
3501    }
3502    result = Map::cast(back);
3503  }
3504}
3505
3506
3507Map* Map::FindLastMatchMap(int verbatim,
3508                           int length,
3509                           DescriptorArray* descriptors) {
3510  DisallowHeapAllocation no_allocation;
3511
3512  // This can only be called on roots of transition trees.
3513  DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
3514
3515  Map* current = this;
3516
3517  for (int i = verbatim; i < length; i++) {
3518    Name* name = descriptors->GetKey(i);
3519    PropertyDetails details = descriptors->GetDetails(i);
3520    Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
3521                                                  details.attributes());
3522    if (next == NULL) break;
3523    DescriptorArray* next_descriptors = next->instance_descriptors();
3524
3525    PropertyDetails next_details = next_descriptors->GetDetails(i);
3526    DCHECK_EQ(details.kind(), next_details.kind());
3527    DCHECK_EQ(details.attributes(), next_details.attributes());
3528    if (details.location() != next_details.location()) break;
3529    if (!details.representation().Equals(next_details.representation())) break;
3530
3531    if (next_details.location() == kField) {
3532      FieldType* next_field_type = next_descriptors->GetFieldType(i);
3533      if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
3534        break;
3535      }
3536    } else {
3537      if (!EqualImmutableValues(descriptors->GetValue(i),
3538                                next_descriptors->GetValue(i))) {
3539        break;
3540      }
3541    }
3542    current = next;
3543  }
3544  return current;
3545}
3546
3547
3548Map* Map::FindFieldOwner(int descriptor) {
3549  DisallowHeapAllocation no_allocation;
3550  DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
3551  Map* result = this;
3552  Isolate* isolate = GetIsolate();
3553  while (true) {
3554    Object* back = result->GetBackPointer();
3555    if (back->IsUndefined(isolate)) break;
3556    Map* parent = Map::cast(back);
3557    if (parent->NumberOfOwnDescriptors() <= descriptor) break;
3558    result = parent;
3559  }
3560  return result;
3561}
3562
3563
3564void Map::UpdateFieldType(int descriptor, Handle<Name> name,
3565                          Representation new_representation,
3566                          Handle<Object> new_wrapped_type) {
3567  DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
3568  // We store raw pointers in the queue, so no allocations are allowed.
3569  DisallowHeapAllocation no_allocation;
3570  PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
3571  if (details.type() != DATA) return;
3572
3573  Zone zone(GetIsolate()->allocator());
3574  ZoneQueue<Map*> backlog(&zone);
3575  backlog.push(this);
3576
3577  while (!backlog.empty()) {
3578    Map* current = backlog.front();
3579    backlog.pop();
3580
3581    Object* transitions = current->raw_transitions();
3582    int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3583    for (int i = 0; i < num_transitions; ++i) {
3584      Map* target = TransitionArray::GetTarget(transitions, i);
3585      backlog.push(target);
3586    }
3587    DescriptorArray* descriptors = current->instance_descriptors();
3588    PropertyDetails details = descriptors->GetDetails(descriptor);
3589
3590    // It is allowed to change representation here only from None to something.
3591    DCHECK(details.representation().Equals(new_representation) ||
3592           details.representation().IsNone());
3593
3594    // Skip if already updated the shared descriptor.
3595    if (descriptors->GetValue(descriptor) != *new_wrapped_type) {
3596      DataDescriptor d(name, descriptors->GetFieldIndex(descriptor),
3597                       new_wrapped_type, details.attributes(),
3598                       new_representation);
3599      descriptors->Replace(descriptor, &d);
3600    }
3601  }
3602}
3603
3604bool FieldTypeIsCleared(Representation rep, FieldType* type) {
3605  return type->IsNone() && rep.IsHeapObject();
3606}
3607
3608
3609// static
3610Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
3611                                           Handle<FieldType> type1,
3612                                           Representation rep2,
3613                                           Handle<FieldType> type2,
3614                                           Isolate* isolate) {
3615  // Cleared field types need special treatment. They represent lost knowledge,
3616  // so we must be conservative, so their generalization with any other type
3617  // is "Any".
3618  if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
3619    return FieldType::Any(isolate);
3620  }
3621  if (type1->NowIs(type2)) return type2;
3622  if (type2->NowIs(type1)) return type1;
3623  return FieldType::Any(isolate);
3624}
3625
3626
3627// static
3628void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
3629                              Representation new_representation,
3630                              Handle<FieldType> new_field_type) {
3631  Isolate* isolate = map->GetIsolate();
3632
3633  // Check if we actually need to generalize the field type at all.
3634  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3635  Representation old_representation =
3636      old_descriptors->GetDetails(modify_index).representation();
3637  Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
3638                                   isolate);
3639
3640  if (old_representation.Equals(new_representation) &&
3641      !FieldTypeIsCleared(new_representation, *new_field_type) &&
3642      // Checking old_field_type for being cleared is not necessary because
3643      // the NowIs check below would fail anyway in that case.
3644      new_field_type->NowIs(old_field_type)) {
3645    DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type,
3646                                    new_representation, new_field_type, isolate)
3647               ->NowIs(old_field_type));
3648    return;
3649  }
3650
3651  // Determine the field owner.
3652  Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
3653  Handle<DescriptorArray> descriptors(
3654      field_owner->instance_descriptors(), isolate);
3655  DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
3656
3657  new_field_type =
3658      Map::GeneralizeFieldType(old_representation, old_field_type,
3659                               new_representation, new_field_type, isolate);
3660
3661  PropertyDetails details = descriptors->GetDetails(modify_index);
3662  Handle<Name> name(descriptors->GetKey(modify_index));
3663
3664  Handle<Object> wrapped_type(WrapType(new_field_type));
3665  field_owner->UpdateFieldType(modify_index, name, new_representation,
3666                               wrapped_type);
3667  field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
3668      isolate, DependentCode::kFieldTypeGroup);
3669
3670  if (FLAG_trace_generalization) {
3671    map->PrintGeneralization(
3672        stdout, "field type generalization", modify_index,
3673        map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
3674        details.representation(), details.representation(), old_field_type,
3675        MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
3676  }
3677}
3678
3679static inline Handle<FieldType> GetFieldType(
3680    Isolate* isolate, Handle<DescriptorArray> descriptors, int descriptor,
3681    PropertyLocation location, Representation representation) {
3682#ifdef DEBUG
3683  PropertyDetails details = descriptors->GetDetails(descriptor);
3684  DCHECK_EQ(kData, details.kind());
3685  DCHECK_EQ(details.location(), location);
3686#endif
3687  if (location == kField) {
3688    return handle(descriptors->GetFieldType(descriptor), isolate);
3689  } else {
3690    return descriptors->GetValue(descriptor)
3691        ->OptimalType(isolate, representation);
3692  }
3693}
3694
3695// Reconfigures elements kind to |new_elements_kind| and/or property at
3696// |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
3697// |new_representation|/|new_field_type|.
3698// If |modify_index| is negative then no properties are reconfigured but the
3699// map is migrated to the up-to-date non-deprecated state.
3700//
3701// This method rewrites or completes the transition tree to reflect the new
3702// change. To avoid high degrees over polymorphism, and to stabilize quickly,
3703// on every rewrite the new type is deduced by merging the current type with
3704// any potential new (partial) version of the type in the transition tree.
3705// To do this, on each rewrite:
3706// - Search the root of the transition tree using FindRootMap.
3707// - Find/create a |root_map| with requested |new_elements_kind|.
3708// - Find |target_map|, the newest matching version of this map using the
3709//   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
3710//   |modify_index| is considered to be of |new_kind| and having
3711//   |new_attributes|) to walk the transition tree.
3712// - Merge/generalize the "enhanced" descriptor array of the |old_map| and
3713//   descriptor array of the |target_map|.
3714// - Generalize the |modify_index| descriptor using |new_representation| and
3715//   |new_field_type|.
3716// - Walk the tree again starting from the root towards |target_map|. Stop at
3717//   |split_map|, the first map who's descriptor array does not match the merged
3718//   descriptor array.
3719// - If |target_map| == |split_map|, |target_map| is in the expected state.
3720//   Return it.
3721// - Otherwise, invalidate the outdated transition target from |target_map|, and
3722//   replace its transition tree with a new branch for the updated descriptors.
3723Handle<Map> Map::Reconfigure(Handle<Map> old_map,
3724                             ElementsKind new_elements_kind, int modify_index,
3725                             PropertyKind new_kind,
3726                             PropertyAttributes new_attributes,
3727                             Representation new_representation,
3728                             Handle<FieldType> new_field_type,
3729                             StoreMode store_mode) {
3730  DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
3731  DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
3732  Isolate* isolate = old_map->GetIsolate();
3733
3734  Handle<DescriptorArray> old_descriptors(
3735      old_map->instance_descriptors(), isolate);
3736  int old_nof = old_map->NumberOfOwnDescriptors();
3737
3738  // If it's just a representation generalization case (i.e. property kind and
3739  // attributes stays unchanged) it's fine to transition from None to anything
3740  // but double without any modification to the object, because the default
3741  // uninitialized value for representation None can be overwritten by both
3742  // smi and tagged values. Doubles, however, would require a box allocation.
3743  if (modify_index >= 0 && !new_representation.IsNone() &&
3744      !new_representation.IsDouble() &&
3745      old_map->elements_kind() == new_elements_kind) {
3746    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3747    Representation old_representation = old_details.representation();
3748
3749    if (old_representation.IsNone()) {
3750      DCHECK_EQ(new_kind, old_details.kind());
3751      DCHECK_EQ(new_attributes, old_details.attributes());
3752      DCHECK_EQ(DATA, old_details.type());
3753      if (FLAG_trace_generalization) {
3754        old_map->PrintGeneralization(
3755            stdout, "uninitialized field", modify_index,
3756            old_map->NumberOfOwnDescriptors(),
3757            old_map->NumberOfOwnDescriptors(), false, old_representation,
3758            new_representation,
3759            handle(old_descriptors->GetFieldType(modify_index), isolate),
3760            MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
3761      }
3762      Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
3763
3764      GeneralizeFieldType(field_owner, modify_index, new_representation,
3765                          new_field_type);
3766      DCHECK(old_descriptors->GetDetails(modify_index)
3767                 .representation()
3768                 .Equals(new_representation));
3769      DCHECK(
3770          old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
3771      return old_map;
3772    }
3773  }
3774
3775  // Check the state of the root map.
3776  Handle<Map> root_map(old_map->FindRootMap(), isolate);
3777  if (!old_map->EquivalentToForTransition(*root_map)) {
3778    return CopyGeneralizeAllRepresentations(
3779        old_map, new_elements_kind, modify_index, store_mode, new_kind,
3780        new_attributes, "GenAll_NotEquivalent");
3781  }
3782
3783  ElementsKind from_kind = root_map->elements_kind();
3784  ElementsKind to_kind = new_elements_kind;
3785  // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
3786  if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
3787      to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
3788      to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
3789      !(IsTransitionableFastElementsKind(from_kind) &&
3790        IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
3791    return CopyGeneralizeAllRepresentations(
3792        old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3793        "GenAll_InvalidElementsTransition");
3794  }
3795  int root_nof = root_map->NumberOfOwnDescriptors();
3796  if (modify_index >= 0 && modify_index < root_nof) {
3797    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3798    if (old_details.kind() != new_kind ||
3799        old_details.attributes() != new_attributes) {
3800      return CopyGeneralizeAllRepresentations(
3801          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3802          "GenAll_RootModification1");
3803    }
3804    if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
3805        (old_details.type() == DATA &&
3806         (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
3807          !new_representation.fits_into(old_details.representation())))) {
3808      return CopyGeneralizeAllRepresentations(
3809          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3810          "GenAll_RootModification2");
3811    }
3812  }
3813
3814  // From here on, use the map with correct elements kind as root map.
3815  if (from_kind != to_kind) {
3816    root_map = Map::AsElementsKind(root_map, to_kind);
3817  }
3818
3819  Handle<Map> target_map = root_map;
3820  for (int i = root_nof; i < old_nof; ++i) {
3821    PropertyDetails old_details = old_descriptors->GetDetails(i);
3822    PropertyKind next_kind;
3823    PropertyLocation next_location;
3824    PropertyAttributes next_attributes;
3825    Representation next_representation;
3826    bool property_kind_reconfiguration = false;
3827
3828    if (modify_index == i) {
3829      DCHECK_EQ(FORCE_FIELD, store_mode);
3830      property_kind_reconfiguration = old_details.kind() != new_kind;
3831
3832      next_kind = new_kind;
3833      next_location = kField;
3834      next_attributes = new_attributes;
3835      // If property kind is not reconfigured merge the result with
3836      // representation/field type from the old descriptor.
3837      next_representation = new_representation;
3838      if (!property_kind_reconfiguration) {
3839        next_representation =
3840            next_representation.generalize(old_details.representation());
3841      }
3842
3843    } else {
3844      next_kind = old_details.kind();
3845      next_location = old_details.location();
3846      next_attributes = old_details.attributes();
3847      next_representation = old_details.representation();
3848    }
3849    Map* transition = TransitionArray::SearchTransition(
3850        *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
3851    if (transition == NULL) break;
3852    Handle<Map> tmp_map(transition, isolate);
3853
3854    Handle<DescriptorArray> tmp_descriptors = handle(
3855        tmp_map->instance_descriptors(), isolate);
3856
3857    // Check if target map is incompatible.
3858    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3859    DCHECK_EQ(next_kind, tmp_details.kind());
3860    DCHECK_EQ(next_attributes, tmp_details.attributes());
3861    if (next_kind == kAccessor &&
3862        !EqualImmutableValues(old_descriptors->GetValue(i),
3863                              tmp_descriptors->GetValue(i))) {
3864      return CopyGeneralizeAllRepresentations(
3865          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3866          "GenAll_Incompatible");
3867    }
3868    if (next_location == kField && tmp_details.location() == kDescriptor) break;
3869
3870    Representation tmp_representation = tmp_details.representation();
3871    if (!next_representation.fits_into(tmp_representation)) break;
3872
3873    PropertyLocation old_location = old_details.location();
3874    PropertyLocation tmp_location = tmp_details.location();
3875    if (tmp_location == kField) {
3876      if (next_kind == kData) {
3877        Handle<FieldType> next_field_type;
3878        if (modify_index == i) {
3879          next_field_type = new_field_type;
3880          if (!property_kind_reconfiguration) {
3881            Handle<FieldType> old_field_type =
3882                GetFieldType(isolate, old_descriptors, i,
3883                             old_details.location(), tmp_representation);
3884            Representation old_representation = old_details.representation();
3885            next_field_type = GeneralizeFieldType(
3886                old_representation, old_field_type, new_representation,
3887                next_field_type, isolate);
3888          }
3889        } else {
3890          Handle<FieldType> old_field_type =
3891              GetFieldType(isolate, old_descriptors, i, old_details.location(),
3892                           tmp_representation);
3893          next_field_type = old_field_type;
3894        }
3895        GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
3896      }
3897    } else if (old_location == kField ||
3898               !EqualImmutableValues(old_descriptors->GetValue(i),
3899                                     tmp_descriptors->GetValue(i))) {
3900      break;
3901    }
3902    DCHECK(!tmp_map->is_deprecated());
3903    target_map = tmp_map;
3904  }
3905
3906  // Directly change the map if the target map is more general.
3907  Handle<DescriptorArray> target_descriptors(
3908      target_map->instance_descriptors(), isolate);
3909  int target_nof = target_map->NumberOfOwnDescriptors();
3910  if (target_nof == old_nof &&
3911      (store_mode != FORCE_FIELD ||
3912       (modify_index >= 0 &&
3913        target_descriptors->GetDetails(modify_index).location() == kField))) {
3914#ifdef DEBUG
3915    if (modify_index >= 0) {
3916      PropertyDetails details = target_descriptors->GetDetails(modify_index);
3917      DCHECK_EQ(new_kind, details.kind());
3918      DCHECK_EQ(new_attributes, details.attributes());
3919      DCHECK(new_representation.fits_into(details.representation()));
3920      DCHECK(details.location() != kField ||
3921             new_field_type->NowIs(
3922                 target_descriptors->GetFieldType(modify_index)));
3923    }
3924#endif
3925    if (*target_map != *old_map) {
3926      old_map->NotifyLeafMapLayoutChange();
3927    }
3928    return target_map;
3929  }
3930
3931  // Find the last compatible target map in the transition tree.
3932  for (int i = target_nof; i < old_nof; ++i) {
3933    PropertyDetails old_details = old_descriptors->GetDetails(i);
3934    PropertyKind next_kind;
3935    PropertyAttributes next_attributes;
3936    if (modify_index == i) {
3937      next_kind = new_kind;
3938      next_attributes = new_attributes;
3939    } else {
3940      next_kind = old_details.kind();
3941      next_attributes = old_details.attributes();
3942    }
3943    Map* transition = TransitionArray::SearchTransition(
3944        *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
3945    if (transition == NULL) break;
3946    Handle<Map> tmp_map(transition, isolate);
3947    Handle<DescriptorArray> tmp_descriptors(
3948        tmp_map->instance_descriptors(), isolate);
3949
3950    // Check if target map is compatible.
3951#ifdef DEBUG
3952    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3953    DCHECK_EQ(next_kind, tmp_details.kind());
3954    DCHECK_EQ(next_attributes, tmp_details.attributes());
3955#endif
3956    if (next_kind == kAccessor &&
3957        !EqualImmutableValues(old_descriptors->GetValue(i),
3958                              tmp_descriptors->GetValue(i))) {
3959      return CopyGeneralizeAllRepresentations(
3960          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
3961          "GenAll_Incompatible");
3962    }
3963    DCHECK(!tmp_map->is_deprecated());
3964    target_map = tmp_map;
3965  }
3966  target_nof = target_map->NumberOfOwnDescriptors();
3967  target_descriptors = handle(target_map->instance_descriptors(), isolate);
3968
3969  // Allocate a new descriptor array large enough to hold the required
3970  // descriptors, with minimally the exact same size as the old descriptor
3971  // array.
3972  int new_slack = Max(
3973      old_nof, old_descriptors->number_of_descriptors()) - old_nof;
3974  Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
3975      isolate, old_nof, new_slack);
3976  DCHECK(new_descriptors->length() > target_descriptors->length() ||
3977         new_descriptors->NumberOfSlackDescriptors() > 0 ||
3978         new_descriptors->number_of_descriptors() ==
3979         old_descriptors->number_of_descriptors());
3980  DCHECK(new_descriptors->number_of_descriptors() == old_nof);
3981
3982  // 0 -> |root_nof|
3983  int current_offset = 0;
3984  for (int i = 0; i < root_nof; ++i) {
3985    PropertyDetails old_details = old_descriptors->GetDetails(i);
3986    if (old_details.location() == kField) {
3987      current_offset += old_details.field_width_in_words();
3988    }
3989    Descriptor d(handle(old_descriptors->GetKey(i), isolate),
3990                 handle(old_descriptors->GetValue(i), isolate),
3991                 old_details);
3992    new_descriptors->Set(i, &d);
3993  }
3994
3995  // |root_nof| -> |target_nof|
3996  for (int i = root_nof; i < target_nof; ++i) {
3997    Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
3998    PropertyDetails old_details = old_descriptors->GetDetails(i);
3999    PropertyDetails target_details = target_descriptors->GetDetails(i);
4000
4001    PropertyKind next_kind;
4002    PropertyAttributes next_attributes;
4003    PropertyLocation next_location;
4004    Representation next_representation;
4005    bool property_kind_reconfiguration = false;
4006
4007    if (modify_index == i) {
4008      DCHECK_EQ(FORCE_FIELD, store_mode);
4009      property_kind_reconfiguration = old_details.kind() != new_kind;
4010
4011      next_kind = new_kind;
4012      next_attributes = new_attributes;
4013      next_location = kField;
4014
4015      // Merge new representation/field type with ones from the target
4016      // descriptor. If property kind is not reconfigured merge the result with
4017      // representation/field type from the old descriptor.
4018      next_representation =
4019          new_representation.generalize(target_details.representation());
4020      if (!property_kind_reconfiguration) {
4021        next_representation =
4022            next_representation.generalize(old_details.representation());
4023      }
4024    } else {
4025      // Merge old_descriptor and target_descriptor entries.
4026      DCHECK_EQ(target_details.kind(), old_details.kind());
4027      next_kind = target_details.kind();
4028      next_attributes = target_details.attributes();
4029      next_location =
4030          old_details.location() == kField ||
4031                  target_details.location() == kField ||
4032                  !EqualImmutableValues(target_descriptors->GetValue(i),
4033                                        old_descriptors->GetValue(i))
4034              ? kField
4035              : kDescriptor;
4036
4037      next_representation = old_details.representation().generalize(
4038          target_details.representation());
4039    }
4040    DCHECK_EQ(next_kind, target_details.kind());
4041    DCHECK_EQ(next_attributes, target_details.attributes());
4042
4043    if (next_location == kField) {
4044      if (next_kind == kData) {
4045        Handle<FieldType> target_field_type =
4046            GetFieldType(isolate, target_descriptors, i,
4047                         target_details.location(), next_representation);
4048
4049        Handle<FieldType> next_field_type;
4050        if (modify_index == i) {
4051          next_field_type = GeneralizeFieldType(
4052              target_details.representation(), target_field_type,
4053              new_representation, new_field_type, isolate);
4054          if (!property_kind_reconfiguration) {
4055            Handle<FieldType> old_field_type =
4056                GetFieldType(isolate, old_descriptors, i,
4057                             old_details.location(), next_representation);
4058            next_field_type = GeneralizeFieldType(
4059                old_details.representation(), old_field_type,
4060                next_representation, next_field_type, isolate);
4061          }
4062        } else {
4063          Handle<FieldType> old_field_type =
4064              GetFieldType(isolate, old_descriptors, i, old_details.location(),
4065                           next_representation);
4066          next_field_type = GeneralizeFieldType(
4067              old_details.representation(), old_field_type, next_representation,
4068              target_field_type, isolate);
4069        }
4070        Handle<Object> wrapped_type(WrapType(next_field_type));
4071        DataDescriptor d(target_key, current_offset, wrapped_type,
4072                         next_attributes, next_representation);
4073        current_offset += d.GetDetails().field_width_in_words();
4074        new_descriptors->Set(i, &d);
4075      } else {
4076        UNIMPLEMENTED();  // TODO(ishell): implement.
4077      }
4078    } else {
4079      PropertyDetails details(next_attributes, next_kind, next_location,
4080                              next_representation);
4081      Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
4082                   details);
4083      new_descriptors->Set(i, &d);
4084    }
4085  }
4086
4087  // |target_nof| -> |old_nof|
4088  for (int i = target_nof; i < old_nof; ++i) {
4089    PropertyDetails old_details = old_descriptors->GetDetails(i);
4090    Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
4091
4092    // Merge old_descriptor entry and modified details together.
4093    PropertyKind next_kind;
4094    PropertyAttributes next_attributes;
4095    PropertyLocation next_location;
4096    Representation next_representation;
4097    bool property_kind_reconfiguration = false;
4098
4099    if (modify_index == i) {
4100      DCHECK_EQ(FORCE_FIELD, store_mode);
4101      // In case of property kind reconfiguration it is not necessary to
4102      // take into account representation/field type of the old descriptor.
4103      property_kind_reconfiguration = old_details.kind() != new_kind;
4104
4105      next_kind = new_kind;
4106      next_attributes = new_attributes;
4107      next_location = kField;
4108      next_representation = new_representation;
4109      if (!property_kind_reconfiguration) {
4110        next_representation =
4111            next_representation.generalize(old_details.representation());
4112      }
4113    } else {
4114      next_kind = old_details.kind();
4115      next_attributes = old_details.attributes();
4116      next_location = old_details.location();
4117      next_representation = old_details.representation();
4118    }
4119
4120    if (next_location == kField) {
4121      if (next_kind == kData) {
4122        Handle<FieldType> next_field_type;
4123        if (modify_index == i) {
4124          next_field_type = new_field_type;
4125          if (!property_kind_reconfiguration) {
4126            Handle<FieldType> old_field_type =
4127                GetFieldType(isolate, old_descriptors, i,
4128                             old_details.location(), next_representation);
4129            next_field_type = GeneralizeFieldType(
4130                old_details.representation(), old_field_type,
4131                next_representation, next_field_type, isolate);
4132          }
4133        } else {
4134          Handle<FieldType> old_field_type =
4135              GetFieldType(isolate, old_descriptors, i, old_details.location(),
4136                           next_representation);
4137          next_field_type = old_field_type;
4138        }
4139
4140        Handle<Object> wrapped_type(WrapType(next_field_type));
4141
4142        DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
4143                         next_representation);
4144        current_offset += d.GetDetails().field_width_in_words();
4145        new_descriptors->Set(i, &d);
4146      } else {
4147        UNIMPLEMENTED();  // TODO(ishell): implement.
4148      }
4149    } else {
4150      PropertyDetails details(next_attributes, next_kind, next_location,
4151                              next_representation);
4152      Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
4153                   details);
4154      new_descriptors->Set(i, &d);
4155    }
4156  }
4157
4158  new_descriptors->Sort();
4159
4160  DCHECK(store_mode != FORCE_FIELD ||
4161         new_descriptors->GetDetails(modify_index).location() == kField);
4162
4163  Handle<Map> split_map(root_map->FindLastMatchMap(
4164          root_nof, old_nof, *new_descriptors), isolate);
4165  int split_nof = split_map->NumberOfOwnDescriptors();
4166  DCHECK_NE(old_nof, split_nof);
4167
4168  PropertyKind split_kind;
4169  PropertyAttributes split_attributes;
4170  if (modify_index == split_nof) {
4171    split_kind = new_kind;
4172    split_attributes = new_attributes;
4173  } else {
4174    PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
4175    split_kind = split_prop_details.kind();
4176    split_attributes = split_prop_details.attributes();
4177  }
4178
4179  // Invalidate a transition target at |key|.
4180  Map* maybe_transition = TransitionArray::SearchTransition(
4181      *split_map, split_kind, old_descriptors->GetKey(split_nof),
4182      split_attributes);
4183  if (maybe_transition != NULL) {
4184    maybe_transition->DeprecateTransitionTree();
4185  }
4186
4187  // If |maybe_transition| is not NULL then the transition array already
4188  // contains entry for given descriptor. This means that the transition
4189  // could be inserted regardless of whether transitions array is full or not.
4190  if (maybe_transition == NULL &&
4191      !TransitionArray::CanHaveMoreTransitions(split_map)) {
4192    return CopyGeneralizeAllRepresentations(
4193        old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
4194        "GenAll_CantHaveMoreTransitions");
4195  }
4196
4197  old_map->NotifyLeafMapLayoutChange();
4198
4199  if (FLAG_trace_generalization && modify_index >= 0) {
4200    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
4201    PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
4202    MaybeHandle<FieldType> old_field_type;
4203    MaybeHandle<FieldType> new_field_type;
4204    MaybeHandle<Object> old_value;
4205    MaybeHandle<Object> new_value;
4206    if (old_details.type() == DATA) {
4207      old_field_type =
4208          handle(old_descriptors->GetFieldType(modify_index), isolate);
4209    } else {
4210      old_value = handle(old_descriptors->GetValue(modify_index), isolate);
4211    }
4212    if (new_details.type() == DATA) {
4213      new_field_type =
4214          handle(new_descriptors->GetFieldType(modify_index), isolate);
4215    } else {
4216      new_value = handle(new_descriptors->GetValue(modify_index), isolate);
4217    }
4218
4219    old_map->PrintGeneralization(
4220        stdout, "", modify_index, split_nof, old_nof,
4221        old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
4222        old_details.representation(), new_details.representation(),
4223        old_field_type, old_value, new_field_type, new_value);
4224  }
4225
4226  Handle<LayoutDescriptor> new_layout_descriptor =
4227      LayoutDescriptor::New(split_map, new_descriptors, old_nof);
4228
4229  Handle<Map> new_map =
4230      AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
4231
4232  // Deprecated part of the transition tree is no longer reachable, so replace
4233  // current instance descriptors in the "survived" part of the tree with
4234  // the new descriptors to maintain descriptors sharing invariant.
4235  split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
4236  return new_map;
4237}
4238
4239
4240// Generalize the representation of all DATA descriptors.
4241Handle<Map> Map::GeneralizeAllFieldRepresentations(
4242    Handle<Map> map) {
4243  Handle<DescriptorArray> descriptors(map->instance_descriptors());
4244  for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
4245    PropertyDetails details = descriptors->GetDetails(i);
4246    if (details.type() == DATA) {
4247      map = ReconfigureProperty(map, i, kData, details.attributes(),
4248                                Representation::Tagged(),
4249                                FieldType::Any(map->GetIsolate()), FORCE_FIELD);
4250    }
4251  }
4252  return map;
4253}
4254
4255
4256// static
4257MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
4258  DisallowHeapAllocation no_allocation;
4259  DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
4260
4261  if (!old_map->is_deprecated()) return old_map;
4262
4263  // Check the state of the root map.
4264  Map* root_map = old_map->FindRootMap();
4265  if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
4266
4267  ElementsKind from_kind = root_map->elements_kind();
4268  ElementsKind to_kind = old_map->elements_kind();
4269  if (from_kind != to_kind) {
4270    // Try to follow existing elements kind transitions.
4271    root_map = root_map->LookupElementsTransitionMap(to_kind);
4272    if (root_map == NULL) return MaybeHandle<Map>();
4273    // From here on, use the map with correct elements kind as root map.
4274  }
4275  Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
4276  if (new_map == nullptr) return MaybeHandle<Map>();
4277  return handle(new_map);
4278}
4279
4280Map* Map::TryReplayPropertyTransitions(Map* old_map) {
4281  DisallowHeapAllocation no_allocation;
4282  DisallowDeoptimization no_deoptimization(GetIsolate());
4283
4284  int root_nof = NumberOfOwnDescriptors();
4285
4286  int old_nof = old_map->NumberOfOwnDescriptors();
4287  DescriptorArray* old_descriptors = old_map->instance_descriptors();
4288
4289  Map* new_map = this;
4290  for (int i = root_nof; i < old_nof; ++i) {
4291    PropertyDetails old_details = old_descriptors->GetDetails(i);
4292    Map* transition = TransitionArray::SearchTransition(
4293        new_map, old_details.kind(), old_descriptors->GetKey(i),
4294        old_details.attributes());
4295    if (transition == NULL) return nullptr;
4296    new_map = transition;
4297    DescriptorArray* new_descriptors = new_map->instance_descriptors();
4298
4299    PropertyDetails new_details = new_descriptors->GetDetails(i);
4300    DCHECK_EQ(old_details.kind(), new_details.kind());
4301    DCHECK_EQ(old_details.attributes(), new_details.attributes());
4302    if (!old_details.representation().fits_into(new_details.representation())) {
4303      return nullptr;
4304    }
4305    switch (new_details.type()) {
4306      case DATA: {
4307        FieldType* new_type = new_descriptors->GetFieldType(i);
4308        // Cleared field types need special treatment. They represent lost
4309        // knowledge, so we must first generalize the new_type to "Any".
4310        if (FieldTypeIsCleared(new_details.representation(), new_type)) {
4311          return nullptr;
4312        }
4313        PropertyType old_property_type = old_details.type();
4314        if (old_property_type == DATA) {
4315          FieldType* old_type = old_descriptors->GetFieldType(i);
4316          if (FieldTypeIsCleared(old_details.representation(), old_type) ||
4317              !old_type->NowIs(new_type)) {
4318            return nullptr;
4319          }
4320        } else {
4321          DCHECK(old_property_type == DATA_CONSTANT);
4322          Object* old_value = old_descriptors->GetValue(i);
4323          if (!new_type->NowContains(old_value)) {
4324            return nullptr;
4325          }
4326        }
4327        break;
4328      }
4329      case ACCESSOR: {
4330#ifdef DEBUG
4331        FieldType* new_type = new_descriptors->GetFieldType(i);
4332        DCHECK(new_type->IsAny());
4333#endif
4334        break;
4335      }
4336
4337      case DATA_CONSTANT:
4338      case ACCESSOR_CONSTANT: {
4339        Object* old_value = old_descriptors->GetValue(i);
4340        Object* new_value = new_descriptors->GetValue(i);
4341        if (old_details.location() == kField || old_value != new_value) {
4342          return nullptr;
4343        }
4344        break;
4345      }
4346    }
4347  }
4348  if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
4349  return new_map;
4350}
4351
4352
4353// static
4354Handle<Map> Map::Update(Handle<Map> map) {
4355  if (!map->is_deprecated()) return map;
4356  return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
4357                             FieldType::None(map->GetIsolate()),
4358                             ALLOW_IN_DESCRIPTOR);
4359}
4360
4361Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
4362                                                 ShouldThrow should_throw,
4363                                                 Handle<Object> value) {
4364  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
4365  return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
4366                                            should_throw, value);
4367}
4368
4369MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
4370                                        Handle<Name> name, Handle<Object> value,
4371                                        LanguageMode language_mode,
4372                                        StoreFromKeyed store_mode) {
4373  LookupIterator it(object, name);
4374  MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
4375  return value;
4376}
4377
4378
4379Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
4380                                        Handle<Object> value,
4381                                        LanguageMode language_mode,
4382                                        StoreFromKeyed store_mode,
4383                                        bool* found) {
4384  it->UpdateProtector();
4385  DCHECK(it->IsFound());
4386  ShouldThrow should_throw =
4387      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4388
4389  // Make sure that the top context does not change when doing callbacks or
4390  // interceptor calls.
4391  AssertNoContextChange ncc(it->isolate());
4392
4393  do {
4394    switch (it->state()) {
4395      case LookupIterator::NOT_FOUND:
4396        UNREACHABLE();
4397
4398      case LookupIterator::ACCESS_CHECK:
4399        if (it->HasAccess()) break;
4400        // Check whether it makes sense to reuse the lookup iterator. Here it
4401        // might still call into setters up the prototype chain.
4402        return JSObject::SetPropertyWithFailedAccessCheck(it, value,
4403                                                          should_throw);
4404
4405      case LookupIterator::JSPROXY:
4406        return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
4407                                    value, it->GetReceiver(), language_mode);
4408
4409      case LookupIterator::INTERCEPTOR: {
4410        Handle<Map> store_target_map;
4411        if (it->GetReceiver()->IsJSObject()) {
4412          store_target_map = handle(it->GetStoreTarget()->map(), it->isolate());
4413        }
4414        if (it->HolderIsReceiverOrHiddenPrototype()) {
4415          Maybe<bool> result =
4416              JSObject::SetPropertyWithInterceptor(it, should_throw, value);
4417          if (result.IsNothing() || result.FromJust()) return result;
4418          // Interceptor modified the store target but failed to set the
4419          // property.
4420          Utils::ApiCheck(store_target_map.is_null() ||
4421                              *store_target_map == it->GetStoreTarget()->map(),
4422                          it->IsElement() ? "v8::IndexedPropertySetterCallback"
4423                                          : "v8::NamedPropertySetterCallback",
4424                          "Interceptor silently changed store target.");
4425        } else {
4426          Maybe<PropertyAttributes> maybe_attributes =
4427              JSObject::GetPropertyAttributesWithInterceptor(it);
4428          if (!maybe_attributes.IsJust()) return Nothing<bool>();
4429          if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
4430            return WriteToReadOnlyProperty(it, value, should_throw);
4431          }
4432          // Interceptor modified the store target but failed to set the
4433          // property.
4434          Utils::ApiCheck(store_target_map.is_null() ||
4435                              *store_target_map == it->GetStoreTarget()->map(),
4436                          it->IsElement() ? "v8::IndexedPropertySetterCallback"
4437                                          : "v8::NamedPropertySetterCallback",
4438                          "Interceptor silently changed store target.");
4439          if (maybe_attributes.FromJust() == ABSENT) break;
4440          *found = false;
4441          return Nothing<bool>();
4442        }
4443        break;
4444      }
4445
4446      case LookupIterator::ACCESSOR: {
4447        if (it->IsReadOnly()) {
4448          return WriteToReadOnlyProperty(it, value, should_throw);
4449        }
4450        Handle<Object> accessors = it->GetAccessors();
4451        if (accessors->IsAccessorInfo() &&
4452            !it->HolderIsReceiverOrHiddenPrototype() &&
4453            AccessorInfo::cast(*accessors)->is_special_data_property()) {
4454          *found = false;
4455          return Nothing<bool>();
4456        }
4457        return SetPropertyWithAccessor(it, value, should_throw);
4458      }
4459      case LookupIterator::INTEGER_INDEXED_EXOTIC:
4460        // TODO(verwaest): We should throw an exception if holder is receiver.
4461        return Just(true);
4462
4463      case LookupIterator::DATA:
4464        if (it->IsReadOnly()) {
4465          return WriteToReadOnlyProperty(it, value, should_throw);
4466        }
4467        if (it->HolderIsReceiverOrHiddenPrototype()) {
4468          return SetDataProperty(it, value);
4469        }
4470      // Fall through.
4471      case LookupIterator::TRANSITION:
4472        *found = false;
4473        return Nothing<bool>();
4474    }
4475    it->Next();
4476  } while (it->IsFound());
4477
4478  *found = false;
4479  return Nothing<bool>();
4480}
4481
4482
4483Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
4484                                LanguageMode language_mode,
4485                                StoreFromKeyed store_mode) {
4486  if (it->IsFound()) {
4487    bool found = true;
4488    Maybe<bool> result =
4489        SetPropertyInternal(it, value, language_mode, store_mode, &found);
4490    if (found) return result;
4491  }
4492
4493  // If the receiver is the JSGlobalObject, the store was contextual. In case
4494  // the property did not exist yet on the global object itself, we have to
4495  // throw a reference error in strict mode.  In sloppy mode, we continue.
4496  if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
4497    it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
4498        MessageTemplate::kNotDefined, it->name()));
4499    return Nothing<bool>();
4500  }
4501
4502  ShouldThrow should_throw =
4503      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4504  return AddDataProperty(it, value, NONE, should_throw, store_mode);
4505}
4506
4507
4508Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
4509                                     LanguageMode language_mode,
4510                                     StoreFromKeyed store_mode) {
4511  Isolate* isolate = it->isolate();
4512
4513  if (it->IsFound()) {
4514    bool found = true;
4515    Maybe<bool> result =
4516        SetPropertyInternal(it, value, language_mode, store_mode, &found);
4517    if (found) return result;
4518  }
4519
4520  it->UpdateProtector();
4521
4522  // The property either doesn't exist on the holder or exists there as a data
4523  // property.
4524
4525  ShouldThrow should_throw =
4526      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4527
4528  if (!it->GetReceiver()->IsJSReceiver()) {
4529    return WriteToReadOnlyProperty(it, value, should_throw);
4530  }
4531  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
4532
4533  LookupIterator::Configuration c = LookupIterator::OWN;
4534  LookupIterator own_lookup =
4535      it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
4536                      : LookupIterator(receiver, it->name(), c);
4537
4538  for (; own_lookup.IsFound(); own_lookup.Next()) {
4539    switch (own_lookup.state()) {
4540      case LookupIterator::ACCESS_CHECK:
4541        if (!own_lookup.HasAccess()) {
4542          return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
4543                                                            should_throw);
4544        }
4545        break;
4546
4547      case LookupIterator::ACCESSOR:
4548        if (own_lookup.GetAccessors()->IsAccessorInfo()) {
4549          if (own_lookup.IsReadOnly()) {
4550            return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
4551          }
4552          return JSObject::SetPropertyWithAccessor(&own_lookup, value,
4553                                                   should_throw);
4554        }
4555      // Fall through.
4556      case LookupIterator::INTEGER_INDEXED_EXOTIC:
4557        return RedefineIncompatibleProperty(isolate, it->GetName(), value,
4558                                            should_throw);
4559
4560      case LookupIterator::DATA: {
4561        if (own_lookup.IsReadOnly()) {
4562          return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
4563        }
4564        return SetDataProperty(&own_lookup, value);
4565      }
4566
4567      case LookupIterator::INTERCEPTOR:
4568      case LookupIterator::JSPROXY: {
4569        PropertyDescriptor desc;
4570        Maybe<bool> owned =
4571            JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
4572        MAYBE_RETURN(owned, Nothing<bool>());
4573        if (!owned.FromJust()) {
4574          return JSReceiver::CreateDataProperty(&own_lookup, value,
4575                                                should_throw);
4576        }
4577        if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
4578            !desc.writable()) {
4579          return RedefineIncompatibleProperty(isolate, it->GetName(), value,
4580                                              should_throw);
4581        }
4582
4583        PropertyDescriptor value_desc;
4584        value_desc.set_value(value);
4585        return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
4586                                             &value_desc, should_throw);
4587      }
4588
4589      case LookupIterator::NOT_FOUND:
4590      case LookupIterator::TRANSITION:
4591        UNREACHABLE();
4592    }
4593  }
4594
4595  return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
4596}
4597
4598MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it) {
4599  return it->isolate()->factory()->undefined_value();
4600}
4601
4602MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
4603                                               Handle<Object> receiver,
4604                                               Handle<Object> name) {
4605  return isolate->factory()->undefined_value();
4606}
4607
4608
4609Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
4610                                         Handle<Object> receiver,
4611                                         Handle<Object> name,
4612                                         Handle<Object> value,
4613                                         ShouldThrow should_throw) {
4614  RETURN_FAILURE(
4615      isolate, should_throw,
4616      NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
4617                   Object::TypeOf(isolate, receiver), receiver));
4618}
4619
4620
4621Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
4622                                            Handle<Object> value,
4623                                            ShouldThrow should_throw) {
4624  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
4625                                 it->GetName(), value, should_throw);
4626}
4627
4628
4629Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
4630                                            Handle<Object> receiver,
4631                                            Handle<Object> name,
4632                                            Handle<Object> value,
4633                                            ShouldThrow should_throw) {
4634  RETURN_FAILURE(isolate, should_throw,
4635                 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
4636                              Object::TypeOf(isolate, receiver), receiver));
4637}
4638
4639
4640Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
4641                                                 Handle<Object> name,
4642                                                 Handle<Object> value,
4643                                                 ShouldThrow should_throw) {
4644  RETURN_FAILURE(isolate, should_throw,
4645                 NewTypeError(MessageTemplate::kRedefineDisallowed, name));
4646}
4647
4648
4649Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
4650  // Proxies are handled elsewhere. Other non-JSObjects cannot have own
4651  // properties.
4652  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
4653
4654  // Store on the holder which may be hidden behind the receiver.
4655  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
4656
4657  Handle<Object> to_assign = value;
4658  // Convert the incoming value to a number for storing into typed arrays.
4659  if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
4660    if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
4661      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4662          it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
4663      // We have to recheck the length. However, it can only change if the
4664      // underlying buffer was neutered, so just check that.
4665      if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
4666        return Just(true);
4667        // TODO(neis): According to the spec, this should throw a TypeError.
4668      }
4669    }
4670  }
4671
4672  // Possibly migrate to the most up-to-date map that will be able to store
4673  // |value| under it->name().
4674  it->PrepareForDataProperty(to_assign);
4675
4676  // Write the property value.
4677  it->WriteDataValue(to_assign);
4678
4679#if VERIFY_HEAP
4680  if (FLAG_verify_heap) {
4681    receiver->JSObjectVerify();
4682  }
4683#endif
4684  return Just(true);
4685}
4686
4687
4688Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
4689                                    PropertyAttributes attributes,
4690                                    ShouldThrow should_throw,
4691                                    StoreFromKeyed store_mode) {
4692  if (!it->GetReceiver()->IsJSObject()) {
4693    if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
4694      RETURN_FAILURE(it->isolate(), should_throw,
4695                     NewTypeError(MessageTemplate::kProxyPrivate));
4696    }
4697    return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
4698                                value, should_throw);
4699  }
4700
4701  DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
4702
4703  Handle<JSObject> receiver = it->GetStoreTarget();
4704
4705  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
4706  // instead. If the prototype is Null, the proxy is detached.
4707  if (receiver->IsJSGlobalProxy()) return Just(true);
4708
4709  Isolate* isolate = it->isolate();
4710
4711  if (it->ExtendingNonExtensible(receiver)) {
4712    RETURN_FAILURE(
4713        isolate, should_throw,
4714        NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
4715  }
4716
4717  if (it->IsElement()) {
4718    if (receiver->IsJSArray()) {
4719      Handle<JSArray> array = Handle<JSArray>::cast(receiver);
4720      if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
4721        RETURN_FAILURE(array->GetIsolate(), should_throw,
4722                       NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
4723                                    isolate->factory()->length_string(),
4724                                    Object::TypeOf(isolate, array), array));
4725      }
4726
4727      if (FLAG_trace_external_array_abuse &&
4728          array->HasFixedTypedArrayElements()) {
4729        CheckArrayAbuse(array, "typed elements write", it->index(), true);
4730      }
4731
4732      if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
4733        CheckArrayAbuse(array, "elements write", it->index(), false);
4734      }
4735    }
4736
4737    Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
4738                                                  attributes, should_throw);
4739    JSObject::ValidateElements(receiver);
4740    return result;
4741  } else {
4742    it->UpdateProtector();
4743    // Migrate to the most up-to-date map that will be able to store |value|
4744    // under it->name() with |attributes|.
4745    it->PrepareTransitionToDataProperty(receiver, value, attributes,
4746                                        store_mode);
4747    DCHECK_EQ(LookupIterator::TRANSITION, it->state());
4748    it->ApplyTransitionToDataProperty(receiver);
4749
4750    // TODO(verwaest): Encapsulate dictionary handling better.
4751    if (receiver->map()->is_dictionary_map()) {
4752      // TODO(dcarney): just populate TransitionPropertyCell here?
4753      JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
4754    } else {
4755      // Write the property value.
4756      it->WriteDataValue(value);
4757    }
4758
4759#if VERIFY_HEAP
4760    if (FLAG_verify_heap) {
4761      receiver->JSObjectVerify();
4762    }
4763#endif
4764  }
4765
4766  return Just(true);
4767}
4768
4769
4770void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
4771  // Only supports adding slack to owned descriptors.
4772  DCHECK(map->owns_descriptors());
4773
4774  Handle<DescriptorArray> descriptors(map->instance_descriptors());
4775  int old_size = map->NumberOfOwnDescriptors();
4776  if (slack <= descriptors->NumberOfSlackDescriptors()) return;
4777
4778  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
4779      descriptors, old_size, slack);
4780
4781  DisallowHeapAllocation no_allocation;
4782  // The descriptors are still the same, so keep the layout descriptor.
4783  LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
4784
4785  if (old_size == 0) {
4786    map->UpdateDescriptors(*new_descriptors, layout_descriptor);
4787    return;
4788  }
4789
4790  // If the source descriptors had an enum cache we copy it. This ensures
4791  // that the maps to which we push the new descriptor array back can rely
4792  // on a cache always being available once it is set. If the map has more
4793  // enumerated descriptors than available in the original cache, the cache
4794  // will be lazily replaced by the extended cache when needed.
4795  if (descriptors->HasEnumCache()) {
4796    new_descriptors->CopyEnumCacheFrom(*descriptors);
4797  }
4798
4799  Isolate* isolate = map->GetIsolate();
4800  // Replace descriptors by new_descriptors in all maps that share it.
4801  isolate->heap()->incremental_marking()->IterateBlackObject(*descriptors);
4802
4803  Map* current = *map;
4804  while (current->instance_descriptors() == *descriptors) {
4805    Object* next = current->GetBackPointer();
4806    if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
4807    current->UpdateDescriptors(*new_descriptors, layout_descriptor);
4808    current = Map::cast(next);
4809  }
4810  map->UpdateDescriptors(*new_descriptors, layout_descriptor);
4811}
4812
4813
4814template<class T>
4815static int AppendUniqueCallbacks(NeanderArray* callbacks,
4816                                 Handle<typename T::Array> array,
4817                                 int valid_descriptors) {
4818  int nof_callbacks = callbacks->length();
4819
4820  Isolate* isolate = array->GetIsolate();
4821  // Ensure the keys are unique names before writing them into the
4822  // instance descriptor. Since it may cause a GC, it has to be done before we
4823  // temporarily put the heap in an invalid state while appending descriptors.
4824  for (int i = 0; i < nof_callbacks; ++i) {
4825    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
4826    if (entry->name()->IsUniqueName()) continue;
4827    Handle<String> key =
4828        isolate->factory()->InternalizeString(
4829            Handle<String>(String::cast(entry->name())));
4830    entry->set_name(*key);
4831  }
4832
4833  // Fill in new callback descriptors.  Process the callbacks from
4834  // back to front so that the last callback with a given name takes
4835  // precedence over previously added callbacks with that name.
4836  for (int i = nof_callbacks - 1; i >= 0; i--) {
4837    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
4838    Handle<Name> key(Name::cast(entry->name()));
4839    // Check if a descriptor with this name already exists before writing.
4840    if (!T::Contains(key, entry, valid_descriptors, array)) {
4841      T::Insert(key, entry, valid_descriptors, array);
4842      valid_descriptors++;
4843    }
4844  }
4845
4846  return valid_descriptors;
4847}
4848
4849struct DescriptorArrayAppender {
4850  typedef DescriptorArray Array;
4851  static bool Contains(Handle<Name> key,
4852                       Handle<AccessorInfo> entry,
4853                       int valid_descriptors,
4854                       Handle<DescriptorArray> array) {
4855    DisallowHeapAllocation no_gc;
4856    return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
4857  }
4858  static void Insert(Handle<Name> key,
4859                     Handle<AccessorInfo> entry,
4860                     int valid_descriptors,
4861                     Handle<DescriptorArray> array) {
4862    DisallowHeapAllocation no_gc;
4863    AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
4864    array->Append(&desc);
4865  }
4866};
4867
4868
4869struct FixedArrayAppender {
4870  typedef FixedArray Array;
4871  static bool Contains(Handle<Name> key,
4872                       Handle<AccessorInfo> entry,
4873                       int valid_descriptors,
4874                       Handle<FixedArray> array) {
4875    for (int i = 0; i < valid_descriptors; i++) {
4876      if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
4877    }
4878    return false;
4879  }
4880  static void Insert(Handle<Name> key,
4881                     Handle<AccessorInfo> entry,
4882                     int valid_descriptors,
4883                     Handle<FixedArray> array) {
4884    DisallowHeapAllocation no_gc;
4885    array->set(valid_descriptors, *entry);
4886  }
4887};
4888
4889
4890void Map::AppendCallbackDescriptors(Handle<Map> map,
4891                                    Handle<Object> descriptors) {
4892  int nof = map->NumberOfOwnDescriptors();
4893  Handle<DescriptorArray> array(map->instance_descriptors());
4894  NeanderArray callbacks(descriptors);
4895  DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
4896  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
4897  map->SetNumberOfOwnDescriptors(nof);
4898}
4899
4900
4901int AccessorInfo::AppendUnique(Handle<Object> descriptors,
4902                               Handle<FixedArray> array,
4903                               int valid_descriptors) {
4904  NeanderArray callbacks(descriptors);
4905  DCHECK(array->length() >= callbacks.length() + valid_descriptors);
4906  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
4907                                                   array,
4908                                                   valid_descriptors);
4909}
4910
4911
4912static bool ContainsMap(MapHandleList* maps, Map* map) {
4913  DCHECK_NOT_NULL(map);
4914  for (int i = 0; i < maps->length(); ++i) {
4915    if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
4916  }
4917  return false;
4918}
4919
4920Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
4921  DisallowHeapAllocation no_allocation;
4922  DisallowDeoptimization no_deoptimization(GetIsolate());
4923
4924  ElementsKind kind = elements_kind();
4925  bool packed = IsFastPackedElementsKind(kind);
4926
4927  Map* transition = nullptr;
4928  if (IsTransitionableFastElementsKind(kind)) {
4929    // Check the state of the root map.
4930    Map* root_map = FindRootMap();
4931    if (!EquivalentToForTransition(root_map)) return nullptr;
4932    root_map = root_map->LookupElementsTransitionMap(kind);
4933    DCHECK_NOT_NULL(root_map);
4934    // Starting from the next existing elements kind transition try to
4935    // replay the property transitions that does not involve instance rewriting
4936    // (ElementsTransitionAndStoreStub does not support that).
4937    for (root_map = root_map->ElementsTransitionMap();
4938         root_map != nullptr && root_map->has_fast_elements();
4939         root_map = root_map->ElementsTransitionMap()) {
4940      Map* current = root_map->TryReplayPropertyTransitions(this);
4941      if (current == nullptr) continue;
4942      if (InstancesNeedRewriting(current)) continue;
4943
4944      if (ContainsMap(candidates, current) &&
4945          (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
4946        transition = current;
4947        packed = packed && IsFastPackedElementsKind(current->elements_kind());
4948      }
4949    }
4950  }
4951  return transition;
4952}
4953
4954
4955static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
4956  // Ensure we are requested to search elements kind transition "near the root".
4957  DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
4958            map->NumberOfOwnDescriptors());
4959  Map* current_map = map;
4960
4961  ElementsKind kind = map->elements_kind();
4962  while (kind != to_kind) {
4963    Map* next_map = current_map->ElementsTransitionMap();
4964    if (next_map == nullptr) return current_map;
4965    kind = next_map->elements_kind();
4966    current_map = next_map;
4967  }
4968
4969  DCHECK_EQ(to_kind, current_map->elements_kind());
4970  return current_map;
4971}
4972
4973
4974Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
4975  Map* to_map = FindClosestElementsTransition(this, to_kind);
4976  if (to_map->elements_kind() == to_kind) return to_map;
4977  return nullptr;
4978}
4979
4980
4981bool Map::IsMapInArrayPrototypeChain() {
4982  Isolate* isolate = GetIsolate();
4983  if (isolate->initial_array_prototype()->map() == this) {
4984    return true;
4985  }
4986
4987  if (isolate->initial_object_prototype()->map() == this) {
4988    return true;
4989  }
4990
4991  return false;
4992}
4993
4994
4995Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
4996  Isolate* isolate = map->GetIsolate();
4997  if (map->weak_cell_cache()->IsWeakCell()) {
4998    return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
4999  }
5000  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
5001  map->set_weak_cell_cache(*weak_cell);
5002  return weak_cell;
5003}
5004
5005
5006static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
5007                                                 ElementsKind to_kind) {
5008  DCHECK(IsTransitionElementsKind(map->elements_kind()));
5009
5010  Handle<Map> current_map = map;
5011
5012  ElementsKind kind = map->elements_kind();
5013  TransitionFlag flag;
5014  if (map->is_prototype_map()) {
5015    flag = OMIT_TRANSITION;
5016  } else {
5017    flag = INSERT_TRANSITION;
5018    if (IsFastElementsKind(kind)) {
5019      while (kind != to_kind && !IsTerminalElementsKind(kind)) {
5020        kind = GetNextTransitionElementsKind(kind);
5021        current_map = Map::CopyAsElementsKind(current_map, kind, flag);
5022      }
5023    }
5024  }
5025
5026  // In case we are exiting the fast elements kind system, just add the map in
5027  // the end.
5028  if (kind != to_kind) {
5029    current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
5030  }
5031
5032  DCHECK(current_map->elements_kind() == to_kind);
5033  return current_map;
5034}
5035
5036
5037Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
5038                                      ElementsKind to_kind) {
5039  ElementsKind from_kind = map->elements_kind();
5040  if (from_kind == to_kind) return map;
5041
5042  Isolate* isolate = map->GetIsolate();
5043  Context* native_context = isolate->context()->native_context();
5044  if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
5045    if (*map == native_context->fast_aliased_arguments_map()) {
5046      DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5047      return handle(native_context->slow_aliased_arguments_map());
5048    }
5049  } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
5050    if (*map == native_context->slow_aliased_arguments_map()) {
5051      DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
5052      return handle(native_context->fast_aliased_arguments_map());
5053    }
5054  } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
5055    // Reuse map transitions for JSArrays.
5056    DisallowHeapAllocation no_gc;
5057    if (native_context->get(Context::ArrayMapIndex(from_kind)) == *map) {
5058      Object* maybe_transitioned_map =
5059          native_context->get(Context::ArrayMapIndex(to_kind));
5060      if (maybe_transitioned_map->IsMap()) {
5061        return handle(Map::cast(maybe_transitioned_map), isolate);
5062      }
5063    }
5064  }
5065
5066  DCHECK(!map->IsUndefined(isolate));
5067  // Check if we can go back in the elements kind transition chain.
5068  if (IsHoleyElementsKind(from_kind) &&
5069      to_kind == GetPackedElementsKind(from_kind) &&
5070      map->GetBackPointer()->IsMap() &&
5071      Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
5072    return handle(Map::cast(map->GetBackPointer()));
5073  }
5074
5075  bool allow_store_transition = IsTransitionElementsKind(from_kind);
5076  // Only store fast element maps in ascending generality.
5077  if (IsFastElementsKind(to_kind)) {
5078    allow_store_transition =
5079        allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
5080        IsMoreGeneralElementsKindTransition(from_kind, to_kind);
5081  }
5082
5083  if (!allow_store_transition) {
5084    return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
5085  }
5086
5087  return Map::ReconfigureElementsKind(map, to_kind);
5088}
5089
5090
5091// static
5092Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
5093  Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
5094
5095  if (closest_map->elements_kind() == kind) {
5096    return closest_map;
5097  }
5098
5099  return AddMissingElementsTransitions(closest_map, kind);
5100}
5101
5102
5103Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
5104                                               ElementsKind to_kind) {
5105  Handle<Map> map(object->map());
5106  return Map::TransitionElementsTo(map, to_kind);
5107}
5108
5109
5110void JSProxy::Revoke(Handle<JSProxy> proxy) {
5111  Isolate* isolate = proxy->GetIsolate();
5112  if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value());
5113  DCHECK(proxy->IsRevoked());
5114}
5115
5116
5117Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
5118                                 Handle<Name> name) {
5119  DCHECK(!name->IsPrivate());
5120  STACK_CHECK(isolate, Nothing<bool>());
5121  // 1. (Assert)
5122  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
5123  Handle<Object> handler(proxy->handler(), isolate);
5124  // 3. If handler is null, throw a TypeError exception.
5125  // 4. Assert: Type(handler) is Object.
5126  if (proxy->IsRevoked()) {
5127    isolate->Throw(*isolate->factory()->NewTypeError(
5128        MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
5129    return Nothing<bool>();
5130  }
5131  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
5132  Handle<JSReceiver> target(proxy->target(), isolate);
5133  // 6. Let trap be ? GetMethod(handler, "has").
5134  Handle<Object> trap;
5135  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5136      isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
5137                                       isolate->factory()->has_string()),
5138      Nothing<bool>());
5139  // 7. If trap is undefined, then
5140  if (trap->IsUndefined(isolate)) {
5141    // 7a. Return target.[[HasProperty]](P).
5142    return JSReceiver::HasProperty(target, name);
5143  }
5144  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)).
5145  Handle<Object> trap_result_obj;
5146  Handle<Object> args[] = {target, name};
5147  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5148      isolate, trap_result_obj,
5149      Execution::Call(isolate, trap, handler, arraysize(args), args),
5150      Nothing<bool>());
5151  bool boolean_trap_result = trap_result_obj->BooleanValue();
5152  // 9. If booleanTrapResult is false, then:
5153  if (!boolean_trap_result) {
5154    // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
5155    PropertyDescriptor target_desc;
5156    Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor(
5157        isolate, target, name, &target_desc);
5158    MAYBE_RETURN(target_found, Nothing<bool>());
5159    // 9b. If targetDesc is not undefined, then:
5160    if (target_found.FromJust()) {
5161      // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
5162      //       exception.
5163      if (!target_desc.configurable()) {
5164        isolate->Throw(*isolate->factory()->NewTypeError(
5165            MessageTemplate::kProxyHasNonConfigurable, name));
5166        return Nothing<bool>();
5167      }
5168      // 9b ii. Let extensibleTarget be ? IsExtensible(target).
5169      Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
5170      MAYBE_RETURN(extensible_target, Nothing<bool>());
5171      // 9b iii. If extensibleTarget is false, throw a TypeError exception.
5172      if (!extensible_target.FromJust()) {
5173        isolate->Throw(*isolate->factory()->NewTypeError(
5174            MessageTemplate::kProxyHasNonExtensible, name));
5175        return Nothing<bool>();
5176      }
5177    }
5178  }
5179  // 10. Return booleanTrapResult.
5180  return Just(boolean_trap_result);
5181}
5182
5183
5184Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
5185                                 Handle<Object> value, Handle<Object> receiver,
5186                                 LanguageMode language_mode) {
5187  DCHECK(!name->IsPrivate());
5188  Isolate* isolate = proxy->GetIsolate();
5189  STACK_CHECK(isolate, Nothing<bool>());
5190  Factory* factory = isolate->factory();
5191  Handle<String> trap_name = factory->set_string();
5192  ShouldThrow should_throw =
5193      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
5194
5195  if (proxy->IsRevoked()) {
5196    isolate->Throw(
5197        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
5198    return Nothing<bool>();
5199  }
5200  Handle<JSReceiver> target(proxy->target(), isolate);
5201  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
5202
5203  Handle<Object> trap;
5204  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5205      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
5206  if (trap->IsUndefined(isolate)) {
5207    LookupIterator it =
5208        LookupIterator::PropertyOrElement(isolate, receiver, name, target);
5209    return Object::SetSuperProperty(&it, value, language_mode,
5210                                    Object::MAY_BE_STORE_FROM_KEYED);
5211  }
5212
5213  Handle<Object> trap_result;
5214  Handle<Object> args[] = {target, name, value, receiver};
5215  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5216      isolate, trap_result,
5217      Execution::Call(isolate, trap, handler, arraysize(args), args),
5218      Nothing<bool>());
5219  if (!trap_result->BooleanValue()) {
5220    RETURN_FAILURE(isolate, should_throw,
5221                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
5222                                trap_name, name));
5223  }
5224
5225  // Enforce the invariant.
5226  PropertyDescriptor target_desc;
5227  Maybe<bool> owned =
5228      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
5229  MAYBE_RETURN(owned, Nothing<bool>());
5230  if (owned.FromJust()) {
5231    bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
5232                        !target_desc.configurable() &&
5233                        !target_desc.writable() &&
5234                        !value->SameValue(*target_desc.value());
5235    if (inconsistent) {
5236      isolate->Throw(*isolate->factory()->NewTypeError(
5237          MessageTemplate::kProxySetFrozenData, name));
5238      return Nothing<bool>();
5239    }
5240    inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
5241                   !target_desc.configurable() &&
5242                   target_desc.set()->IsUndefined(isolate);
5243    if (inconsistent) {
5244      isolate->Throw(*isolate->factory()->NewTypeError(
5245          MessageTemplate::kProxySetFrozenAccessor, name));
5246      return Nothing<bool>();
5247    }
5248  }
5249  return Just(true);
5250}
5251
5252
5253Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
5254                                             Handle<Name> name,
5255                                             LanguageMode language_mode) {
5256  DCHECK(!name->IsPrivate());
5257  ShouldThrow should_throw =
5258      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
5259  Isolate* isolate = proxy->GetIsolate();
5260  STACK_CHECK(isolate, Nothing<bool>());
5261  Factory* factory = isolate->factory();
5262  Handle<String> trap_name = factory->deleteProperty_string();
5263
5264  if (proxy->IsRevoked()) {
5265    isolate->Throw(
5266        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
5267    return Nothing<bool>();
5268  }
5269  Handle<JSReceiver> target(proxy->target(), isolate);
5270  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
5271
5272  Handle<Object> trap;
5273  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5274      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
5275  if (trap->IsUndefined(isolate)) {
5276    return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
5277  }
5278
5279  Handle<Object> trap_result;
5280  Handle<Object> args[] = {target, name};
5281  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5282      isolate, trap_result,
5283      Execution::Call(isolate, trap, handler, arraysize(args), args),
5284      Nothing<bool>());
5285  if (!trap_result->BooleanValue()) {
5286    RETURN_FAILURE(isolate, should_throw,
5287                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
5288                                trap_name, name));
5289  }
5290
5291  // Enforce the invariant.
5292  PropertyDescriptor target_desc;
5293  Maybe<bool> owned =
5294      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
5295  MAYBE_RETURN(owned, Nothing<bool>());
5296  if (owned.FromJust() && !target_desc.configurable()) {
5297    isolate->Throw(*factory->NewTypeError(
5298        MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
5299    return Nothing<bool>();
5300  }
5301  return Just(true);
5302}
5303
5304
5305// static
5306MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
5307                                  Handle<Object> handler) {
5308  if (!target->IsJSReceiver()) {
5309    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
5310                    JSProxy);
5311  }
5312  if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
5313    THROW_NEW_ERROR(isolate,
5314                    NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
5315                    JSProxy);
5316  }
5317  if (!handler->IsJSReceiver()) {
5318    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
5319                    JSProxy);
5320  }
5321  if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
5322    THROW_NEW_ERROR(isolate,
5323                    NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
5324                    JSProxy);
5325  }
5326  return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
5327                                        Handle<JSReceiver>::cast(handler));
5328}
5329
5330
5331// static
5332MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
5333  DCHECK(proxy->map()->is_constructor());
5334  if (proxy->IsRevoked()) {
5335    THROW_NEW_ERROR(proxy->GetIsolate(),
5336                    NewTypeError(MessageTemplate::kProxyRevoked), Context);
5337  }
5338  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()));
5339  return JSReceiver::GetFunctionRealm(target);
5340}
5341
5342
5343// static
5344MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
5345    Handle<JSBoundFunction> function) {
5346  DCHECK(function->map()->is_constructor());
5347  return JSReceiver::GetFunctionRealm(
5348      handle(function->bound_target_function()));
5349}
5350
5351// static
5352MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
5353                                             Handle<JSBoundFunction> function) {
5354  Handle<String> prefix = isolate->factory()->bound__string();
5355  if (!function->bound_target_function()->IsJSFunction()) return prefix;
5356  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
5357                            isolate);
5358  Handle<Object> target_name = JSFunction::GetName(isolate, target);
5359  if (!target_name->IsString()) return prefix;
5360  Factory* factory = isolate->factory();
5361  return factory->NewConsString(prefix, Handle<String>::cast(target_name));
5362}
5363
5364// static
5365Handle<Object> JSFunction::GetName(Isolate* isolate,
5366                                   Handle<JSFunction> function) {
5367  if (function->shared()->name_should_print_as_anonymous()) {
5368    return isolate->factory()->anonymous_string();
5369  }
5370  return handle(function->shared()->name(), isolate);
5371}
5372
5373// static
5374MaybeHandle<Smi> JSFunction::GetLength(Isolate* isolate,
5375                                       Handle<JSFunction> function) {
5376  int length = 0;
5377  if (function->shared()->is_compiled()) {
5378    length = function->shared()->length();
5379  } else {
5380    // If the function isn't compiled yet, the length is not computed
5381    // correctly yet. Compile it now and return the right length.
5382    if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
5383      length = function->shared()->length();
5384    }
5385    if (isolate->has_pending_exception()) return MaybeHandle<Smi>();
5386  }
5387  return handle(Smi::FromInt(length), isolate);
5388}
5389
5390// static
5391Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
5392  DCHECK(function->map()->is_constructor());
5393  return handle(function->context()->native_context());
5394}
5395
5396
5397// static
5398MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
5399  DCHECK(object->map()->is_constructor());
5400  DCHECK(!object->IsJSFunction());
5401  return handle(object->GetCreationContext());
5402}
5403
5404
5405// static
5406MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
5407  if (receiver->IsJSProxy()) {
5408    return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
5409  }
5410
5411  if (receiver->IsJSFunction()) {
5412    return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
5413  }
5414
5415  if (receiver->IsJSBoundFunction()) {
5416    return JSBoundFunction::GetFunctionRealm(
5417        Handle<JSBoundFunction>::cast(receiver));
5418  }
5419
5420  return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
5421}
5422
5423
5424Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
5425  PropertyDescriptor desc;
5426  Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
5427      it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
5428  MAYBE_RETURN(found, Nothing<PropertyAttributes>());
5429  if (!found.FromJust()) return Just(ABSENT);
5430  return Just(desc.ToAttributes());
5431}
5432
5433
5434void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
5435  DCHECK(object->map()->GetInObjectProperties() ==
5436         map->GetInObjectProperties());
5437  ElementsKind obj_kind = object->map()->elements_kind();
5438  ElementsKind map_kind = map->elements_kind();
5439  if (map_kind != obj_kind) {
5440    ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
5441    if (IsDictionaryElementsKind(obj_kind)) {
5442      to_kind = obj_kind;
5443    }
5444    if (IsDictionaryElementsKind(to_kind)) {
5445      NormalizeElements(object);
5446    } else {
5447      TransitionElementsKind(object, to_kind);
5448    }
5449    map = Map::ReconfigureElementsKind(map, to_kind);
5450  }
5451  JSObject::MigrateToMap(object, map);
5452}
5453
5454
5455void JSObject::MigrateInstance(Handle<JSObject> object) {
5456  Handle<Map> original_map(object->map());
5457  Handle<Map> map = Map::Update(original_map);
5458  map->set_migration_target(true);
5459  MigrateToMap(object, map);
5460  if (FLAG_trace_migration) {
5461    object->PrintInstanceMigration(stdout, *original_map, *map);
5462  }
5463#if VERIFY_HEAP
5464  if (FLAG_verify_heap) {
5465    object->JSObjectVerify();
5466  }
5467#endif
5468}
5469
5470
5471// static
5472bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
5473  Isolate* isolate = object->GetIsolate();
5474  DisallowDeoptimization no_deoptimization(isolate);
5475  Handle<Map> original_map(object->map(), isolate);
5476  Handle<Map> new_map;
5477  if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
5478    return false;
5479  }
5480  JSObject::MigrateToMap(object, new_map);
5481  if (FLAG_trace_migration) {
5482    object->PrintInstanceMigration(stdout, *original_map, object->map());
5483  }
5484#if VERIFY_HEAP
5485  if (FLAG_verify_heap) {
5486    object->JSObjectVerify();
5487  }
5488#endif
5489  return true;
5490}
5491
5492
5493void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
5494                           Handle<Object> value,
5495                           PropertyAttributes attributes) {
5496  LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
5497  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
5498#ifdef DEBUG
5499  uint32_t index;
5500  DCHECK(!object->IsJSProxy());
5501  DCHECK(!name->AsArrayIndex(&index));
5502  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5503  DCHECK(maybe.IsJust());
5504  DCHECK(!it.IsFound());
5505  DCHECK(object->map()->is_extensible() || name->IsPrivate());
5506#endif
5507  CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
5508                        CERTAINLY_NOT_STORE_FROM_KEYED)
5509            .IsJust());
5510}
5511
5512
5513// Reconfigures a property to a data property with attributes, even if it is not
5514// reconfigurable.
5515// Requires a LookupIterator that does not look at the prototype chain beyond
5516// hidden prototypes.
5517MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
5518    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5519    AccessorInfoHandling handling) {
5520  MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
5521      it, value, attributes, THROW_ON_ERROR, handling));
5522  return value;
5523}
5524
5525
5526Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
5527    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5528    ShouldThrow should_throw, AccessorInfoHandling handling) {
5529  it->UpdateProtector();
5530  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
5531
5532  for (; it->IsFound(); it->Next()) {
5533    switch (it->state()) {
5534      case LookupIterator::JSPROXY:
5535      case LookupIterator::NOT_FOUND:
5536      case LookupIterator::TRANSITION:
5537        UNREACHABLE();
5538
5539      case LookupIterator::ACCESS_CHECK:
5540        if (!it->HasAccess()) {
5541          it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
5542          RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
5543          return Just(true);
5544        }
5545        break;
5546
5547      // If there's an interceptor, try to store the property with the
5548      // interceptor.
5549      // In case of success, the attributes will have been reset to the default
5550      // attributes of the interceptor, rather than the incoming attributes.
5551      //
5552      // TODO(verwaest): JSProxy afterwards verify the attributes that the
5553      // JSProxy claims it has, and verifies that they are compatible. If not,
5554      // they throw. Here we should do the same.
5555      case LookupIterator::INTERCEPTOR:
5556        if (handling == DONT_FORCE_FIELD) {
5557          Maybe<bool> result =
5558              JSObject::SetPropertyWithInterceptor(it, should_throw, value);
5559          if (result.IsNothing() || result.FromJust()) return result;
5560        }
5561        break;
5562
5563      case LookupIterator::ACCESSOR: {
5564        Handle<Object> accessors = it->GetAccessors();
5565
5566        // Special handling for AccessorInfo, which behaves like a data
5567        // property.
5568        if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
5569          PropertyAttributes current_attributes = it->property_attributes();
5570          // Ensure the context isn't changed after calling into accessors.
5571          AssertNoContextChange ncc(it->isolate());
5572
5573          // Update the attributes before calling the setter. The setter may
5574          // later change the shape of the property.
5575          if (current_attributes != attributes) {
5576            it->TransitionToAccessorPair(accessors, attributes);
5577          }
5578
5579          Maybe<bool> result =
5580              JSObject::SetPropertyWithAccessor(it, value, should_throw);
5581
5582          if (current_attributes == attributes || result.IsNothing()) {
5583            return result;
5584          }
5585
5586        } else {
5587          it->ReconfigureDataProperty(value, attributes);
5588        }
5589
5590        return Just(true);
5591      }
5592      case LookupIterator::INTEGER_INDEXED_EXOTIC:
5593        return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
5594                                            should_throw);
5595
5596      case LookupIterator::DATA: {
5597        // Regular property update if the attributes match.
5598        if (it->property_attributes() == attributes) {
5599          return SetDataProperty(it, value);
5600        }
5601
5602        // Special case: properties of typed arrays cannot be reconfigured to
5603        // non-writable nor to non-enumerable.
5604        if (it->IsElement() && object->HasFixedTypedArrayElements()) {
5605          return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
5606                                              value, should_throw);
5607        }
5608
5609        // Reconfigure the data property if the attributes mismatch.
5610        it->ReconfigureDataProperty(value, attributes);
5611
5612        return Just(true);
5613      }
5614    }
5615  }
5616
5617  return AddDataProperty(it, value, attributes, should_throw,
5618                         CERTAINLY_NOT_STORE_FROM_KEYED);
5619}
5620
5621MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
5622    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
5623    PropertyAttributes attributes) {
5624  DCHECK(!value->IsTheHole(object->GetIsolate()));
5625  LookupIterator it(object, name, object, LookupIterator::OWN);
5626  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
5627}
5628
5629MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
5630    Handle<JSObject> object, uint32_t index, Handle<Object> value,
5631    PropertyAttributes attributes) {
5632  Isolate* isolate = object->GetIsolate();
5633  LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
5634  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
5635}
5636
5637MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
5638    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
5639    PropertyAttributes attributes) {
5640  Isolate* isolate = object->GetIsolate();
5641  LookupIterator it = LookupIterator::PropertyOrElement(
5642      isolate, object, name, object, LookupIterator::OWN);
5643  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
5644}
5645
5646Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
5647    LookupIterator* it) {
5648  return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
5649}
5650
5651Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
5652    LookupIterator* it) {
5653  for (; it->IsFound(); it->Next()) {
5654    switch (it->state()) {
5655      case LookupIterator::NOT_FOUND:
5656      case LookupIterator::TRANSITION:
5657        UNREACHABLE();
5658      case LookupIterator::JSPROXY:
5659        return JSProxy::GetPropertyAttributes(it);
5660      case LookupIterator::INTERCEPTOR: {
5661        Maybe<PropertyAttributes> result =
5662            JSObject::GetPropertyAttributesWithInterceptor(it);
5663        if (!result.IsJust()) return result;
5664        if (result.FromJust() != ABSENT) return result;
5665        break;
5666      }
5667      case LookupIterator::ACCESS_CHECK:
5668        if (it->HasAccess()) break;
5669        return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
5670      case LookupIterator::INTEGER_INDEXED_EXOTIC:
5671        return Just(ABSENT);
5672      case LookupIterator::ACCESSOR:
5673      case LookupIterator::DATA:
5674        return Just(it->property_attributes());
5675    }
5676  }
5677  return Just(ABSENT);
5678}
5679
5680
5681Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
5682  Handle<FixedArray> array(
5683      isolate->factory()->NewFixedArray(kEntries, TENURED));
5684  return Handle<NormalizedMapCache>::cast(array);
5685}
5686
5687
5688MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
5689                                         PropertyNormalizationMode mode) {
5690  DisallowHeapAllocation no_gc;
5691  Object* value = FixedArray::get(GetIndex(fast_map));
5692  if (!value->IsMap() ||
5693      !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
5694    return MaybeHandle<Map>();
5695  }
5696  return handle(Map::cast(value));
5697}
5698
5699
5700void NormalizedMapCache::Set(Handle<Map> fast_map,
5701                             Handle<Map> normalized_map) {
5702  DisallowHeapAllocation no_gc;
5703  DCHECK(normalized_map->is_dictionary_map());
5704  FixedArray::set(GetIndex(fast_map), *normalized_map);
5705}
5706
5707
5708void NormalizedMapCache::Clear() {
5709  int entries = length();
5710  for (int i = 0; i != entries; i++) {
5711    set_undefined(i);
5712  }
5713}
5714
5715
5716void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
5717                                    Handle<Name> name,
5718                                    Handle<Code> code) {
5719  Handle<Map> map(object->map());
5720  Map::UpdateCodeCache(map, name, code);
5721}
5722
5723
5724void JSObject::NormalizeProperties(Handle<JSObject> object,
5725                                   PropertyNormalizationMode mode,
5726                                   int expected_additional_properties,
5727                                   const char* reason) {
5728  if (!object->HasFastProperties()) return;
5729
5730  Handle<Map> map(object->map());
5731  Handle<Map> new_map = Map::Normalize(map, mode, reason);
5732
5733  MigrateToMap(object, new_map, expected_additional_properties);
5734}
5735
5736
5737void JSObject::MigrateSlowToFast(Handle<JSObject> object,
5738                                 int unused_property_fields,
5739                                 const char* reason) {
5740  if (object->HasFastProperties()) return;
5741  DCHECK(!object->IsJSGlobalObject());
5742  Isolate* isolate = object->GetIsolate();
5743  Factory* factory = isolate->factory();
5744  Handle<NameDictionary> dictionary(object->property_dictionary());
5745
5746  // Make sure we preserve dictionary representation if there are too many
5747  // descriptors.
5748  int number_of_elements = dictionary->NumberOfElements();
5749  if (number_of_elements > kMaxNumberOfDescriptors) return;
5750
5751  Handle<FixedArray> iteration_order;
5752  if (number_of_elements != dictionary->NextEnumerationIndex()) {
5753    iteration_order =
5754        NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
5755  } else {
5756    iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
5757  }
5758
5759  int instance_descriptor_length = iteration_order->length();
5760  int number_of_fields = 0;
5761
5762  // Compute the length of the instance descriptor.
5763  for (int i = 0; i < instance_descriptor_length; i++) {
5764    int index = Smi::cast(iteration_order->get(i))->value();
5765    DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
5766
5767    Object* value = dictionary->ValueAt(index);
5768    PropertyType type = dictionary->DetailsAt(index).type();
5769    if (type == DATA && !value->IsJSFunction()) {
5770      number_of_fields += 1;
5771    }
5772  }
5773
5774  Handle<Map> old_map(object->map(), isolate);
5775
5776  int inobject_props = old_map->GetInObjectProperties();
5777
5778  // Allocate new map.
5779  Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
5780  new_map->set_dictionary_map(false);
5781
5782  UpdatePrototypeUserRegistration(old_map, new_map, isolate);
5783
5784#if TRACE_MAPS
5785  if (FLAG_trace_maps) {
5786    PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
5787           reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map),
5788           reason);
5789  }
5790#endif
5791
5792  if (instance_descriptor_length == 0) {
5793    DisallowHeapAllocation no_gc;
5794    DCHECK_LE(unused_property_fields, inobject_props);
5795    // Transform the object.
5796    new_map->set_unused_property_fields(inobject_props);
5797    object->synchronized_set_map(*new_map);
5798    object->set_properties(isolate->heap()->empty_fixed_array());
5799    // Check that it really works.
5800    DCHECK(object->HasFastProperties());
5801    return;
5802  }
5803
5804  // Allocate the instance descriptor.
5805  Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
5806      isolate, instance_descriptor_length, 0, TENURED);
5807
5808  int number_of_allocated_fields =
5809      number_of_fields + unused_property_fields - inobject_props;
5810  if (number_of_allocated_fields < 0) {
5811    // There is enough inobject space for all fields (including unused).
5812    number_of_allocated_fields = 0;
5813    unused_property_fields = inobject_props - number_of_fields;
5814  }
5815
5816  // Allocate the fixed array for the fields.
5817  Handle<FixedArray> fields = factory->NewFixedArray(
5818      number_of_allocated_fields);
5819
5820  // Fill in the instance descriptor and the fields.
5821  int current_offset = 0;
5822  for (int i = 0; i < instance_descriptor_length; i++) {
5823    int index = Smi::cast(iteration_order->get(i))->value();
5824    Object* k = dictionary->KeyAt(index);
5825    DCHECK(dictionary->IsKey(k));
5826    // Dictionary keys are internalized upon insertion.
5827    // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
5828    CHECK(k->IsUniqueName());
5829    Handle<Name> key(Name::cast(k), isolate);
5830
5831    Object* value = dictionary->ValueAt(index);
5832
5833    PropertyDetails details = dictionary->DetailsAt(index);
5834    int enumeration_index = details.dictionary_index();
5835    PropertyType type = details.type();
5836
5837    if (value->IsJSFunction()) {
5838      DataConstantDescriptor d(key, handle(value, isolate),
5839                               details.attributes());
5840      descriptors->Set(enumeration_index - 1, &d);
5841    } else if (type == DATA) {
5842      if (current_offset < inobject_props) {
5843        object->InObjectPropertyAtPut(current_offset, value,
5844                                      UPDATE_WRITE_BARRIER);
5845      } else {
5846        int offset = current_offset - inobject_props;
5847        fields->set(offset, value);
5848      }
5849      DataDescriptor d(key, current_offset, details.attributes(),
5850                       // TODO(verwaest): value->OptimalRepresentation();
5851                       Representation::Tagged());
5852      current_offset += d.GetDetails().field_width_in_words();
5853      descriptors->Set(enumeration_index - 1, &d);
5854    } else if (type == ACCESSOR_CONSTANT) {
5855      AccessorConstantDescriptor d(key, handle(value, isolate),
5856                                   details.attributes());
5857      descriptors->Set(enumeration_index - 1, &d);
5858    } else {
5859      UNREACHABLE();
5860    }
5861  }
5862  DCHECK(current_offset == number_of_fields);
5863
5864  descriptors->Sort();
5865
5866  Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
5867      new_map, descriptors, descriptors->number_of_descriptors());
5868
5869  DisallowHeapAllocation no_gc;
5870  new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
5871  new_map->set_unused_property_fields(unused_property_fields);
5872
5873  // Transform the object.
5874  object->synchronized_set_map(*new_map);
5875
5876  object->set_properties(*fields);
5877  DCHECK(object->IsJSObject());
5878
5879  // Check that it really works.
5880  DCHECK(object->HasFastProperties());
5881}
5882
5883
5884void JSObject::ResetElements(Handle<JSObject> object) {
5885  Isolate* isolate = object->GetIsolate();
5886  CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
5887  if (object->map()->has_dictionary_elements()) {
5888    Handle<SeededNumberDictionary> new_elements =
5889        SeededNumberDictionary::New(isolate, 0);
5890    object->set_elements(*new_elements);
5891  } else {
5892    object->set_elements(object->map()->GetInitialElements());
5893  }
5894}
5895
5896
5897void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
5898  if (dictionary->requires_slow_elements()) return;
5899  dictionary->set_requires_slow_elements();
5900  // TODO(verwaest): Remove this hack.
5901  if (map()->is_prototype_map()) {
5902    TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
5903  }
5904}
5905
5906
5907Handle<SeededNumberDictionary> JSObject::NormalizeElements(
5908    Handle<JSObject> object) {
5909  DCHECK(!object->HasFixedTypedArrayElements());
5910  Isolate* isolate = object->GetIsolate();
5911  bool is_arguments = object->HasSloppyArgumentsElements();
5912  {
5913    DisallowHeapAllocation no_gc;
5914    FixedArrayBase* elements = object->elements();
5915
5916    if (is_arguments) {
5917      FixedArray* parameter_map = FixedArray::cast(elements);
5918      elements = FixedArrayBase::cast(parameter_map->get(1));
5919    }
5920
5921    if (elements->IsDictionary()) {
5922      return handle(SeededNumberDictionary::cast(elements), isolate);
5923    }
5924  }
5925
5926  DCHECK(object->HasFastSmiOrObjectElements() ||
5927         object->HasFastDoubleElements() ||
5928         object->HasFastArgumentsElements() ||
5929         object->HasFastStringWrapperElements());
5930
5931  Handle<SeededNumberDictionary> dictionary =
5932      object->GetElementsAccessor()->Normalize(object);
5933
5934  // Switch to using the dictionary as the backing storage for elements.
5935  ElementsKind target_kind = is_arguments
5936                                 ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
5937                                 : object->HasFastStringWrapperElements()
5938                                       ? SLOW_STRING_WRAPPER_ELEMENTS
5939                                       : DICTIONARY_ELEMENTS;
5940  Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
5941  // Set the new map first to satify the elements type assert in set_elements().
5942  JSObject::MigrateToMap(object, new_map);
5943
5944  if (is_arguments) {
5945    FixedArray::cast(object->elements())->set(1, *dictionary);
5946  } else {
5947    object->set_elements(*dictionary);
5948  }
5949
5950  isolate->counters()->elements_to_dictionary()->Increment();
5951
5952#ifdef DEBUG
5953  if (FLAG_trace_normalization) {
5954    OFStream os(stdout);
5955    os << "Object elements have been normalized:\n";
5956    object->Print(os);
5957  }
5958#endif
5959
5960  DCHECK(object->HasDictionaryElements() ||
5961         object->HasSlowArgumentsElements() ||
5962         object->HasSlowStringWrapperElements());
5963  return dictionary;
5964}
5965
5966
5967static Smi* GenerateIdentityHash(Isolate* isolate) {
5968  int hash_value;
5969  int attempts = 0;
5970  do {
5971    // Generate a random 32-bit hash value but limit range to fit
5972    // within a smi.
5973    hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
5974    attempts++;
5975  } while (hash_value == 0 && attempts < 30);
5976  hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
5977
5978  return Smi::FromInt(hash_value);
5979}
5980
5981template <typename ProxyType>
5982static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
5983                                          Handle<ProxyType> proxy) {
5984  Object* maybe_hash = proxy->hash();
5985  if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
5986
5987  Smi* hash = GenerateIdentityHash(isolate);
5988  proxy->set_hash(hash);
5989  return hash;
5990}
5991
5992// static
5993Object* JSObject::GetIdentityHash(Isolate* isolate, Handle<JSObject> object) {
5994  if (object->IsJSGlobalProxy()) {
5995    return JSGlobalProxy::cast(*object)->hash();
5996  }
5997  Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
5998  return *JSReceiver::GetDataProperty(object, hash_code_symbol);
5999}
6000
6001// static
6002Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
6003                                       Handle<JSObject> object) {
6004  if (object->IsJSGlobalProxy()) {
6005    return GetOrCreateIdentityHashHelper(isolate,
6006                                         Handle<JSGlobalProxy>::cast(object));
6007  }
6008
6009  Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
6010  LookupIterator it(object, hash_code_symbol, object, LookupIterator::OWN);
6011  if (it.IsFound()) {
6012    DCHECK_EQ(LookupIterator::DATA, it.state());
6013    Object* maybe_hash = *it.GetDataValue();
6014    if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
6015  }
6016
6017  Smi* hash = GenerateIdentityHash(isolate);
6018  CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
6019                        CERTAINLY_NOT_STORE_FROM_KEYED)
6020            .IsJust());
6021  return hash;
6022}
6023
6024// static
6025Object* JSProxy::GetIdentityHash(Handle<JSProxy> proxy) {
6026  return proxy->hash();
6027}
6028
6029Smi* JSProxy::GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy) {
6030  return GetOrCreateIdentityHashHelper(isolate, proxy);
6031}
6032
6033
6034Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
6035                                                    ShouldThrow should_throw) {
6036  Isolate* isolate = it->isolate();
6037  // Make sure that the top context does not change when doing callbacks or
6038  // interceptor calls.
6039  AssertNoContextChange ncc(isolate);
6040
6041  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
6042  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
6043  if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
6044
6045  Handle<JSObject> holder = it->GetHolder<JSObject>();
6046  Handle<Object> receiver = it->GetReceiver();
6047  if (!receiver->IsJSReceiver()) {
6048    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
6049                                     Object::ConvertReceiver(isolate, receiver),
6050                                     Nothing<bool>());
6051  }
6052
6053  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
6054                                 *holder, should_throw);
6055  Handle<Object> result;
6056  if (it->IsElement()) {
6057    uint32_t index = it->index();
6058    v8::IndexedPropertyDeleterCallback deleter =
6059        v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
6060    result = args.Call(deleter, index);
6061  } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
6062    return Nothing<bool>();
6063  } else {
6064    Handle<Name> name = it->name();
6065    DCHECK(!name->IsPrivate());
6066    v8::GenericNamedPropertyDeleterCallback deleter =
6067        v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
6068            interceptor->deleter());
6069    result = args.Call(deleter, name);
6070  }
6071
6072  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6073  if (result.is_null()) return Nothing<bool>();
6074
6075  DCHECK(result->IsBoolean());
6076  // Rebox CustomArguments::kReturnValueOffset before returning.
6077  return Just(result->IsTrue(isolate));
6078}
6079
6080
6081void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
6082                                          Handle<Name> name, int entry) {
6083  DCHECK(!object->HasFastProperties());
6084  Isolate* isolate = object->GetIsolate();
6085
6086  if (object->IsJSGlobalObject()) {
6087    // If we have a global object, invalidate the cell and swap in a new one.
6088    Handle<GlobalDictionary> dictionary(
6089        JSObject::cast(*object)->global_dictionary());
6090    DCHECK_NE(GlobalDictionary::kNotFound, entry);
6091
6092    auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
6093    cell->set_value(isolate->heap()->the_hole_value());
6094    // TODO(ishell): InvalidateForDelete
6095    cell->set_property_details(
6096        cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
6097  } else {
6098    Handle<NameDictionary> dictionary(object->property_dictionary());
6099    DCHECK_NE(NameDictionary::kNotFound, entry);
6100
6101    NameDictionary::DeleteProperty(dictionary, entry);
6102    Handle<NameDictionary> new_properties =
6103        NameDictionary::Shrink(dictionary, name);
6104    object->set_properties(*new_properties);
6105  }
6106}
6107
6108
6109Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
6110                                       LanguageMode language_mode) {
6111  it->UpdateProtector();
6112
6113  Isolate* isolate = it->isolate();
6114
6115  if (it->state() == LookupIterator::JSPROXY) {
6116    return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
6117                                            it->GetName(), language_mode);
6118  }
6119
6120  if (it->GetReceiver()->IsJSProxy()) {
6121    if (it->state() != LookupIterator::NOT_FOUND) {
6122      DCHECK_EQ(LookupIterator::DATA, it->state());
6123      DCHECK(it->name()->IsPrivate());
6124      it->Delete();
6125    }
6126    return Just(true);
6127  }
6128  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
6129
6130  for (; it->IsFound(); it->Next()) {
6131    switch (it->state()) {
6132      case LookupIterator::JSPROXY:
6133      case LookupIterator::NOT_FOUND:
6134      case LookupIterator::TRANSITION:
6135        UNREACHABLE();
6136      case LookupIterator::ACCESS_CHECK:
6137        if (it->HasAccess()) break;
6138        isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
6139        RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6140        return Just(false);
6141      case LookupIterator::INTERCEPTOR: {
6142        ShouldThrow should_throw =
6143            is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
6144        Maybe<bool> result =
6145            JSObject::DeletePropertyWithInterceptor(it, should_throw);
6146        // An exception was thrown in the interceptor. Propagate.
6147        if (isolate->has_pending_exception()) return Nothing<bool>();
6148        // Delete with interceptor succeeded. Return result.
6149        // TODO(neis): In strict mode, we should probably throw if the
6150        // interceptor returns false.
6151        if (result.IsJust()) return result;
6152        break;
6153      }
6154      case LookupIterator::INTEGER_INDEXED_EXOTIC:
6155        return Just(true);
6156      case LookupIterator::DATA:
6157      case LookupIterator::ACCESSOR: {
6158        if (!it->IsConfigurable()) {
6159          // Fail if the property is not configurable.
6160          if (is_strict(language_mode)) {
6161            isolate->Throw(*isolate->factory()->NewTypeError(
6162                MessageTemplate::kStrictDeleteProperty, it->GetName(),
6163                receiver));
6164            return Nothing<bool>();
6165          }
6166          return Just(false);
6167        }
6168
6169        it->Delete();
6170
6171        return Just(true);
6172      }
6173    }
6174  }
6175
6176  return Just(true);
6177}
6178
6179
6180Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
6181                                      LanguageMode language_mode) {
6182  LookupIterator it(object->GetIsolate(), object, index, object,
6183                    LookupIterator::OWN);
6184  return DeleteProperty(&it, language_mode);
6185}
6186
6187
6188Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
6189                                       Handle<Name> name,
6190                                       LanguageMode language_mode) {
6191  LookupIterator it(object, name, object, LookupIterator::OWN);
6192  return DeleteProperty(&it, language_mode);
6193}
6194
6195
6196Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
6197                                                Handle<Name> name,
6198                                                LanguageMode language_mode) {
6199  LookupIterator it = LookupIterator::PropertyOrElement(
6200      name->GetIsolate(), object, name, object, LookupIterator::OWN);
6201  return DeleteProperty(&it, language_mode);
6202}
6203
6204
6205// ES6 7.1.14
6206// static
6207MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
6208                                          Handle<Object> value) {
6209  // 1. Let key be ToPrimitive(argument, hint String).
6210  MaybeHandle<Object> maybe_key =
6211      Object::ToPrimitive(value, ToPrimitiveHint::kString);
6212  // 2. ReturnIfAbrupt(key).
6213  Handle<Object> key;
6214  if (!maybe_key.ToHandle(&key)) return key;
6215  // 3. If Type(key) is Symbol, then return key.
6216  if (key->IsSymbol()) return key;
6217  // 4. Return ToString(key).
6218  // Extending spec'ed behavior, we'd be happy to return an element index.
6219  if (key->IsSmi()) return key;
6220  if (key->IsHeapNumber()) {
6221    uint32_t uint_value;
6222    if (value->ToArrayLength(&uint_value) &&
6223        uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
6224      return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
6225    }
6226  }
6227  return Object::ToString(isolate, key);
6228}
6229
6230
6231// ES6 19.1.2.4
6232// static
6233Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
6234                                   Handle<Object> key,
6235                                   Handle<Object> attributes) {
6236  // 1. If Type(O) is not Object, throw a TypeError exception.
6237  if (!object->IsJSReceiver()) {
6238    Handle<String> fun_name =
6239        isolate->factory()->InternalizeUtf8String("Object.defineProperty");
6240    THROW_NEW_ERROR_RETURN_FAILURE(
6241        isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
6242  }
6243  // 2. Let key be ToPropertyKey(P).
6244  // 3. ReturnIfAbrupt(key).
6245  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
6246  // 4. Let desc be ToPropertyDescriptor(Attributes).
6247  // 5. ReturnIfAbrupt(desc).
6248  PropertyDescriptor desc;
6249  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
6250    return isolate->heap()->exception();
6251  }
6252  // 6. Let success be DefinePropertyOrThrow(O,key, desc).
6253  Maybe<bool> success = DefineOwnProperty(
6254      isolate, Handle<JSReceiver>::cast(object), key, &desc, THROW_ON_ERROR);
6255  // 7. ReturnIfAbrupt(success).
6256  MAYBE_RETURN(success, isolate->heap()->exception());
6257  CHECK(success.FromJust());
6258  // 8. Return O.
6259  return *object;
6260}
6261
6262
6263// ES6 19.1.2.3.1
6264// static
6265MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
6266                                                 Handle<Object> object,
6267                                                 Handle<Object> properties) {
6268  // 1. If Type(O) is not Object, throw a TypeError exception.
6269  if (!object->IsJSReceiver()) {
6270    Handle<String> fun_name =
6271        isolate->factory()->InternalizeUtf8String("Object.defineProperties");
6272    THROW_NEW_ERROR(isolate,
6273                    NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
6274                    Object);
6275  }
6276  // 2. Let props be ToObject(Properties).
6277  // 3. ReturnIfAbrupt(props).
6278  Handle<JSReceiver> props;
6279  if (!Object::ToObject(isolate, properties).ToHandle(&props)) {
6280    THROW_NEW_ERROR(isolate,
6281                    NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
6282                    Object);
6283  }
6284  // 4. Let keys be props.[[OwnPropertyKeys]]().
6285  // 5. ReturnIfAbrupt(keys).
6286  Handle<FixedArray> keys;
6287  ASSIGN_RETURN_ON_EXCEPTION(
6288      isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
6289                                             ALL_PROPERTIES),
6290      Object);
6291  // 6. Let descriptors be an empty List.
6292  int capacity = keys->length();
6293  std::vector<PropertyDescriptor> descriptors(capacity);
6294  size_t descriptors_index = 0;
6295  // 7. Repeat for each element nextKey of keys in List order,
6296  for (int i = 0; i < keys->length(); ++i) {
6297    Handle<Object> next_key(keys->get(i), isolate);
6298    // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
6299    // 7b. ReturnIfAbrupt(propDesc).
6300    bool success = false;
6301    LookupIterator it = LookupIterator::PropertyOrElement(
6302        isolate, props, next_key, &success, LookupIterator::OWN);
6303    DCHECK(success);
6304    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
6305    if (!maybe.IsJust()) return MaybeHandle<Object>();
6306    PropertyAttributes attrs = maybe.FromJust();
6307    // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
6308    if (attrs == ABSENT) continue;
6309    if (attrs & DONT_ENUM) continue;
6310    // 7c i. Let descObj be Get(props, nextKey).
6311    // 7c ii. ReturnIfAbrupt(descObj).
6312    Handle<Object> desc_obj;
6313    ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
6314                               Object);
6315    // 7c iii. Let desc be ToPropertyDescriptor(descObj).
6316    success = PropertyDescriptor::ToPropertyDescriptor(
6317        isolate, desc_obj, &descriptors[descriptors_index]);
6318    // 7c iv. ReturnIfAbrupt(desc).
6319    if (!success) return MaybeHandle<Object>();
6320    // 7c v. Append the pair (a two element List) consisting of nextKey and
6321    //       desc to the end of descriptors.
6322    descriptors[descriptors_index].set_name(next_key);
6323    descriptors_index++;
6324  }
6325  // 8. For each pair from descriptors in list order,
6326  for (size_t i = 0; i < descriptors_index; ++i) {
6327    PropertyDescriptor* desc = &descriptors[i];
6328    // 8a. Let P be the first element of pair.
6329    // 8b. Let desc be the second element of pair.
6330    // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
6331    Maybe<bool> status =
6332        DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
6333                          desc->name(), desc, THROW_ON_ERROR);
6334    // 8d. ReturnIfAbrupt(status).
6335    if (!status.IsJust()) return MaybeHandle<Object>();
6336    CHECK(status.FromJust());
6337  }
6338  // 9. Return o.
6339  return object;
6340}
6341
6342
6343// static
6344Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
6345                                          Handle<JSReceiver> object,
6346                                          Handle<Object> key,
6347                                          PropertyDescriptor* desc,
6348                                          ShouldThrow should_throw) {
6349  if (object->IsJSArray()) {
6350    return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
6351                                      key, desc, should_throw);
6352  }
6353  if (object->IsJSProxy()) {
6354    return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
6355                                      key, desc, should_throw);
6356  }
6357  // TODO(jkummerow): Support Modules (ES6 9.4.6.6)
6358
6359  // OrdinaryDefineOwnProperty, by virtue of calling
6360  // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
6361  // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception:
6362  // TODO(jkummerow): Setting an indexed accessor on a typed array should throw.
6363  return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
6364                                   desc, should_throw);
6365}
6366
6367
6368// static
6369Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
6370                                                  Handle<JSObject> object,
6371                                                  Handle<Object> key,
6372                                                  PropertyDescriptor* desc,
6373                                                  ShouldThrow should_throw) {
6374  bool success = false;
6375  DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
6376  LookupIterator it = LookupIterator::PropertyOrElement(
6377      isolate, object, key, &success, LookupIterator::OWN);
6378  DCHECK(success);  // ...so creating a LookupIterator can't fail.
6379
6380  // Deal with access checks first.
6381  if (it.state() == LookupIterator::ACCESS_CHECK) {
6382    if (!it.HasAccess()) {
6383      isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6384      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6385      return Just(true);
6386    }
6387    it.Next();
6388  }
6389
6390  return OrdinaryDefineOwnProperty(&it, desc, should_throw);
6391}
6392
6393
6394// ES6 9.1.6.1
6395// static
6396Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
6397                                                  PropertyDescriptor* desc,
6398                                                  ShouldThrow should_throw) {
6399  Isolate* isolate = it->isolate();
6400  // 1. Let current be O.[[GetOwnProperty]](P).
6401  // 2. ReturnIfAbrupt(current).
6402  PropertyDescriptor current;
6403  MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
6404
6405  // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
6406  // the iterator every time. Currently, the reasons why we need it are:
6407  // - handle interceptors correctly
6408  // - handle accessors correctly (which might change the holder's map)
6409  it->Restart();
6410  // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
6411  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
6412  bool extensible = JSObject::IsExtensible(object);
6413
6414  return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc,
6415                                            &current, should_throw);
6416}
6417
6418
6419// ES6 9.1.6.2
6420// static
6421Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
6422    Isolate* isolate, bool extensible, PropertyDescriptor* desc,
6423    PropertyDescriptor* current, Handle<Name> property_name,
6424    ShouldThrow should_throw) {
6425  // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
6426  //    Extensible, Desc, Current).
6427  return ValidateAndApplyPropertyDescriptor(
6428      isolate, NULL, extensible, desc, current, should_throw, property_name);
6429}
6430
6431
6432// ES6 9.1.6.3
6433// static
6434Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
6435    Isolate* isolate, LookupIterator* it, bool extensible,
6436    PropertyDescriptor* desc, PropertyDescriptor* current,
6437    ShouldThrow should_throw, Handle<Name> property_name) {
6438  // We either need a LookupIterator, or a property name.
6439  DCHECK((it == NULL) != property_name.is_null());
6440  Handle<JSObject> object;
6441  if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver());
6442  bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
6443  bool desc_is_accessor_descriptor =
6444      PropertyDescriptor::IsAccessorDescriptor(desc);
6445  bool desc_is_generic_descriptor =
6446      PropertyDescriptor::IsGenericDescriptor(desc);
6447  // 1. (Assert)
6448  // 2. If current is undefined, then
6449  if (current->is_empty()) {
6450    // 2a. If extensible is false, return false.
6451    if (!extensible) {
6452      RETURN_FAILURE(isolate, should_throw,
6453                     NewTypeError(MessageTemplate::kDefineDisallowed,
6454                                  it != NULL ? it->GetName() : property_name));
6455    }
6456    // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
6457    // (This is equivalent to !IsAccessorDescriptor(desc).)
6458    DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
6459           !desc_is_accessor_descriptor);
6460    if (!desc_is_accessor_descriptor) {
6461      // 2c i. If O is not undefined, create an own data property named P of
6462      // object O whose [[Value]], [[Writable]], [[Enumerable]] and
6463      // [[Configurable]] attribute values are described by Desc. If the value
6464      // of an attribute field of Desc is absent, the attribute of the newly
6465      // created property is set to its default value.
6466      if (it != NULL) {
6467        if (!desc->has_writable()) desc->set_writable(false);
6468        if (!desc->has_enumerable()) desc->set_enumerable(false);
6469        if (!desc->has_configurable()) desc->set_configurable(false);
6470        Handle<Object> value(
6471            desc->has_value()
6472                ? desc->value()
6473                : Handle<Object>::cast(isolate->factory()->undefined_value()));
6474        MaybeHandle<Object> result =
6475            JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
6476                                                        desc->ToAttributes());
6477        if (result.is_null()) return Nothing<bool>();
6478      }
6479    } else {
6480      // 2d. Else Desc must be an accessor Property Descriptor,
6481      DCHECK(desc_is_accessor_descriptor);
6482      // 2d i. If O is not undefined, create an own accessor property named P
6483      // of object O whose [[Get]], [[Set]], [[Enumerable]] and
6484      // [[Configurable]] attribute values are described by Desc. If the value
6485      // of an attribute field of Desc is absent, the attribute of the newly
6486      // created property is set to its default value.
6487      if (it != NULL) {
6488        if (!desc->has_enumerable()) desc->set_enumerable(false);
6489        if (!desc->has_configurable()) desc->set_configurable(false);
6490        Handle<Object> getter(
6491            desc->has_get()
6492                ? desc->get()
6493                : Handle<Object>::cast(isolate->factory()->null_value()));
6494        Handle<Object> setter(
6495            desc->has_set()
6496                ? desc->set()
6497                : Handle<Object>::cast(isolate->factory()->null_value()));
6498        MaybeHandle<Object> result =
6499            JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
6500        if (result.is_null()) return Nothing<bool>();
6501      }
6502    }
6503    // 2e. Return true.
6504    return Just(true);
6505  }
6506  // 3. Return true, if every field in Desc is absent.
6507  // 4. Return true, if every field in Desc also occurs in current and the
6508  // value of every field in Desc is the same value as the corresponding field
6509  // in current when compared using the SameValue algorithm.
6510  if ((!desc->has_enumerable() ||
6511       desc->enumerable() == current->enumerable()) &&
6512      (!desc->has_configurable() ||
6513       desc->configurable() == current->configurable()) &&
6514      (!desc->has_value() ||
6515       (current->has_value() && current->value()->SameValue(*desc->value()))) &&
6516      (!desc->has_writable() ||
6517       (current->has_writable() && current->writable() == desc->writable())) &&
6518      (!desc->has_get() ||
6519       (current->has_get() && current->get()->SameValue(*desc->get()))) &&
6520      (!desc->has_set() ||
6521       (current->has_set() && current->set()->SameValue(*desc->set())))) {
6522    return Just(true);
6523  }
6524  // 5. If the [[Configurable]] field of current is false, then
6525  if (!current->configurable()) {
6526    // 5a. Return false, if the [[Configurable]] field of Desc is true.
6527    if (desc->has_configurable() && desc->configurable()) {
6528      RETURN_FAILURE(isolate, should_throw,
6529                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6530                                  it != NULL ? it->GetName() : property_name));
6531    }
6532    // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
6533    // [[Enumerable]] fields of current and Desc are the Boolean negation of
6534    // each other.
6535    if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
6536      RETURN_FAILURE(isolate, should_throw,
6537                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6538                                  it != NULL ? it->GetName() : property_name));
6539    }
6540  }
6541
6542  bool current_is_data_descriptor =
6543      PropertyDescriptor::IsDataDescriptor(current);
6544  // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
6545  if (desc_is_generic_descriptor) {
6546    // Nothing to see here.
6547
6548    // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
6549    // different results, then:
6550  } else if (current_is_data_descriptor != desc_is_data_descriptor) {
6551    // 7a. Return false, if the [[Configurable]] field of current is false.
6552    if (!current->configurable()) {
6553      RETURN_FAILURE(isolate, should_throw,
6554                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6555                                  it != NULL ? it->GetName() : property_name));
6556    }
6557    // 7b. If IsDataDescriptor(current) is true, then:
6558    if (current_is_data_descriptor) {
6559      // 7b i. If O is not undefined, convert the property named P of object O
6560      // from a data property to an accessor property. Preserve the existing
6561      // values of the converted property's [[Configurable]] and [[Enumerable]]
6562      // attributes and set the rest of the property's attributes to their
6563      // default values.
6564      // --> Folded into step 10.
6565    } else {
6566      // 7c i. If O is not undefined, convert the property named P of object O
6567      // from an accessor property to a data property. Preserve the existing
6568      // values of the converted property’s [[Configurable]] and [[Enumerable]]
6569      // attributes and set the rest of the property’s attributes to their
6570      // default values.
6571      // --> Folded into step 10.
6572    }
6573
6574    // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
6575    // true, then:
6576  } else if (current_is_data_descriptor && desc_is_data_descriptor) {
6577    // 8a. If the [[Configurable]] field of current is false, then:
6578    if (!current->configurable()) {
6579      // 8a i. Return false, if the [[Writable]] field of current is false and
6580      // the [[Writable]] field of Desc is true.
6581      if (!current->writable() && desc->has_writable() && desc->writable()) {
6582        RETURN_FAILURE(
6583            isolate, should_throw,
6584            NewTypeError(MessageTemplate::kRedefineDisallowed,
6585                         it != NULL ? it->GetName() : property_name));
6586      }
6587      // 8a ii. If the [[Writable]] field of current is false, then:
6588      if (!current->writable()) {
6589        // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
6590        // SameValue(Desc.[[Value]], current.[[Value]]) is false.
6591        if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
6592          RETURN_FAILURE(
6593              isolate, should_throw,
6594              NewTypeError(MessageTemplate::kRedefineDisallowed,
6595                           it != NULL ? it->GetName() : property_name));
6596        }
6597      }
6598    }
6599  } else {
6600    // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
6601    // are both true,
6602    DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
6603           desc_is_accessor_descriptor);
6604    // 9a. If the [[Configurable]] field of current is false, then:
6605    if (!current->configurable()) {
6606      // 9a i. Return false, if the [[Set]] field of Desc is present and
6607      // SameValue(Desc.[[Set]], current.[[Set]]) is false.
6608      if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
6609        RETURN_FAILURE(
6610            isolate, should_throw,
6611            NewTypeError(MessageTemplate::kRedefineDisallowed,
6612                         it != NULL ? it->GetName() : property_name));
6613      }
6614      // 9a ii. Return false, if the [[Get]] field of Desc is present and
6615      // SameValue(Desc.[[Get]], current.[[Get]]) is false.
6616      if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
6617        RETURN_FAILURE(
6618            isolate, should_throw,
6619            NewTypeError(MessageTemplate::kRedefineDisallowed,
6620                         it != NULL ? it->GetName() : property_name));
6621      }
6622    }
6623  }
6624
6625  // 10. If O is not undefined, then:
6626  if (it != NULL) {
6627    // 10a. For each field of Desc that is present, set the corresponding
6628    // attribute of the property named P of object O to the value of the field.
6629    PropertyAttributes attrs = NONE;
6630
6631    if (desc->has_enumerable()) {
6632      attrs = static_cast<PropertyAttributes>(
6633          attrs | (desc->enumerable() ? NONE : DONT_ENUM));
6634    } else {
6635      attrs = static_cast<PropertyAttributes>(
6636          attrs | (current->enumerable() ? NONE : DONT_ENUM));
6637    }
6638    if (desc->has_configurable()) {
6639      attrs = static_cast<PropertyAttributes>(
6640          attrs | (desc->configurable() ? NONE : DONT_DELETE));
6641    } else {
6642      attrs = static_cast<PropertyAttributes>(
6643          attrs | (current->configurable() ? NONE : DONT_DELETE));
6644    }
6645    if (desc_is_data_descriptor ||
6646        (desc_is_generic_descriptor && current_is_data_descriptor)) {
6647      if (desc->has_writable()) {
6648        attrs = static_cast<PropertyAttributes>(
6649            attrs | (desc->writable() ? NONE : READ_ONLY));
6650      } else {
6651        attrs = static_cast<PropertyAttributes>(
6652            attrs | (current->writable() ? NONE : READ_ONLY));
6653      }
6654      Handle<Object> value(
6655          desc->has_value() ? desc->value()
6656                            : current->has_value()
6657                                  ? current->value()
6658                                  : Handle<Object>::cast(
6659                                        isolate->factory()->undefined_value()));
6660      MaybeHandle<Object> result =
6661          JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs);
6662      if (result.is_null()) return Nothing<bool>();
6663    } else {
6664      DCHECK(desc_is_accessor_descriptor ||
6665             (desc_is_generic_descriptor &&
6666              PropertyDescriptor::IsAccessorDescriptor(current)));
6667      Handle<Object> getter(
6668          desc->has_get()
6669              ? desc->get()
6670              : current->has_get()
6671                    ? current->get()
6672                    : Handle<Object>::cast(isolate->factory()->null_value()));
6673      Handle<Object> setter(
6674          desc->has_set()
6675              ? desc->set()
6676              : current->has_set()
6677                    ? current->set()
6678                    : Handle<Object>::cast(isolate->factory()->null_value()));
6679      MaybeHandle<Object> result =
6680          JSObject::DefineAccessor(it, getter, setter, attrs);
6681      if (result.is_null()) return Nothing<bool>();
6682    }
6683  }
6684
6685  // 11. Return true.
6686  return Just(true);
6687}
6688
6689
6690// static
6691Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
6692                                           Handle<Object> value,
6693                                           ShouldThrow should_throw) {
6694  DCHECK(!it->check_prototype_chain());
6695  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
6696  Isolate* isolate = receiver->GetIsolate();
6697
6698  if (receiver->IsJSObject()) {
6699    return JSObject::CreateDataProperty(it, value, should_throw);  // Shortcut.
6700  }
6701
6702  PropertyDescriptor new_desc;
6703  new_desc.set_value(value);
6704  new_desc.set_writable(true);
6705  new_desc.set_enumerable(true);
6706  new_desc.set_configurable(true);
6707
6708  return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
6709                                       &new_desc, should_throw);
6710}
6711
6712Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
6713                                         Handle<Object> value,
6714                                         ShouldThrow should_throw) {
6715  DCHECK(it->GetReceiver()->IsJSObject());
6716  MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
6717  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
6718  Isolate* isolate = receiver->GetIsolate();
6719
6720  if (it->IsFound()) {
6721    Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
6722    MAYBE_RETURN(attributes, Nothing<bool>());
6723    if ((attributes.FromJust() & DONT_DELETE) != 0) {
6724      RETURN_FAILURE(
6725          isolate, should_throw,
6726          NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
6727    }
6728  } else {
6729    if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
6730      RETURN_FAILURE(
6731          isolate, should_throw,
6732          NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
6733    }
6734  }
6735
6736  RETURN_ON_EXCEPTION_VALUE(it->isolate(),
6737                            DefineOwnPropertyIgnoreAttributes(it, value, NONE),
6738                            Nothing<bool>());
6739
6740  return Just(true);
6741}
6742
6743
6744// TODO(jkummerow): Consider unification with FastAsArrayLength() in
6745// accessors.cc.
6746bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
6747  DCHECK(value->IsNumber() || value->IsName());
6748  if (value->ToArrayLength(length)) return true;
6749  if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
6750  return false;
6751}
6752
6753
6754bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
6755  return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
6756}
6757
6758
6759// ES6 9.4.2.1
6760// static
6761Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
6762                                       Handle<Object> name,
6763                                       PropertyDescriptor* desc,
6764                                       ShouldThrow should_throw) {
6765  // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
6766  // 2. If P is "length", then:
6767  // TODO(jkummerow): Check if we need slow string comparison.
6768  if (*name == isolate->heap()->length_string()) {
6769    // 2a. Return ArraySetLength(A, Desc).
6770    return ArraySetLength(isolate, o, desc, should_throw);
6771  }
6772  // 3. Else if P is an array index, then:
6773  uint32_t index = 0;
6774  if (PropertyKeyToArrayIndex(name, &index)) {
6775    // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
6776    PropertyDescriptor old_len_desc;
6777    Maybe<bool> success = GetOwnPropertyDescriptor(
6778        isolate, o, isolate->factory()->length_string(), &old_len_desc);
6779    // 3b. (Assert)
6780    DCHECK(success.FromJust());
6781    USE(success);
6782    // 3c. Let oldLen be oldLenDesc.[[Value]].
6783    uint32_t old_len = 0;
6784    CHECK(old_len_desc.value()->ToArrayLength(&old_len));
6785    // 3d. Let index be ToUint32(P).
6786    // (Already done above.)
6787    // 3e. (Assert)
6788    // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
6789    //     return false.
6790    if (index >= old_len && old_len_desc.has_writable() &&
6791        !old_len_desc.writable()) {
6792      RETURN_FAILURE(isolate, should_throw,
6793                     NewTypeError(MessageTemplate::kDefineDisallowed, name));
6794    }
6795    // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
6796    Maybe<bool> succeeded =
6797        OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
6798    // 3h. Assert: succeeded is not an abrupt completion.
6799    //     In our case, if should_throw == THROW_ON_ERROR, it can be!
6800    // 3i. If succeeded is false, return false.
6801    if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
6802    // 3j. If index >= oldLen, then:
6803    if (index >= old_len) {
6804      // 3j i. Set oldLenDesc.[[Value]] to index + 1.
6805      old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
6806      // 3j ii. Let succeeded be
6807      //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
6808      succeeded = OrdinaryDefineOwnProperty(isolate, o,
6809                                            isolate->factory()->length_string(),
6810                                            &old_len_desc, should_throw);
6811      // 3j iii. Assert: succeeded is true.
6812      DCHECK(succeeded.FromJust());
6813      USE(succeeded);
6814    }
6815    // 3k. Return true.
6816    return Just(true);
6817  }
6818
6819  // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
6820  return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
6821}
6822
6823
6824// Part of ES6 9.4.2.4 ArraySetLength.
6825// static
6826bool JSArray::AnythingToArrayLength(Isolate* isolate,
6827                                    Handle<Object> length_object,
6828                                    uint32_t* output) {
6829  // Fast path: check numbers and strings that can be converted directly
6830  // and unobservably.
6831  if (length_object->ToArrayLength(output)) return true;
6832  if (length_object->IsString() &&
6833      Handle<String>::cast(length_object)->AsArrayIndex(output)) {
6834    return true;
6835  }
6836  // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
6837  // 3. Let newLen be ToUint32(Desc.[[Value]]).
6838  Handle<Object> uint32_v;
6839  if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
6840    // 4. ReturnIfAbrupt(newLen).
6841    return false;
6842  }
6843  // 5. Let numberLen be ToNumber(Desc.[[Value]]).
6844  Handle<Object> number_v;
6845  if (!Object::ToNumber(length_object).ToHandle(&number_v)) {
6846    // 6. ReturnIfAbrupt(newLen).
6847    return false;
6848  }
6849  // 7. If newLen != numberLen, throw a RangeError exception.
6850  if (uint32_v->Number() != number_v->Number()) {
6851    Handle<Object> exception =
6852        isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
6853    isolate->Throw(*exception);
6854    return false;
6855  }
6856  CHECK(uint32_v->ToArrayLength(output));
6857  return true;
6858}
6859
6860
6861// ES6 9.4.2.4
6862// static
6863Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
6864                                    PropertyDescriptor* desc,
6865                                    ShouldThrow should_throw) {
6866  // 1. If the [[Value]] field of Desc is absent, then
6867  if (!desc->has_value()) {
6868    // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
6869    return OrdinaryDefineOwnProperty(
6870        isolate, a, isolate->factory()->length_string(), desc, should_throw);
6871  }
6872  // 2. Let newLenDesc be a copy of Desc.
6873  // (Actual copying is not necessary.)
6874  PropertyDescriptor* new_len_desc = desc;
6875  // 3. - 7. Convert Desc.[[Value]] to newLen.
6876  uint32_t new_len = 0;
6877  if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
6878    DCHECK(isolate->has_pending_exception());
6879    return Nothing<bool>();
6880  }
6881  // 8. Set newLenDesc.[[Value]] to newLen.
6882  // (Done below, if needed.)
6883  // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
6884  PropertyDescriptor old_len_desc;
6885  Maybe<bool> success = GetOwnPropertyDescriptor(
6886      isolate, a, isolate->factory()->length_string(), &old_len_desc);
6887  // 10. (Assert)
6888  DCHECK(success.FromJust());
6889  USE(success);
6890  // 11. Let oldLen be oldLenDesc.[[Value]].
6891  uint32_t old_len = 0;
6892  CHECK(old_len_desc.value()->ToArrayLength(&old_len));
6893  // 12. If newLen >= oldLen, then
6894  if (new_len >= old_len) {
6895    // 8. Set newLenDesc.[[Value]] to newLen.
6896    // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
6897    new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
6898    return OrdinaryDefineOwnProperty(isolate, a,
6899                                     isolate->factory()->length_string(),
6900                                     new_len_desc, should_throw);
6901  }
6902  // 13. If oldLenDesc.[[Writable]] is false, return false.
6903  if (!old_len_desc.writable()) {
6904    RETURN_FAILURE(isolate, should_throw,
6905                   NewTypeError(MessageTemplate::kRedefineDisallowed,
6906                                isolate->factory()->length_string()));
6907  }
6908  // 14. If newLenDesc.[[Writable]] is absent or has the value true,
6909  // let newWritable be true.
6910  bool new_writable = false;
6911  if (!new_len_desc->has_writable() || new_len_desc->writable()) {
6912    new_writable = true;
6913  } else {
6914    // 15. Else,
6915    // 15a. Need to defer setting the [[Writable]] attribute to false in case
6916    //      any elements cannot be deleted.
6917    // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
6918    // 15c. Set newLenDesc.[[Writable]] to true.
6919    // (Not needed.)
6920  }
6921  // Most of steps 16 through 19 is implemented by JSArray::SetLength.
6922  JSArray::SetLength(a, new_len);
6923  // Steps 19d-ii, 20.
6924  if (!new_writable) {
6925    PropertyDescriptor readonly;
6926    readonly.set_writable(false);
6927    Maybe<bool> success = OrdinaryDefineOwnProperty(
6928        isolate, a, isolate->factory()->length_string(), &readonly,
6929        should_throw);
6930    DCHECK(success.FromJust());
6931    USE(success);
6932  }
6933  uint32_t actual_new_len = 0;
6934  CHECK(a->length()->ToArrayLength(&actual_new_len));
6935  // Steps 19d-v, 21. Return false if there were non-deletable elements.
6936  bool result = actual_new_len == new_len;
6937  if (!result) {
6938    RETURN_FAILURE(
6939        isolate, should_throw,
6940        NewTypeError(MessageTemplate::kStrictDeleteProperty,
6941                     isolate->factory()->NewNumberFromUint(actual_new_len - 1),
6942                     a));
6943  }
6944  return Just(result);
6945}
6946
6947
6948// ES6 9.5.6
6949// static
6950Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
6951                                       Handle<Object> key,
6952                                       PropertyDescriptor* desc,
6953                                       ShouldThrow should_throw) {
6954  STACK_CHECK(isolate, Nothing<bool>());
6955  if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
6956    return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc,
6957                              should_throw);
6958  }
6959  Handle<String> trap_name = isolate->factory()->defineProperty_string();
6960  // 1. Assert: IsPropertyKey(P) is true.
6961  DCHECK(key->IsName() || key->IsNumber());
6962  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
6963  Handle<Object> handler(proxy->handler(), isolate);
6964  // 3. If handler is null, throw a TypeError exception.
6965  // 4. Assert: Type(handler) is Object.
6966  if (proxy->IsRevoked()) {
6967    isolate->Throw(*isolate->factory()->NewTypeError(
6968        MessageTemplate::kProxyRevoked, trap_name));
6969    return Nothing<bool>();
6970  }
6971  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
6972  Handle<JSReceiver> target(proxy->target(), isolate);
6973  // 6. Let trap be ? GetMethod(handler, "defineProperty").
6974  Handle<Object> trap;
6975  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6976      isolate, trap,
6977      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
6978      Nothing<bool>());
6979  // 7. If trap is undefined, then:
6980  if (trap->IsUndefined(isolate)) {
6981    // 7a. Return target.[[DefineOwnProperty]](P, Desc).
6982    return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
6983                                         should_throw);
6984  }
6985  // 8. Let descObj be FromPropertyDescriptor(Desc).
6986  Handle<Object> desc_obj = desc->ToObject(isolate);
6987  // 9. Let booleanTrapResult be
6988  //    ToBoolean(? Call(trap, handler, «target, P, descObj»)).
6989  Handle<Name> property_name =
6990      key->IsName()
6991          ? Handle<Name>::cast(key)
6992          : Handle<Name>::cast(isolate->factory()->NumberToString(key));
6993  // Do not leak private property names.
6994  DCHECK(!property_name->IsPrivate());
6995  Handle<Object> trap_result_obj;
6996  Handle<Object> args[] = {target, property_name, desc_obj};
6997  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6998      isolate, trap_result_obj,
6999      Execution::Call(isolate, trap, handler, arraysize(args), args),
7000      Nothing<bool>());
7001  // 10. If booleanTrapResult is false, return false.
7002  if (!trap_result_obj->BooleanValue()) {
7003    RETURN_FAILURE(isolate, should_throw,
7004                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
7005                                trap_name, property_name));
7006  }
7007  // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
7008  PropertyDescriptor target_desc;
7009  Maybe<bool> target_found =
7010      JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
7011  MAYBE_RETURN(target_found, Nothing<bool>());
7012  // 12. Let extensibleTarget be ? IsExtensible(target).
7013  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
7014  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
7015  bool extensible_target = maybe_extensible.FromJust();
7016  // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
7017  //     is false, then:
7018  // 13a. Let settingConfigFalse be true.
7019  // 14. Else let settingConfigFalse be false.
7020  bool setting_config_false = desc->has_configurable() && !desc->configurable();
7021  // 15. If targetDesc is undefined, then
7022  if (!target_found.FromJust()) {
7023    // 15a. If extensibleTarget is false, throw a TypeError exception.
7024    if (!extensible_target) {
7025      isolate->Throw(*isolate->factory()->NewTypeError(
7026          MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
7027      return Nothing<bool>();
7028    }
7029    // 15b. If settingConfigFalse is true, throw a TypeError exception.
7030    if (setting_config_false) {
7031      isolate->Throw(*isolate->factory()->NewTypeError(
7032          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7033      return Nothing<bool>();
7034    }
7035  } else {
7036    // 16. Else targetDesc is not undefined,
7037    // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
7038    //      targetDesc) is false, throw a TypeError exception.
7039    Maybe<bool> valid =
7040        IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
7041                                       &target_desc, property_name, DONT_THROW);
7042    MAYBE_RETURN(valid, Nothing<bool>());
7043    if (!valid.FromJust()) {
7044      isolate->Throw(*isolate->factory()->NewTypeError(
7045          MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
7046      return Nothing<bool>();
7047    }
7048    // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
7049    //      true, throw a TypeError exception.
7050    if (setting_config_false && target_desc.configurable()) {
7051      isolate->Throw(*isolate->factory()->NewTypeError(
7052          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7053      return Nothing<bool>();
7054    }
7055  }
7056  // 17. Return true.
7057  return Just(true);
7058}
7059
7060
7061// static
7062Maybe<bool> JSProxy::SetPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy,
7063                                        Handle<Symbol> private_name,
7064                                        PropertyDescriptor* desc,
7065                                        ShouldThrow should_throw) {
7066  // Despite the generic name, this can only add private data properties.
7067  if (!PropertyDescriptor::IsDataDescriptor(desc) ||
7068      desc->ToAttributes() != DONT_ENUM) {
7069    RETURN_FAILURE(isolate, should_throw,
7070                   NewTypeError(MessageTemplate::kProxyPrivate));
7071  }
7072  DCHECK(proxy->map()->is_dictionary_map());
7073  Handle<Object> value =
7074      desc->has_value()
7075          ? desc->value()
7076          : Handle<Object>::cast(isolate->factory()->undefined_value());
7077
7078  LookupIterator it(proxy, private_name, proxy);
7079
7080  if (it.IsFound()) {
7081    DCHECK_EQ(LookupIterator::DATA, it.state());
7082    DCHECK_EQ(DONT_ENUM, it.property_attributes());
7083    it.WriteDataValue(value);
7084    return Just(true);
7085  }
7086
7087  Handle<NameDictionary> dict(proxy->property_dictionary());
7088  PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell);
7089  Handle<NameDictionary> result =
7090      NameDictionary::Add(dict, private_name, value, details);
7091  if (!dict.is_identical_to(result)) proxy->set_properties(*result);
7092  return Just(true);
7093}
7094
7095
7096// static
7097Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
7098                                                 Handle<JSReceiver> object,
7099                                                 Handle<Object> key,
7100                                                 PropertyDescriptor* desc) {
7101  bool success = false;
7102  DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
7103  LookupIterator it = LookupIterator::PropertyOrElement(
7104      isolate, object, key, &success, LookupIterator::OWN);
7105  DCHECK(success);  // ...so creating a LookupIterator can't fail.
7106  return GetOwnPropertyDescriptor(&it, desc);
7107}
7108
7109
7110// ES6 9.1.5.1
7111// Returns true on success, false if the property didn't exist, nothing if
7112// an exception was thrown.
7113// static
7114Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
7115                                                 PropertyDescriptor* desc) {
7116  Isolate* isolate = it->isolate();
7117  // "Virtual" dispatch.
7118  if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
7119    return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
7120                                             it->GetName(), desc);
7121  }
7122
7123  // 1. (Assert)
7124  // 2. If O does not have an own property with key P, return undefined.
7125  Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
7126  MAYBE_RETURN(maybe, Nothing<bool>());
7127  PropertyAttributes attrs = maybe.FromJust();
7128  if (attrs == ABSENT) return Just(false);
7129  DCHECK(!isolate->has_pending_exception());
7130
7131  // 3. Let D be a newly created Property Descriptor with no fields.
7132  DCHECK(desc->is_empty());
7133  // 4. Let X be O's own property whose key is P.
7134  // 5. If X is a data property, then
7135  bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
7136                          it->GetAccessors()->IsAccessorPair();
7137  if (!is_accessor_pair) {
7138    // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
7139    Handle<Object> value;
7140    if (!Object::GetProperty(it).ToHandle(&value)) {
7141      DCHECK(isolate->has_pending_exception());
7142      return Nothing<bool>();
7143    }
7144    desc->set_value(value);
7145    // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
7146    desc->set_writable((attrs & READ_ONLY) == 0);
7147  } else {
7148    // 6. Else X is an accessor property, so
7149    Handle<AccessorPair> accessors =
7150        Handle<AccessorPair>::cast(it->GetAccessors());
7151    // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
7152    desc->set_get(AccessorPair::GetComponent(accessors, ACCESSOR_GETTER));
7153    // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
7154    desc->set_set(AccessorPair::GetComponent(accessors, ACCESSOR_SETTER));
7155  }
7156
7157  // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
7158  desc->set_enumerable((attrs & DONT_ENUM) == 0);
7159  // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
7160  desc->set_configurable((attrs & DONT_DELETE) == 0);
7161  // 9. Return D.
7162  DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
7163         PropertyDescriptor::IsDataDescriptor(desc));
7164  return Just(true);
7165}
7166
7167
7168// ES6 9.5.5
7169// static
7170Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
7171                                              Handle<JSProxy> proxy,
7172                                              Handle<Name> name,
7173                                              PropertyDescriptor* desc) {
7174  DCHECK(!name->IsPrivate());
7175  STACK_CHECK(isolate, Nothing<bool>());
7176
7177  Handle<String> trap_name =
7178      isolate->factory()->getOwnPropertyDescriptor_string();
7179  // 1. (Assert)
7180  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
7181  Handle<Object> handler(proxy->handler(), isolate);
7182  // 3. If handler is null, throw a TypeError exception.
7183  // 4. Assert: Type(handler) is Object.
7184  if (proxy->IsRevoked()) {
7185    isolate->Throw(*isolate->factory()->NewTypeError(
7186        MessageTemplate::kProxyRevoked, trap_name));
7187    return Nothing<bool>();
7188  }
7189  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
7190  Handle<JSReceiver> target(proxy->target(), isolate);
7191  // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
7192  Handle<Object> trap;
7193  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7194      isolate, trap,
7195      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
7196      Nothing<bool>());
7197  // 7. If trap is undefined, then
7198  if (trap->IsUndefined(isolate)) {
7199    // 7a. Return target.[[GetOwnProperty]](P).
7200    return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
7201  }
7202  // 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
7203  Handle<Object> trap_result_obj;
7204  Handle<Object> args[] = {target, name};
7205  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7206      isolate, trap_result_obj,
7207      Execution::Call(isolate, trap, handler, arraysize(args), args),
7208      Nothing<bool>());
7209  // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
7210  //    TypeError exception.
7211  if (!trap_result_obj->IsJSReceiver() &&
7212      !trap_result_obj->IsUndefined(isolate)) {
7213    isolate->Throw(*isolate->factory()->NewTypeError(
7214        MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
7215    return Nothing<bool>();
7216  }
7217  // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
7218  PropertyDescriptor target_desc;
7219  Maybe<bool> found =
7220      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
7221  MAYBE_RETURN(found, Nothing<bool>());
7222  // 11. If trapResultObj is undefined, then
7223  if (trap_result_obj->IsUndefined(isolate)) {
7224    // 11a. If targetDesc is undefined, return undefined.
7225    if (!found.FromJust()) return Just(false);
7226    // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
7227    //      exception.
7228    if (!target_desc.configurable()) {
7229      isolate->Throw(*isolate->factory()->NewTypeError(
7230          MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
7231      return Nothing<bool>();
7232    }
7233    // 11c. Let extensibleTarget be ? IsExtensible(target).
7234    Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
7235    MAYBE_RETURN(extensible_target, Nothing<bool>());
7236    // 11d. (Assert)
7237    // 11e. If extensibleTarget is false, throw a TypeError exception.
7238    if (!extensible_target.FromJust()) {
7239      isolate->Throw(*isolate->factory()->NewTypeError(
7240          MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
7241      return Nothing<bool>();
7242    }
7243    // 11f. Return undefined.
7244    return Just(false);
7245  }
7246  // 12. Let extensibleTarget be ? IsExtensible(target).
7247  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
7248  MAYBE_RETURN(extensible_target, Nothing<bool>());
7249  // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
7250  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
7251                                                desc)) {
7252    DCHECK(isolate->has_pending_exception());
7253    return Nothing<bool>();
7254  }
7255  // 14. Call CompletePropertyDescriptor(resultDesc).
7256  PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
7257  // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
7258  //     resultDesc, targetDesc).
7259  Maybe<bool> valid =
7260      IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
7261                                     desc, &target_desc, name, DONT_THROW);
7262  MAYBE_RETURN(valid, Nothing<bool>());
7263  // 16. If valid is false, throw a TypeError exception.
7264  if (!valid.FromJust()) {
7265    isolate->Throw(*isolate->factory()->NewTypeError(
7266        MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
7267    return Nothing<bool>();
7268  }
7269  // 17. If resultDesc.[[Configurable]] is false, then
7270  if (!desc->configurable()) {
7271    // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
7272    if (target_desc.is_empty() || target_desc.configurable()) {
7273      // 17a i. Throw a TypeError exception.
7274      isolate->Throw(*isolate->factory()->NewTypeError(
7275          MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
7276          name));
7277      return Nothing<bool>();
7278    }
7279  }
7280  // 18. Return resultDesc.
7281  return Just(true);
7282}
7283
7284
7285bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
7286                                            ElementsKind kind,
7287                                            Object* object) {
7288  Isolate* isolate = elements->GetIsolate();
7289  if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
7290    int length = IsJSArray()
7291        ? Smi::cast(JSArray::cast(this)->length())->value()
7292        : elements->length();
7293    for (int i = 0; i < length; ++i) {
7294      Object* element = elements->get(i);
7295      if (!element->IsTheHole(isolate) && element == object) return true;
7296    }
7297  } else {
7298    DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
7299    Object* key =
7300        SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
7301    if (!key->IsUndefined(isolate)) return true;
7302  }
7303  return false;
7304}
7305
7306
7307// Check whether this object references another object.
7308bool JSObject::ReferencesObject(Object* obj) {
7309  Map* map_of_this = map();
7310  Heap* heap = GetHeap();
7311  DisallowHeapAllocation no_allocation;
7312
7313  // Is the object the constructor for this object?
7314  if (map_of_this->GetConstructor() == obj) {
7315    return true;
7316  }
7317
7318  // Is the object the prototype for this object?
7319  if (map_of_this->prototype() == obj) {
7320    return true;
7321  }
7322
7323  // Check if the object is among the named properties.
7324  Object* key = SlowReverseLookup(obj);
7325  if (!key->IsUndefined(heap->isolate())) {
7326    return true;
7327  }
7328
7329  // Check if the object is among the indexed properties.
7330  ElementsKind kind = GetElementsKind();
7331  switch (kind) {
7332    // Raw pixels and external arrays do not reference other
7333    // objects.
7334#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
7335    case TYPE##_ELEMENTS:                                                      \
7336      break;
7337
7338    TYPED_ARRAYS(TYPED_ARRAY_CASE)
7339#undef TYPED_ARRAY_CASE
7340
7341    case FAST_DOUBLE_ELEMENTS:
7342    case FAST_HOLEY_DOUBLE_ELEMENTS:
7343      break;
7344    case FAST_SMI_ELEMENTS:
7345    case FAST_HOLEY_SMI_ELEMENTS:
7346      break;
7347    case FAST_ELEMENTS:
7348    case FAST_HOLEY_ELEMENTS:
7349    case DICTIONARY_ELEMENTS:
7350    case FAST_STRING_WRAPPER_ELEMENTS:
7351    case SLOW_STRING_WRAPPER_ELEMENTS: {
7352      FixedArray* elements = FixedArray::cast(this->elements());
7353      if (ReferencesObjectFromElements(elements, kind, obj)) return true;
7354      break;
7355    }
7356    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
7357    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
7358      FixedArray* parameter_map = FixedArray::cast(elements());
7359      // Check the mapped parameters.
7360      int length = parameter_map->length();
7361      for (int i = 2; i < length; ++i) {
7362        Object* value = parameter_map->get(i);
7363        if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
7364      }
7365      // Check the arguments.
7366      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7367      kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
7368          FAST_HOLEY_ELEMENTS;
7369      if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
7370      break;
7371    }
7372    case NO_ELEMENTS:
7373      break;
7374  }
7375
7376  // For functions check the context.
7377  if (IsJSFunction()) {
7378    // Get the constructor function for arguments array.
7379    Map* arguments_map =
7380        heap->isolate()->context()->native_context()->sloppy_arguments_map();
7381    JSFunction* arguments_function =
7382        JSFunction::cast(arguments_map->GetConstructor());
7383
7384    // Get the context and don't check if it is the native context.
7385    JSFunction* f = JSFunction::cast(this);
7386    Context* context = f->context();
7387    if (context->IsNativeContext()) {
7388      return false;
7389    }
7390
7391    // Check the non-special context slots.
7392    for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
7393      // Only check JS objects.
7394      if (context->get(i)->IsJSObject()) {
7395        JSObject* ctxobj = JSObject::cast(context->get(i));
7396        // If it is an arguments array check the content.
7397        if (ctxobj->map()->GetConstructor() == arguments_function) {
7398          if (ctxobj->ReferencesObject(obj)) {
7399            return true;
7400          }
7401        } else if (ctxobj == obj) {
7402          return true;
7403        }
7404      }
7405    }
7406
7407    // Check the context extension (if any) if it can have references.
7408    if (context->has_extension() && !context->IsCatchContext()) {
7409      // With harmony scoping, a JSFunction may have a script context.
7410      // TODO(mvstanton): walk into the ScopeInfo.
7411      if (context->IsScriptContext()) {
7412        return false;
7413      }
7414
7415      return context->extension_object()->ReferencesObject(obj);
7416    }
7417  }
7418
7419  // No references to object.
7420  return false;
7421}
7422
7423
7424Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
7425                                          IntegrityLevel level,
7426                                          ShouldThrow should_throw) {
7427  DCHECK(level == SEALED || level == FROZEN);
7428
7429  if (receiver->IsJSObject()) {
7430    Handle<JSObject> object = Handle<JSObject>::cast(receiver);
7431    if (!object->HasSloppyArgumentsElements()) {  // Fast path.
7432      if (level == SEALED) {
7433        return JSObject::PreventExtensionsWithTransition<SEALED>(object,
7434                                                                 should_throw);
7435      } else {
7436        return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
7437                                                                 should_throw);
7438      }
7439    }
7440  }
7441
7442  Isolate* isolate = receiver->GetIsolate();
7443
7444  MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
7445               Nothing<bool>());
7446
7447  Handle<FixedArray> keys;
7448  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7449      isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
7450
7451  PropertyDescriptor no_conf;
7452  no_conf.set_configurable(false);
7453
7454  PropertyDescriptor no_conf_no_write;
7455  no_conf_no_write.set_configurable(false);
7456  no_conf_no_write.set_writable(false);
7457
7458  if (level == SEALED) {
7459    for (int i = 0; i < keys->length(); ++i) {
7460      Handle<Object> key(keys->get(i), isolate);
7461      MAYBE_RETURN(
7462          DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR),
7463          Nothing<bool>());
7464    }
7465    return Just(true);
7466  }
7467
7468  for (int i = 0; i < keys->length(); ++i) {
7469    Handle<Object> key(keys->get(i), isolate);
7470    PropertyDescriptor current_desc;
7471    Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
7472        isolate, receiver, key, &current_desc);
7473    MAYBE_RETURN(owned, Nothing<bool>());
7474    if (owned.FromJust()) {
7475      PropertyDescriptor desc =
7476          PropertyDescriptor::IsAccessorDescriptor(&current_desc)
7477              ? no_conf
7478              : no_conf_no_write;
7479      MAYBE_RETURN(
7480          DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR),
7481          Nothing<bool>());
7482    }
7483  }
7484  return Just(true);
7485}
7486
7487
7488Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object,
7489                                           IntegrityLevel level) {
7490  DCHECK(level == SEALED || level == FROZEN);
7491  Isolate* isolate = object->GetIsolate();
7492
7493  Maybe<bool> extensible = JSReceiver::IsExtensible(object);
7494  MAYBE_RETURN(extensible, Nothing<bool>());
7495  if (extensible.FromJust()) return Just(false);
7496
7497  Handle<FixedArray> keys;
7498  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7499      isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>());
7500
7501  for (int i = 0; i < keys->length(); ++i) {
7502    Handle<Object> key(keys->get(i), isolate);
7503    PropertyDescriptor current_desc;
7504    Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
7505        isolate, object, key, &current_desc);
7506    MAYBE_RETURN(owned, Nothing<bool>());
7507    if (owned.FromJust()) {
7508      if (current_desc.configurable()) return Just(false);
7509      if (level == FROZEN &&
7510          PropertyDescriptor::IsDataDescriptor(&current_desc) &&
7511          current_desc.writable()) {
7512        return Just(false);
7513      }
7514    }
7515  }
7516  return Just(true);
7517}
7518
7519
7520Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
7521                                          ShouldThrow should_throw) {
7522  if (object->IsJSProxy()) {
7523    return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
7524                                      should_throw);
7525  }
7526  DCHECK(object->IsJSObject());
7527  return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
7528                                     should_throw);
7529}
7530
7531
7532Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
7533                                       ShouldThrow should_throw) {
7534  Isolate* isolate = proxy->GetIsolate();
7535  STACK_CHECK(isolate, Nothing<bool>());
7536  Factory* factory = isolate->factory();
7537  Handle<String> trap_name = factory->preventExtensions_string();
7538
7539  if (proxy->IsRevoked()) {
7540    isolate->Throw(
7541        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
7542    return Nothing<bool>();
7543  }
7544  Handle<JSReceiver> target(proxy->target(), isolate);
7545  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
7546
7547  Handle<Object> trap;
7548  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7549      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
7550  if (trap->IsUndefined(isolate)) {
7551    return JSReceiver::PreventExtensions(target, should_throw);
7552  }
7553
7554  Handle<Object> trap_result;
7555  Handle<Object> args[] = {target};
7556  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7557      isolate, trap_result,
7558      Execution::Call(isolate, trap, handler, arraysize(args), args),
7559      Nothing<bool>());
7560  if (!trap_result->BooleanValue()) {
7561    RETURN_FAILURE(
7562        isolate, should_throw,
7563        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
7564  }
7565
7566  // Enforce the invariant.
7567  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
7568  MAYBE_RETURN(target_result, Nothing<bool>());
7569  if (target_result.FromJust()) {
7570    isolate->Throw(*factory->NewTypeError(
7571        MessageTemplate::kProxyPreventExtensionsExtensible));
7572    return Nothing<bool>();
7573  }
7574  return Just(true);
7575}
7576
7577
7578Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
7579                                        ShouldThrow should_throw) {
7580  Isolate* isolate = object->GetIsolate();
7581
7582  if (!object->HasSloppyArgumentsElements()) {
7583    return PreventExtensionsWithTransition<NONE>(object, should_throw);
7584  }
7585
7586  if (object->IsAccessCheckNeeded() &&
7587      !isolate->MayAccess(handle(isolate->context()), object)) {
7588    isolate->ReportFailedAccessCheck(object);
7589    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7590    RETURN_FAILURE(isolate, should_throw,
7591                   NewTypeError(MessageTemplate::kNoAccess));
7592  }
7593
7594  if (!object->map()->is_extensible()) return Just(true);
7595
7596  if (object->IsJSGlobalProxy()) {
7597    PrototypeIterator iter(isolate, object);
7598    if (iter.IsAtEnd()) return Just(true);
7599    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
7600    return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
7601                             should_throw);
7602  }
7603
7604  if (!object->HasFixedTypedArrayElements()) {
7605    // If there are fast elements we normalize.
7606    Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
7607    DCHECK(object->HasDictionaryElements() ||
7608           object->HasSlowArgumentsElements());
7609
7610    // Make sure that we never go back to fast case.
7611    object->RequireSlowElements(*dictionary);
7612  }
7613
7614  // Do a map transition, other objects with this map may still
7615  // be extensible.
7616  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
7617  Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
7618
7619  new_map->set_is_extensible(false);
7620  JSObject::MigrateToMap(object, new_map);
7621  DCHECK(!object->map()->is_extensible());
7622
7623  return Just(true);
7624}
7625
7626
7627Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
7628  if (object->IsJSProxy()) {
7629    return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
7630  }
7631  return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
7632}
7633
7634
7635Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
7636  Isolate* isolate = proxy->GetIsolate();
7637  STACK_CHECK(isolate, Nothing<bool>());
7638  Factory* factory = isolate->factory();
7639  Handle<String> trap_name = factory->isExtensible_string();
7640
7641  if (proxy->IsRevoked()) {
7642    isolate->Throw(
7643        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
7644    return Nothing<bool>();
7645  }
7646  Handle<JSReceiver> target(proxy->target(), isolate);
7647  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
7648
7649  Handle<Object> trap;
7650  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7651      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
7652  if (trap->IsUndefined(isolate)) {
7653    return JSReceiver::IsExtensible(target);
7654  }
7655
7656  Handle<Object> trap_result;
7657  Handle<Object> args[] = {target};
7658  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7659      isolate, trap_result,
7660      Execution::Call(isolate, trap, handler, arraysize(args), args),
7661      Nothing<bool>());
7662
7663  // Enforce the invariant.
7664  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
7665  MAYBE_RETURN(target_result, Nothing<bool>());
7666  if (target_result.FromJust() != trap_result->BooleanValue()) {
7667    isolate->Throw(
7668        *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
7669                               factory->ToBoolean(target_result.FromJust())));
7670    return Nothing<bool>();
7671  }
7672  return target_result;
7673}
7674
7675
7676bool JSObject::IsExtensible(Handle<JSObject> object) {
7677  Isolate* isolate = object->GetIsolate();
7678  if (object->IsAccessCheckNeeded() &&
7679      !isolate->MayAccess(handle(isolate->context()), object)) {
7680    return true;
7681  }
7682  if (object->IsJSGlobalProxy()) {
7683    PrototypeIterator iter(isolate, *object);
7684    if (iter.IsAtEnd()) return false;
7685    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
7686    return iter.GetCurrent<JSObject>()->map()->is_extensible();
7687  }
7688  return object->map()->is_extensible();
7689}
7690
7691
7692template <typename Dictionary>
7693static void ApplyAttributesToDictionary(Dictionary* dictionary,
7694                                        const PropertyAttributes attributes) {
7695  int capacity = dictionary->Capacity();
7696  Isolate* isolate = dictionary->GetIsolate();
7697  for (int i = 0; i < capacity; i++) {
7698    Object* k = dictionary->KeyAt(i);
7699    if (dictionary->IsKey(isolate, k) &&
7700        !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
7701      PropertyDetails details = dictionary->DetailsAt(i);
7702      int attrs = attributes;
7703      // READ_ONLY is an invalid attribute for JS setters/getters.
7704      if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
7705        Object* v = dictionary->ValueAt(i);
7706        if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
7707        if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
7708      }
7709      details = details.CopyAddAttributes(
7710          static_cast<PropertyAttributes>(attrs));
7711      dictionary->DetailsAtPut(i, details);
7712    }
7713  }
7714}
7715
7716
7717template <PropertyAttributes attrs>
7718Maybe<bool> JSObject::PreventExtensionsWithTransition(
7719    Handle<JSObject> object, ShouldThrow should_throw) {
7720  STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
7721
7722  // Sealing/freezing sloppy arguments should be handled elsewhere.
7723  DCHECK(!object->HasSloppyArgumentsElements());
7724
7725  Isolate* isolate = object->GetIsolate();
7726  if (object->IsAccessCheckNeeded() &&
7727      !isolate->MayAccess(handle(isolate->context()), object)) {
7728    isolate->ReportFailedAccessCheck(object);
7729    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7730    RETURN_FAILURE(isolate, should_throw,
7731                   NewTypeError(MessageTemplate::kNoAccess));
7732  }
7733
7734  if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
7735
7736  if (object->IsJSGlobalProxy()) {
7737    PrototypeIterator iter(isolate, object);
7738    if (iter.IsAtEnd()) return Just(true);
7739    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
7740    return PreventExtensionsWithTransition<attrs>(
7741        PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
7742  }
7743
7744  Handle<SeededNumberDictionary> new_element_dictionary;
7745  if (!object->HasFixedTypedArrayElements() &&
7746      !object->HasDictionaryElements() &&
7747      !object->HasSlowStringWrapperElements()) {
7748    int length =
7749        object->IsJSArray()
7750            ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
7751            : object->elements()->length();
7752    new_element_dictionary =
7753        length == 0 ? isolate->factory()->empty_slow_element_dictionary()
7754                    : object->GetElementsAccessor()->Normalize(object);
7755  }
7756
7757  Handle<Symbol> transition_marker;
7758  if (attrs == NONE) {
7759    transition_marker = isolate->factory()->nonextensible_symbol();
7760  } else if (attrs == SEALED) {
7761    transition_marker = isolate->factory()->sealed_symbol();
7762  } else {
7763    DCHECK(attrs == FROZEN);
7764    transition_marker = isolate->factory()->frozen_symbol();
7765  }
7766
7767  Handle<Map> old_map(object->map(), isolate);
7768  Map* transition =
7769      TransitionArray::SearchSpecial(*old_map, *transition_marker);
7770  if (transition != NULL) {
7771    Handle<Map> transition_map(transition, isolate);
7772    DCHECK(transition_map->has_dictionary_elements() ||
7773           transition_map->has_fixed_typed_array_elements() ||
7774           transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
7775    DCHECK(!transition_map->is_extensible());
7776    JSObject::MigrateToMap(object, transition_map);
7777  } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
7778    // Create a new descriptor array with the appropriate property attributes
7779    Handle<Map> new_map = Map::CopyForPreventExtensions(
7780        old_map, attrs, transition_marker, "CopyForPreventExtensions");
7781    JSObject::MigrateToMap(object, new_map);
7782  } else {
7783    DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
7784    // Slow path: need to normalize properties for safety
7785    NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
7786                        "SlowPreventExtensions");
7787
7788    // Create a new map, since other objects with this map may be extensible.
7789    // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
7790    Handle<Map> new_map =
7791        Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
7792    new_map->set_is_extensible(false);
7793    if (!new_element_dictionary.is_null()) {
7794      ElementsKind new_kind =
7795          IsStringWrapperElementsKind(old_map->elements_kind())
7796              ? SLOW_STRING_WRAPPER_ELEMENTS
7797              : DICTIONARY_ELEMENTS;
7798      new_map->set_elements_kind(new_kind);
7799    }
7800    JSObject::MigrateToMap(object, new_map);
7801
7802    if (attrs != NONE) {
7803      if (object->IsJSGlobalObject()) {
7804        ApplyAttributesToDictionary(object->global_dictionary(), attrs);
7805      } else {
7806        ApplyAttributesToDictionary(object->property_dictionary(), attrs);
7807      }
7808    }
7809  }
7810
7811  // Both seal and preventExtensions always go through without modifications to
7812  // typed array elements. Freeze works only if there are no actual elements.
7813  if (object->HasFixedTypedArrayElements()) {
7814    if (attrs == FROZEN &&
7815        JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) {
7816      isolate->Throw(*isolate->factory()->NewTypeError(
7817          MessageTemplate::kCannotFreezeArrayBufferView));
7818      return Nothing<bool>();
7819    }
7820    return Just(true);
7821  }
7822
7823  DCHECK(object->map()->has_dictionary_elements() ||
7824         object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
7825  if (!new_element_dictionary.is_null()) {
7826    object->set_elements(*new_element_dictionary);
7827  }
7828
7829  if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
7830    SeededNumberDictionary* dictionary = object->element_dictionary();
7831    // Make sure we never go back to the fast case
7832    object->RequireSlowElements(dictionary);
7833    if (attrs != NONE) {
7834      ApplyAttributesToDictionary(dictionary, attrs);
7835    }
7836  }
7837
7838  return Just(true);
7839}
7840
7841
7842Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
7843                                        Representation representation,
7844                                        FieldIndex index) {
7845  Isolate* isolate = object->GetIsolate();
7846  if (object->IsUnboxedDoubleField(index)) {
7847    double value = object->RawFastDoublePropertyAt(index);
7848    return isolate->factory()->NewHeapNumber(value);
7849  }
7850  Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
7851  return Object::WrapForRead(isolate, raw_value, representation);
7852}
7853
7854template <class ContextObject>
7855class JSObjectWalkVisitor {
7856 public:
7857  JSObjectWalkVisitor(ContextObject* site_context, bool copying,
7858                      JSObject::DeepCopyHints hints)
7859    : site_context_(site_context),
7860      copying_(copying),
7861      hints_(hints) {}
7862
7863  MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
7864
7865 protected:
7866  MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
7867      Handle<JSObject> object,
7868      Handle<JSObject> value) {
7869    Handle<AllocationSite> current_site = site_context()->EnterNewScope();
7870    MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
7871    site_context()->ExitScope(current_site, value);
7872    return copy_of_value;
7873  }
7874
7875  inline ContextObject* site_context() { return site_context_; }
7876  inline Isolate* isolate() { return site_context()->isolate(); }
7877
7878  inline bool copying() const { return copying_; }
7879
7880 private:
7881  ContextObject* site_context_;
7882  const bool copying_;
7883  const JSObject::DeepCopyHints hints_;
7884};
7885
7886template <class ContextObject>
7887MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
7888    Handle<JSObject> object) {
7889  Isolate* isolate = this->isolate();
7890  bool copying = this->copying();
7891  bool shallow = hints_ == JSObject::kObjectIsShallow;
7892
7893  if (!shallow) {
7894    StackLimitCheck check(isolate);
7895
7896    if (check.HasOverflowed()) {
7897      isolate->StackOverflow();
7898      return MaybeHandle<JSObject>();
7899    }
7900  }
7901
7902  if (object->map()->is_deprecated()) {
7903    JSObject::MigrateInstance(object);
7904  }
7905
7906  Handle<JSObject> copy;
7907  if (copying) {
7908    // JSFunction objects are not allowed to be in normal boilerplates at all.
7909    DCHECK(!object->IsJSFunction());
7910    Handle<AllocationSite> site_to_pass;
7911    if (site_context()->ShouldCreateMemento(object)) {
7912      site_to_pass = site_context()->current();
7913    }
7914    copy = isolate->factory()->CopyJSObjectWithAllocationSite(
7915        object, site_to_pass);
7916  } else {
7917    copy = object;
7918  }
7919
7920  DCHECK(copying || copy.is_identical_to(object));
7921
7922  ElementsKind kind = copy->GetElementsKind();
7923  if (copying && IsFastSmiOrObjectElementsKind(kind) &&
7924      FixedArray::cast(copy->elements())->map() ==
7925        isolate->heap()->fixed_cow_array_map()) {
7926    isolate->counters()->cow_arrays_created_runtime()->Increment();
7927  }
7928
7929  if (!shallow) {
7930    HandleScope scope(isolate);
7931
7932    // Deep copy own properties.
7933    if (copy->HasFastProperties()) {
7934      Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
7935      int limit = copy->map()->NumberOfOwnDescriptors();
7936      for (int i = 0; i < limit; i++) {
7937        PropertyDetails details = descriptors->GetDetails(i);
7938        if (details.type() != DATA) continue;
7939        FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
7940        if (object->IsUnboxedDoubleField(index)) {
7941          if (copying) {
7942            double value = object->RawFastDoublePropertyAt(index);
7943            copy->RawFastDoublePropertyAtPut(index, value);
7944          }
7945        } else {
7946          Handle<Object> value(object->RawFastPropertyAt(index), isolate);
7947          if (value->IsJSObject()) {
7948            ASSIGN_RETURN_ON_EXCEPTION(
7949                isolate, value,
7950                VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
7951                JSObject);
7952            if (copying) {
7953              copy->FastPropertyAtPut(index, *value);
7954            }
7955          } else {
7956            if (copying) {
7957              Representation representation = details.representation();
7958              value = Object::NewStorageFor(isolate, value, representation);
7959              copy->FastPropertyAtPut(index, *value);
7960            }
7961          }
7962        }
7963      }
7964    } else {
7965      // Only deep copy fields from the object literal expression.
7966      // In particular, don't try to copy the length attribute of
7967      // an array.
7968      PropertyFilter filter = static_cast<PropertyFilter>(
7969          ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
7970      KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter);
7971      accumulator.CollectOwnPropertyNames(copy, copy);
7972      Handle<FixedArray> names = accumulator.GetKeys();
7973      for (int i = 0; i < names->length(); i++) {
7974        DCHECK(names->get(i)->IsName());
7975        Handle<Name> name(Name::cast(names->get(i)));
7976        Handle<Object> value =
7977            JSObject::GetProperty(copy, name).ToHandleChecked();
7978        if (value->IsJSObject()) {
7979          Handle<JSObject> result;
7980          ASSIGN_RETURN_ON_EXCEPTION(
7981              isolate, result,
7982              VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
7983              JSObject);
7984          if (copying) {
7985            // Creating object copy for literals. No strict mode needed.
7986            JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
7987          }
7988        }
7989      }
7990    }
7991
7992    // Deep copy own elements.
7993    switch (kind) {
7994      case FAST_ELEMENTS:
7995      case FAST_HOLEY_ELEMENTS: {
7996        Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
7997        if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
7998#ifdef DEBUG
7999          for (int i = 0; i < elements->length(); i++) {
8000            DCHECK(!elements->get(i)->IsJSObject());
8001          }
8002#endif
8003        } else {
8004          for (int i = 0; i < elements->length(); i++) {
8005            Handle<Object> value(elements->get(i), isolate);
8006            if (value->IsJSObject()) {
8007              Handle<JSObject> result;
8008              ASSIGN_RETURN_ON_EXCEPTION(
8009                  isolate, result,
8010                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8011                  JSObject);
8012              if (copying) {
8013                elements->set(i, *result);
8014              }
8015            }
8016          }
8017        }
8018        break;
8019      }
8020      case DICTIONARY_ELEMENTS: {
8021        Handle<SeededNumberDictionary> element_dictionary(
8022            copy->element_dictionary());
8023        int capacity = element_dictionary->Capacity();
8024        for (int i = 0; i < capacity; i++) {
8025          Object* k = element_dictionary->KeyAt(i);
8026          if (element_dictionary->IsKey(isolate, k)) {
8027            Handle<Object> value(element_dictionary->ValueAt(i), isolate);
8028            if (value->IsJSObject()) {
8029              Handle<JSObject> result;
8030              ASSIGN_RETURN_ON_EXCEPTION(
8031                  isolate, result,
8032                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8033                  JSObject);
8034              if (copying) {
8035                element_dictionary->ValueAtPut(i, *result);
8036              }
8037            }
8038          }
8039        }
8040        break;
8041      }
8042      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8043      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8044        UNIMPLEMENTED();
8045        break;
8046      case FAST_STRING_WRAPPER_ELEMENTS:
8047      case SLOW_STRING_WRAPPER_ELEMENTS:
8048        UNREACHABLE();
8049        break;
8050
8051#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
8052      case TYPE##_ELEMENTS:                                                    \
8053
8054      TYPED_ARRAYS(TYPED_ARRAY_CASE)
8055#undef TYPED_ARRAY_CASE
8056      // Typed elements cannot be created using an object literal.
8057      UNREACHABLE();
8058      break;
8059
8060      case FAST_SMI_ELEMENTS:
8061      case FAST_HOLEY_SMI_ELEMENTS:
8062      case FAST_DOUBLE_ELEMENTS:
8063      case FAST_HOLEY_DOUBLE_ELEMENTS:
8064      case NO_ELEMENTS:
8065        // No contained objects, nothing to do.
8066        break;
8067    }
8068  }
8069
8070  return copy;
8071}
8072
8073
8074MaybeHandle<JSObject> JSObject::DeepWalk(
8075    Handle<JSObject> object,
8076    AllocationSiteCreationContext* site_context) {
8077  JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
8078                                                       kNoHints);
8079  MaybeHandle<JSObject> result = v.StructureWalk(object);
8080  Handle<JSObject> for_assert;
8081  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
8082  return result;
8083}
8084
8085
8086MaybeHandle<JSObject> JSObject::DeepCopy(
8087    Handle<JSObject> object,
8088    AllocationSiteUsageContext* site_context,
8089    DeepCopyHints hints) {
8090  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
8091  MaybeHandle<JSObject> copy = v.StructureWalk(object);
8092  Handle<JSObject> for_assert;
8093  DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
8094  return copy;
8095}
8096
8097// static
8098MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
8099                                            ToPrimitiveHint hint) {
8100  Isolate* const isolate = receiver->GetIsolate();
8101  Handle<Object> exotic_to_prim;
8102  ASSIGN_RETURN_ON_EXCEPTION(
8103      isolate, exotic_to_prim,
8104      GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
8105  if (!exotic_to_prim->IsUndefined(isolate)) {
8106    Handle<Object> hint_string;
8107    switch (hint) {
8108      case ToPrimitiveHint::kDefault:
8109        hint_string = isolate->factory()->default_string();
8110        break;
8111      case ToPrimitiveHint::kNumber:
8112        hint_string = isolate->factory()->number_string();
8113        break;
8114      case ToPrimitiveHint::kString:
8115        hint_string = isolate->factory()->string_string();
8116        break;
8117    }
8118    Handle<Object> result;
8119    ASSIGN_RETURN_ON_EXCEPTION(
8120        isolate, result,
8121        Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
8122        Object);
8123    if (result->IsPrimitive()) return result;
8124    THROW_NEW_ERROR(isolate,
8125                    NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8126                    Object);
8127  }
8128  return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
8129                                           ? OrdinaryToPrimitiveHint::kString
8130                                           : OrdinaryToPrimitiveHint::kNumber);
8131}
8132
8133
8134// static
8135MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
8136    Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
8137  Isolate* const isolate = receiver->GetIsolate();
8138  Handle<String> method_names[2];
8139  switch (hint) {
8140    case OrdinaryToPrimitiveHint::kNumber:
8141      method_names[0] = isolate->factory()->valueOf_string();
8142      method_names[1] = isolate->factory()->toString_string();
8143      break;
8144    case OrdinaryToPrimitiveHint::kString:
8145      method_names[0] = isolate->factory()->toString_string();
8146      method_names[1] = isolate->factory()->valueOf_string();
8147      break;
8148  }
8149  for (Handle<String> name : method_names) {
8150    Handle<Object> method;
8151    ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
8152                               JSReceiver::GetProperty(receiver, name), Object);
8153    if (method->IsCallable()) {
8154      Handle<Object> result;
8155      ASSIGN_RETURN_ON_EXCEPTION(
8156          isolate, result, Execution::Call(isolate, method, receiver, 0, NULL),
8157          Object);
8158      if (result->IsPrimitive()) return result;
8159    }
8160  }
8161  THROW_NEW_ERROR(isolate,
8162                  NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8163                  Object);
8164}
8165
8166
8167// TODO(cbruni/jkummerow): Consider moving this into elements.cc.
8168bool JSObject::HasEnumerableElements() {
8169  // TODO(cbruni): cleanup
8170  JSObject* object = this;
8171  switch (object->GetElementsKind()) {
8172    case FAST_SMI_ELEMENTS:
8173    case FAST_ELEMENTS:
8174    case FAST_DOUBLE_ELEMENTS: {
8175      int length = object->IsJSArray()
8176                       ? Smi::cast(JSArray::cast(object)->length())->value()
8177                       : object->elements()->length();
8178      return length > 0;
8179    }
8180    case FAST_HOLEY_SMI_ELEMENTS:
8181    case FAST_HOLEY_ELEMENTS: {
8182      FixedArray* elements = FixedArray::cast(object->elements());
8183      int length = object->IsJSArray()
8184                       ? Smi::cast(JSArray::cast(object)->length())->value()
8185                       : elements->length();
8186      for (int i = 0; i < length; i++) {
8187        if (!elements->is_the_hole(i)) return true;
8188      }
8189      return false;
8190    }
8191    case FAST_HOLEY_DOUBLE_ELEMENTS: {
8192      int length = object->IsJSArray()
8193                       ? Smi::cast(JSArray::cast(object)->length())->value()
8194                       : object->elements()->length();
8195      // Zero-length arrays would use the empty FixedArray...
8196      if (length == 0) return false;
8197      // ...so only cast to FixedDoubleArray otherwise.
8198      FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements());
8199      for (int i = 0; i < length; i++) {
8200        if (!elements->is_the_hole(i)) return true;
8201      }
8202      return false;
8203    }
8204#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
8205    case TYPE##_ELEMENTS:
8206
8207      TYPED_ARRAYS(TYPED_ARRAY_CASE)
8208#undef TYPED_ARRAY_CASE
8209      {
8210        int length = object->elements()->length();
8211        return length > 0;
8212      }
8213    case DICTIONARY_ELEMENTS: {
8214      SeededNumberDictionary* elements =
8215          SeededNumberDictionary::cast(object->elements());
8216      return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0;
8217    }
8218    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8219    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8220      // We're approximating non-empty arguments objects here.
8221      return true;
8222    case FAST_STRING_WRAPPER_ELEMENTS:
8223    case SLOW_STRING_WRAPPER_ELEMENTS:
8224      if (String::cast(JSValue::cast(object)->value())->length() > 0) {
8225        return true;
8226      }
8227      return object->elements()->length() > 0;
8228    case NO_ELEMENTS:
8229      return false;
8230  }
8231  UNREACHABLE();
8232  return true;
8233}
8234
8235
8236int Map::NumberOfDescribedProperties(DescriptorFlag which,
8237                                     PropertyFilter filter) {
8238  int result = 0;
8239  DescriptorArray* descs = instance_descriptors();
8240  int limit = which == ALL_DESCRIPTORS
8241      ? descs->number_of_descriptors()
8242      : NumberOfOwnDescriptors();
8243  for (int i = 0; i < limit; i++) {
8244    if ((descs->GetDetails(i).attributes() & filter) == 0 &&
8245        !descs->GetKey(i)->FilterKey(filter)) {
8246      result++;
8247    }
8248  }
8249  return result;
8250}
8251
8252
8253int Map::NextFreePropertyIndex() {
8254  int free_index = 0;
8255  int number_of_own_descriptors = NumberOfOwnDescriptors();
8256  DescriptorArray* descs = instance_descriptors();
8257  for (int i = 0; i < number_of_own_descriptors; i++) {
8258    PropertyDetails details = descs->GetDetails(i);
8259    if (details.location() == kField) {
8260      int candidate = details.field_index() + details.field_width_in_words();
8261      if (candidate > free_index) free_index = candidate;
8262    }
8263  }
8264  return free_index;
8265}
8266
8267
8268bool Map::OnlyHasSimpleProperties() {
8269  // Wrapped string elements aren't explicitly stored in the elements backing
8270  // store, but are loaded indirectly from the underlying string.
8271  return !IsStringWrapperElementsKind(elements_kind()) &&
8272         instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
8273         !has_hidden_prototype() && !is_dictionary_map();
8274}
8275
8276MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
8277    Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
8278    Handle<FixedArray>* result) {
8279  Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
8280
8281  if (!map->IsJSObjectMap()) return Just(false);
8282  if (!map->OnlyHasSimpleProperties()) return Just(false);
8283
8284  Handle<JSObject> object(JSObject::cast(*receiver));
8285
8286  Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
8287  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
8288  int number_of_own_elements =
8289      object->GetElementsAccessor()->GetCapacity(*object, object->elements());
8290  Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
8291      number_of_own_descriptors + number_of_own_elements);
8292  int count = 0;
8293
8294  if (object->elements() != isolate->heap()->empty_fixed_array()) {
8295    MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
8296                     isolate, object, values_or_entries, get_entries, &count,
8297                     ENUMERABLE_STRINGS),
8298                 Nothing<bool>());
8299  }
8300
8301  bool stable = object->map() == *map;
8302
8303  for (int index = 0; index < number_of_own_descriptors; index++) {
8304    Handle<Name> next_key(descriptors->GetKey(index), isolate);
8305    if (!next_key->IsString()) continue;
8306    Handle<Object> prop_value;
8307
8308    // Directly decode from the descriptor array if |from| did not change shape.
8309    if (stable) {
8310      PropertyDetails details = descriptors->GetDetails(index);
8311      if (!details.IsEnumerable()) continue;
8312      if (details.kind() == kData) {
8313        if (details.location() == kDescriptor) {
8314          prop_value = handle(descriptors->GetValue(index), isolate);
8315        } else {
8316          Representation representation = details.representation();
8317          FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
8318          prop_value =
8319              JSObject::FastPropertyAt(object, representation, field_index);
8320        }
8321      } else {
8322        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8323            isolate, prop_value, JSReceiver::GetProperty(object, next_key),
8324            Nothing<bool>());
8325        stable = object->map() == *map;
8326      }
8327    } else {
8328      // If the map did change, do a slower lookup. We are still guaranteed that
8329      // the object has a simple shape, and that the key is a name.
8330      LookupIterator it(object, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR);
8331      if (!it.IsFound()) continue;
8332      DCHECK(it.state() == LookupIterator::DATA ||
8333             it.state() == LookupIterator::ACCESSOR);
8334      if (!it.IsEnumerable()) continue;
8335      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8336          isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
8337    }
8338
8339    if (get_entries) {
8340      prop_value = MakeEntryPair(isolate, next_key, prop_value);
8341    }
8342
8343    values_or_entries->set(count, *prop_value);
8344    count++;
8345  }
8346
8347  if (count < values_or_entries->length()) values_or_entries->Shrink(count);
8348  *result = values_or_entries;
8349  return Just(true);
8350}
8351
8352MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
8353                                              Handle<JSReceiver> object,
8354                                              PropertyFilter filter,
8355                                              bool get_entries) {
8356  Handle<FixedArray> values_or_entries;
8357  if (filter == ENUMERABLE_STRINGS) {
8358    Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
8359        isolate, object, get_entries, &values_or_entries);
8360    if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
8361    if (fast_values_or_entries.FromJust()) return values_or_entries;
8362  }
8363
8364  PropertyFilter key_filter =
8365      static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
8366
8367  Handle<FixedArray> keys;
8368  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8369      isolate, keys,
8370      KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
8371                              GetKeysConversion::kConvertToString),
8372      MaybeHandle<FixedArray>());
8373
8374  values_or_entries = isolate->factory()->NewFixedArray(keys->length());
8375  int length = 0;
8376
8377  for (int i = 0; i < keys->length(); ++i) {
8378    Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
8379
8380    if (filter & ONLY_ENUMERABLE) {
8381      PropertyDescriptor descriptor;
8382      Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
8383          isolate, object, key, &descriptor);
8384      MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
8385      if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
8386    }
8387
8388    Handle<Object> value;
8389    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8390        isolate, value, JSReceiver::GetPropertyOrElement(object, key),
8391        MaybeHandle<FixedArray>());
8392
8393    if (get_entries) {
8394      Handle<FixedArray> entry_storage =
8395          isolate->factory()->NewUninitializedFixedArray(2);
8396      entry_storage->set(0, *key);
8397      entry_storage->set(1, *value);
8398      value = isolate->factory()->NewJSArrayWithElements(entry_storage,
8399                                                         FAST_ELEMENTS, 2);
8400    }
8401
8402    values_or_entries->set(length, *value);
8403    length++;
8404  }
8405  if (length < values_or_entries->length()) values_or_entries->Shrink(length);
8406  return values_or_entries;
8407}
8408
8409MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
8410                                                 PropertyFilter filter) {
8411  return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, false);
8412}
8413
8414MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
8415                                                  PropertyFilter filter) {
8416  return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, true);
8417}
8418
8419bool Map::DictionaryElementsInPrototypeChainOnly() {
8420  if (IsDictionaryElementsKind(elements_kind())) {
8421    return false;
8422  }
8423
8424  for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
8425    // Be conservative, don't walk into proxies.
8426    if (iter.GetCurrent()->IsJSProxy()) return true;
8427    // String wrappers have non-configurable, non-writable elements.
8428    if (iter.GetCurrent()->IsStringWrapper()) return true;
8429    JSObject* current = iter.GetCurrent<JSObject>();
8430
8431    if (current->HasDictionaryElements() &&
8432        current->element_dictionary()->requires_slow_elements()) {
8433      return true;
8434    }
8435
8436    if (current->HasSlowArgumentsElements()) {
8437      FixedArray* parameter_map = FixedArray::cast(current->elements());
8438      Object* arguments = parameter_map->get(1);
8439      if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
8440        return true;
8441      }
8442    }
8443  }
8444
8445  return false;
8446}
8447
8448
8449MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
8450                                             Handle<Name> name,
8451                                             Handle<Object> getter,
8452                                             Handle<Object> setter,
8453                                             PropertyAttributes attributes) {
8454  Isolate* isolate = object->GetIsolate();
8455
8456  LookupIterator it = LookupIterator::PropertyOrElement(
8457      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
8458  return DefineAccessor(&it, getter, setter, attributes);
8459}
8460
8461
8462MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
8463                                             Handle<Object> getter,
8464                                             Handle<Object> setter,
8465                                             PropertyAttributes attributes) {
8466  Isolate* isolate = it->isolate();
8467
8468  it->UpdateProtector();
8469
8470  if (it->state() == LookupIterator::ACCESS_CHECK) {
8471    if (!it->HasAccess()) {
8472      isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
8473      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
8474      return isolate->factory()->undefined_value();
8475    }
8476    it->Next();
8477  }
8478
8479  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
8480  // Ignore accessors on typed arrays.
8481  if (it->IsElement() && object->HasFixedTypedArrayElements()) {
8482    return it->factory()->undefined_value();
8483  }
8484
8485  DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
8486         getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
8487  DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
8488         setter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
8489  it->TransitionToAccessorProperty(getter, setter, attributes);
8490
8491  return isolate->factory()->undefined_value();
8492}
8493
8494
8495MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
8496                                          Handle<AccessorInfo> info) {
8497  Isolate* isolate = object->GetIsolate();
8498  Handle<Name> name(Name::cast(info->name()), isolate);
8499
8500  LookupIterator it = LookupIterator::PropertyOrElement(
8501      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
8502
8503  // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
8504  // the FailedAccessCheckCallbackFunction doesn't throw an exception.
8505  //
8506  // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
8507  // remove reliance on default return values.
8508  if (it.state() == LookupIterator::ACCESS_CHECK) {
8509    if (!it.HasAccess()) {
8510      isolate->ReportFailedAccessCheck(object);
8511      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
8512      return it.factory()->undefined_value();
8513    }
8514    it.Next();
8515  }
8516
8517  // Ignore accessors on typed arrays.
8518  if (it.IsElement() && object->HasFixedTypedArrayElements()) {
8519    return it.factory()->undefined_value();
8520  }
8521
8522  CHECK(GetPropertyAttributes(&it).IsJust());
8523
8524  // ES5 forbids turning a property into an accessor if it's not
8525  // configurable. See 8.6.1 (Table 5).
8526  if (it.IsFound() && !it.IsConfigurable()) {
8527    return it.factory()->undefined_value();
8528  }
8529
8530  it.TransitionToAccessorPair(info, info->property_attributes());
8531
8532  return object;
8533}
8534
8535Object* JSObject::SlowReverseLookup(Object* value) {
8536  if (HasFastProperties()) {
8537    int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
8538    DescriptorArray* descs = map()->instance_descriptors();
8539    bool value_is_number = value->IsNumber();
8540    for (int i = 0; i < number_of_own_descriptors; i++) {
8541      if (descs->GetType(i) == DATA) {
8542        FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
8543        if (IsUnboxedDoubleField(field_index)) {
8544          if (value_is_number) {
8545            double property = RawFastDoublePropertyAt(field_index);
8546            if (property == value->Number()) {
8547              return descs->GetKey(i);
8548            }
8549          }
8550        } else {
8551          Object* property = RawFastPropertyAt(field_index);
8552          if (field_index.is_double()) {
8553            DCHECK(property->IsMutableHeapNumber());
8554            if (value_is_number && property->Number() == value->Number()) {
8555              return descs->GetKey(i);
8556            }
8557          } else if (property == value) {
8558            return descs->GetKey(i);
8559          }
8560        }
8561      } else if (descs->GetType(i) == DATA_CONSTANT) {
8562        if (descs->GetConstant(i) == value) {
8563          return descs->GetKey(i);
8564        }
8565      }
8566    }
8567    return GetHeap()->undefined_value();
8568  } else if (IsJSGlobalObject()) {
8569    return global_dictionary()->SlowReverseLookup(value);
8570  } else {
8571    return property_dictionary()->SlowReverseLookup(value);
8572  }
8573}
8574
8575
8576Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
8577  Isolate* isolate = map->GetIsolate();
8578  Handle<Map> result =
8579      isolate->factory()->NewMap(map->instance_type(), instance_size);
8580  Handle<Object> prototype(map->prototype(), isolate);
8581  Map::SetPrototype(result, prototype);
8582  result->set_constructor_or_backpointer(map->GetConstructor());
8583  result->set_bit_field(map->bit_field());
8584  result->set_bit_field2(map->bit_field2());
8585  int new_bit_field3 = map->bit_field3();
8586  new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
8587  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
8588  new_bit_field3 = EnumLengthBits::update(new_bit_field3,
8589                                          kInvalidEnumCacheSentinel);
8590  new_bit_field3 = Deprecated::update(new_bit_field3, false);
8591  if (!map->is_dictionary_map()) {
8592    new_bit_field3 = IsUnstable::update(new_bit_field3, false);
8593  }
8594  result->set_bit_field3(new_bit_field3);
8595  return result;
8596}
8597
8598
8599Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
8600                           const char* reason) {
8601  DCHECK(!fast_map->is_dictionary_map());
8602
8603  Isolate* isolate = fast_map->GetIsolate();
8604  Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
8605                             isolate);
8606  bool use_cache =
8607      !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
8608  Handle<NormalizedMapCache> cache;
8609  if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
8610
8611  Handle<Map> new_map;
8612  if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
8613#ifdef VERIFY_HEAP
8614    if (FLAG_verify_heap) new_map->DictionaryMapVerify();
8615#endif
8616#ifdef ENABLE_SLOW_DCHECKS
8617    if (FLAG_enable_slow_asserts) {
8618      // The cached map should match newly created normalized map bit-by-bit,
8619      // except for the code cache, which can contain some ics which can be
8620      // applied to the shared map, dependent code and weak cell cache.
8621      Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
8622
8623      if (new_map->is_prototype_map()) {
8624        // For prototype maps, the PrototypeInfo is not copied.
8625        DCHECK(memcmp(fresh->address(), new_map->address(),
8626                      kTransitionsOrPrototypeInfoOffset) == 0);
8627        DCHECK(fresh->raw_transitions() == Smi::FromInt(0));
8628        STATIC_ASSERT(kDescriptorsOffset ==
8629                      kTransitionsOrPrototypeInfoOffset + kPointerSize);
8630        DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
8631                      HeapObject::RawField(*new_map, kDescriptorsOffset),
8632                      kCodeCacheOffset - kDescriptorsOffset) == 0);
8633      } else {
8634        DCHECK(memcmp(fresh->address(), new_map->address(),
8635                      Map::kCodeCacheOffset) == 0);
8636      }
8637      STATIC_ASSERT(Map::kDependentCodeOffset ==
8638                    Map::kCodeCacheOffset + kPointerSize);
8639      STATIC_ASSERT(Map::kWeakCellCacheOffset ==
8640                    Map::kDependentCodeOffset + kPointerSize);
8641      int offset = Map::kWeakCellCacheOffset + kPointerSize;
8642      DCHECK(memcmp(fresh->address() + offset,
8643                    new_map->address() + offset,
8644                    Map::kSize - offset) == 0);
8645    }
8646#endif
8647  } else {
8648    new_map = Map::CopyNormalized(fast_map, mode);
8649    if (use_cache) {
8650      cache->Set(fast_map, new_map);
8651      isolate->counters()->maps_normalized()->Increment();
8652    }
8653#if TRACE_MAPS
8654    if (FLAG_trace_maps) {
8655      PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
8656             reinterpret_cast<void*>(*fast_map),
8657             reinterpret_cast<void*>(*new_map), reason);
8658    }
8659#endif
8660  }
8661  fast_map->NotifyLeafMapLayoutChange();
8662  return new_map;
8663}
8664
8665
8666Handle<Map> Map::CopyNormalized(Handle<Map> map,
8667                                PropertyNormalizationMode mode) {
8668  int new_instance_size = map->instance_size();
8669  if (mode == CLEAR_INOBJECT_PROPERTIES) {
8670    new_instance_size -= map->GetInObjectProperties() * kPointerSize;
8671  }
8672
8673  Handle<Map> result = RawCopy(map, new_instance_size);
8674
8675  if (mode != CLEAR_INOBJECT_PROPERTIES) {
8676    result->SetInObjectProperties(map->GetInObjectProperties());
8677  }
8678
8679  result->set_dictionary_map(true);
8680  result->set_migration_target(false);
8681  result->set_construction_counter(kNoSlackTracking);
8682
8683#ifdef VERIFY_HEAP
8684  if (FLAG_verify_heap) result->DictionaryMapVerify();
8685#endif
8686
8687  return result;
8688}
8689
8690
8691Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
8692                                int in_object_properties,
8693                                int unused_property_fields) {
8694#ifdef DEBUG
8695  Isolate* isolate = map->GetIsolate();
8696  // Strict function maps have Function as a constructor but the
8697  // Function's initial map is a sloppy function map. Same holds for
8698  // GeneratorFunction and its initial map.
8699  Object* constructor = map->GetConstructor();
8700  DCHECK(constructor->IsJSFunction());
8701  DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
8702         *map == *isolate->strict_function_map() ||
8703         *map == *isolate->strict_generator_function_map());
8704#endif
8705  // Initial maps must always own their descriptors and it's descriptor array
8706  // does not contain descriptors that do not belong to the map.
8707  DCHECK(map->owns_descriptors());
8708  DCHECK_EQ(map->NumberOfOwnDescriptors(),
8709            map->instance_descriptors()->number_of_descriptors());
8710
8711  Handle<Map> result = RawCopy(map, instance_size);
8712
8713  // Please note instance_type and instance_size are set when allocated.
8714  result->SetInObjectProperties(in_object_properties);
8715  result->set_unused_property_fields(unused_property_fields);
8716
8717  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
8718  if (number_of_own_descriptors > 0) {
8719    // The copy will use the same descriptors array.
8720    result->UpdateDescriptors(map->instance_descriptors(),
8721                              map->GetLayoutDescriptor());
8722    result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
8723
8724    DCHECK_EQ(result->NumberOfFields(),
8725              in_object_properties - unused_property_fields);
8726  }
8727
8728  return result;
8729}
8730
8731
8732Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
8733  Handle<Map> result = RawCopy(map, map->instance_size());
8734
8735  // Please note instance_type and instance_size are set when allocated.
8736  if (map->IsJSObjectMap()) {
8737    result->SetInObjectProperties(map->GetInObjectProperties());
8738    result->set_unused_property_fields(map->unused_property_fields());
8739  }
8740  result->ClearCodeCache(map->GetHeap());
8741  map->NotifyLeafMapLayoutChange();
8742  return result;
8743}
8744
8745
8746Handle<Map> Map::ShareDescriptor(Handle<Map> map,
8747                                 Handle<DescriptorArray> descriptors,
8748                                 Descriptor* descriptor) {
8749  // Sanity check. This path is only to be taken if the map owns its descriptor
8750  // array, implying that its NumberOfOwnDescriptors equals the number of
8751  // descriptors in the descriptor array.
8752  DCHECK_EQ(map->NumberOfOwnDescriptors(),
8753            map->instance_descriptors()->number_of_descriptors());
8754
8755  Handle<Map> result = CopyDropDescriptors(map);
8756  Handle<Name> name = descriptor->GetKey();
8757
8758  // Ensure there's space for the new descriptor in the shared descriptor array.
8759  if (descriptors->NumberOfSlackDescriptors() == 0) {
8760    int old_size = descriptors->number_of_descriptors();
8761    if (old_size == 0) {
8762      descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
8763    } else {
8764      int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
8765      EnsureDescriptorSlack(map, slack);
8766      descriptors = handle(map->instance_descriptors());
8767    }
8768  }
8769
8770  Handle<LayoutDescriptor> layout_descriptor =
8771      FLAG_unbox_double_fields
8772          ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
8773          : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
8774
8775  {
8776    DisallowHeapAllocation no_gc;
8777    descriptors->Append(descriptor);
8778    result->InitializeDescriptors(*descriptors, *layout_descriptor);
8779  }
8780
8781  DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
8782  ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
8783
8784  return result;
8785}
8786
8787
8788#if TRACE_MAPS
8789
8790// static
8791void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
8792  if (FLAG_trace_maps) {
8793    PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
8794           reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
8795    name->NameShortPrint();
8796    PrintF(" ]\n");
8797  }
8798}
8799
8800
8801// static
8802void Map::TraceAllTransitions(Map* map) {
8803  Object* transitions = map->raw_transitions();
8804  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
8805  for (int i = -0; i < num_transitions; ++i) {
8806    Map* target = TransitionArray::GetTarget(transitions, i);
8807    Name* key = TransitionArray::GetKey(transitions, i);
8808    Map::TraceTransition("Transition", map, target, key);
8809    Map::TraceAllTransitions(target);
8810  }
8811}
8812
8813#endif  // TRACE_MAPS
8814
8815
8816void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
8817                            Handle<Name> name, SimpleTransitionFlag flag) {
8818  if (!parent->GetBackPointer()->IsUndefined(parent->GetIsolate())) {
8819    parent->set_owns_descriptors(false);
8820  } else {
8821    // |parent| is initial map and it must keep the ownership, there must be no
8822    // descriptors in the descriptors array that do not belong to the map.
8823    DCHECK(parent->owns_descriptors());
8824    DCHECK_EQ(parent->NumberOfOwnDescriptors(),
8825              parent->instance_descriptors()->number_of_descriptors());
8826  }
8827  if (parent->is_prototype_map()) {
8828    DCHECK(child->is_prototype_map());
8829#if TRACE_MAPS
8830    Map::TraceTransition("NoTransition", *parent, *child, *name);
8831#endif
8832  } else {
8833    TransitionArray::Insert(parent, name, child, flag);
8834#if TRACE_MAPS
8835    Map::TraceTransition("Transition", *parent, *child, *name);
8836#endif
8837  }
8838}
8839
8840
8841Handle<Map> Map::CopyReplaceDescriptors(
8842    Handle<Map> map, Handle<DescriptorArray> descriptors,
8843    Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
8844    MaybeHandle<Name> maybe_name, const char* reason,
8845    SimpleTransitionFlag simple_flag) {
8846  DCHECK(descriptors->IsSortedNoDuplicates());
8847
8848  Handle<Map> result = CopyDropDescriptors(map);
8849
8850  if (!map->is_prototype_map()) {
8851    if (flag == INSERT_TRANSITION &&
8852        TransitionArray::CanHaveMoreTransitions(map)) {
8853      result->InitializeDescriptors(*descriptors, *layout_descriptor);
8854
8855      Handle<Name> name;
8856      CHECK(maybe_name.ToHandle(&name));
8857      ConnectTransition(map, result, name, simple_flag);
8858    } else {
8859      int length = descriptors->number_of_descriptors();
8860      for (int i = 0; i < length; i++) {
8861        descriptors->SetRepresentation(i, Representation::Tagged());
8862        if (descriptors->GetDetails(i).type() == DATA) {
8863          descriptors->SetValue(i, FieldType::Any());
8864        }
8865      }
8866      result->InitializeDescriptors(*descriptors,
8867                                    LayoutDescriptor::FastPointerLayout());
8868    }
8869  } else {
8870    result->InitializeDescriptors(*descriptors, *layout_descriptor);
8871  }
8872#if TRACE_MAPS
8873  if (FLAG_trace_maps &&
8874      // Mirror conditions above that did not call ConnectTransition().
8875      (map->is_prototype_map() ||
8876       !(flag == INSERT_TRANSITION &&
8877         TransitionArray::CanHaveMoreTransitions(map)))) {
8878    PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
8879           reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
8880           reason);
8881  }
8882#endif
8883
8884  return result;
8885}
8886
8887
8888// Creates transition tree starting from |split_map| and adding all descriptors
8889// starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
8890// The way how it is done is tricky because of GC and special descriptors
8891// marking logic.
8892Handle<Map> Map::AddMissingTransitions(
8893    Handle<Map> split_map, Handle<DescriptorArray> descriptors,
8894    Handle<LayoutDescriptor> full_layout_descriptor) {
8895  DCHECK(descriptors->IsSortedNoDuplicates());
8896  int split_nof = split_map->NumberOfOwnDescriptors();
8897  int nof_descriptors = descriptors->number_of_descriptors();
8898  DCHECK_LT(split_nof, nof_descriptors);
8899
8900  // Start with creating last map which will own full descriptors array.
8901  // This is necessary to guarantee that GC will mark the whole descriptor
8902  // array if any of the allocations happening below fail.
8903  // Number of unused properties is temporarily incorrect and the layout
8904  // descriptor could unnecessarily be in slow mode but we will fix after
8905  // all the other intermediate maps are created.
8906  Handle<Map> last_map = CopyDropDescriptors(split_map);
8907  last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
8908  last_map->set_unused_property_fields(0);
8909
8910  // During creation of intermediate maps we violate descriptors sharing
8911  // invariant since the last map is not yet connected to the transition tree
8912  // we create here. But it is safe because GC never trims map's descriptors
8913  // if there are no dead transitions from that map and this is exactly the
8914  // case for all the intermediate maps we create here.
8915  Handle<Map> map = split_map;
8916  for (int i = split_nof; i < nof_descriptors - 1; ++i) {
8917    Handle<Map> new_map = CopyDropDescriptors(map);
8918    InstallDescriptors(map, new_map, i, descriptors, full_layout_descriptor);
8919    map = new_map;
8920  }
8921  map->NotifyLeafMapLayoutChange();
8922  InstallDescriptors(map, last_map, nof_descriptors - 1, descriptors,
8923                     full_layout_descriptor);
8924  return last_map;
8925}
8926
8927
8928// Since this method is used to rewrite an existing transition tree, it can
8929// always insert transitions without checking.
8930void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
8931                             int new_descriptor,
8932                             Handle<DescriptorArray> descriptors,
8933                             Handle<LayoutDescriptor> full_layout_descriptor) {
8934  DCHECK(descriptors->IsSortedNoDuplicates());
8935
8936  child->set_instance_descriptors(*descriptors);
8937  child->SetNumberOfOwnDescriptors(new_descriptor + 1);
8938
8939  int unused_property_fields = parent->unused_property_fields();
8940  PropertyDetails details = descriptors->GetDetails(new_descriptor);
8941  if (details.location() == kField) {
8942    unused_property_fields = parent->unused_property_fields() - 1;
8943    if (unused_property_fields < 0) {
8944      unused_property_fields += JSObject::kFieldsAdded;
8945    }
8946  }
8947  child->set_unused_property_fields(unused_property_fields);
8948
8949  if (FLAG_unbox_double_fields) {
8950    Handle<LayoutDescriptor> layout_descriptor =
8951        LayoutDescriptor::AppendIfFastOrUseFull(parent, details,
8952                                                full_layout_descriptor);
8953    child->set_layout_descriptor(*layout_descriptor);
8954#ifdef VERIFY_HEAP
8955    // TODO(ishell): remove these checks from VERIFY_HEAP mode.
8956    if (FLAG_verify_heap) {
8957      CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
8958    }
8959#else
8960    SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
8961#endif
8962    child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child));
8963  }
8964
8965  Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
8966  ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
8967}
8968
8969
8970Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
8971                                    TransitionFlag flag) {
8972  Map* maybe_elements_transition_map = NULL;
8973  if (flag == INSERT_TRANSITION) {
8974    // Ensure we are requested to add elements kind transition "near the root".
8975    DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
8976              map->NumberOfOwnDescriptors());
8977
8978    maybe_elements_transition_map = map->ElementsTransitionMap();
8979    DCHECK(maybe_elements_transition_map == NULL ||
8980           (maybe_elements_transition_map->elements_kind() ==
8981                DICTIONARY_ELEMENTS &&
8982            kind == DICTIONARY_ELEMENTS));
8983    DCHECK(!IsFastElementsKind(kind) ||
8984           IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
8985    DCHECK(kind != map->elements_kind());
8986  }
8987
8988  bool insert_transition = flag == INSERT_TRANSITION &&
8989                           TransitionArray::CanHaveMoreTransitions(map) &&
8990                           maybe_elements_transition_map == NULL;
8991
8992  if (insert_transition) {
8993    Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
8994    new_map->set_elements_kind(kind);
8995
8996    Isolate* isolate = map->GetIsolate();
8997    Handle<Name> name = isolate->factory()->elements_transition_symbol();
8998    ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
8999    return new_map;
9000  }
9001
9002  // Create a new free-floating map only if we are not allowed to store it.
9003  Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
9004  new_map->set_elements_kind(kind);
9005  return new_map;
9006}
9007
9008
9009Handle<Map> Map::AsLanguageMode(Handle<Map> initial_map,
9010                                LanguageMode language_mode, FunctionKind kind) {
9011  DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
9012  // Initial map for sloppy mode function is stored in the function
9013  // constructor. Initial maps for strict mode are cached as special transitions
9014  // using |strict_function_transition_symbol| as a key.
9015  if (language_mode == SLOPPY) return initial_map;
9016  Isolate* isolate = initial_map->GetIsolate();
9017  Factory* factory = isolate->factory();
9018  Handle<Symbol> transition_symbol;
9019
9020  int map_index = Context::FunctionMapIndex(language_mode, kind);
9021  Handle<Map> function_map(
9022      Map::cast(isolate->native_context()->get(map_index)));
9023
9024  STATIC_ASSERT(LANGUAGE_END == 3);
9025  switch (language_mode) {
9026    case STRICT:
9027      transition_symbol = factory->strict_function_transition_symbol();
9028      break;
9029    default:
9030      UNREACHABLE();
9031      break;
9032  }
9033  Map* maybe_transition =
9034      TransitionArray::SearchSpecial(*initial_map, *transition_symbol);
9035  if (maybe_transition != NULL) {
9036    return handle(maybe_transition, isolate);
9037  }
9038  initial_map->NotifyLeafMapLayoutChange();
9039
9040  // Create new map taking descriptors from the |function_map| and all
9041  // the other details from the |initial_map|.
9042  Handle<Map> map =
9043      Map::CopyInitialMap(function_map, initial_map->instance_size(),
9044                          initial_map->GetInObjectProperties(),
9045                          initial_map->unused_property_fields());
9046  map->SetConstructor(initial_map->GetConstructor());
9047  map->set_prototype(initial_map->prototype());
9048
9049  if (TransitionArray::CanHaveMoreTransitions(initial_map)) {
9050    Map::ConnectTransition(initial_map, map, transition_symbol,
9051                           SPECIAL_TRANSITION);
9052  }
9053  return map;
9054}
9055
9056
9057Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
9058  DCHECK(!map->is_prototype_map());
9059  Handle<Map> new_map = CopyDropDescriptors(map);
9060
9061  if (map->owns_descriptors()) {
9062    // In case the map owned its own descriptors, share the descriptors and
9063    // transfer ownership to the new map.
9064    // The properties did not change, so reuse descriptors.
9065    new_map->InitializeDescriptors(map->instance_descriptors(),
9066                                   map->GetLayoutDescriptor());
9067  } else {
9068    // In case the map did not own its own descriptors, a split is forced by
9069    // copying the map; creating a new descriptor array cell.
9070    Handle<DescriptorArray> descriptors(map->instance_descriptors());
9071    int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9072    Handle<DescriptorArray> new_descriptors =
9073        DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
9074    Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9075                                                   map->GetIsolate());
9076    new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
9077  }
9078
9079#if TRACE_MAPS
9080  if (FLAG_trace_maps) {
9081    PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
9082           reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
9083           reason);
9084  }
9085#endif
9086
9087  return new_map;
9088}
9089
9090
9091Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
9092  Handle<DescriptorArray> descriptors(map->instance_descriptors());
9093  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9094  Handle<DescriptorArray> new_descriptors =
9095      DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
9096  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9097                                                 map->GetIsolate());
9098  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
9099                                OMIT_TRANSITION, MaybeHandle<Name>(), reason,
9100                                SPECIAL_TRANSITION);
9101}
9102
9103
9104Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
9105  Handle<Map> copy =
9106      Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
9107
9108  // Check that we do not overflow the instance size when adding the extra
9109  // inobject properties. If the instance size overflows, we allocate as many
9110  // properties as we can as inobject properties.
9111  int max_extra_properties =
9112      (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
9113
9114  if (inobject_properties > max_extra_properties) {
9115    inobject_properties = max_extra_properties;
9116  }
9117
9118  int new_instance_size =
9119      JSObject::kHeaderSize + kPointerSize * inobject_properties;
9120
9121  // Adjust the map with the extra inobject properties.
9122  copy->SetInObjectProperties(inobject_properties);
9123  copy->set_unused_property_fields(inobject_properties);
9124  copy->set_instance_size(new_instance_size);
9125  copy->set_visitor_id(Heap::GetStaticVisitorIdForMap(*copy));
9126  return copy;
9127}
9128
9129
9130Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
9131                                          PropertyAttributes attrs_to_add,
9132                                          Handle<Symbol> transition_marker,
9133                                          const char* reason) {
9134  int num_descriptors = map->NumberOfOwnDescriptors();
9135  Isolate* isolate = map->GetIsolate();
9136  Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
9137      handle(map->instance_descriptors(), isolate), num_descriptors,
9138      attrs_to_add);
9139  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9140                                                 isolate);
9141  Handle<Map> new_map = CopyReplaceDescriptors(
9142      map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
9143      transition_marker, reason, SPECIAL_TRANSITION);
9144  new_map->set_is_extensible(false);
9145  if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
9146    ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
9147                                ? SLOW_STRING_WRAPPER_ELEMENTS
9148                                : DICTIONARY_ELEMENTS;
9149    new_map->set_elements_kind(new_kind);
9150  }
9151  return new_map;
9152}
9153
9154FieldType* DescriptorArray::GetFieldType(int descriptor_number) {
9155  DCHECK(GetDetails(descriptor_number).location() == kField);
9156  Object* value = GetValue(descriptor_number);
9157  if (value->IsWeakCell()) {
9158    if (WeakCell::cast(value)->cleared()) return FieldType::None();
9159    value = WeakCell::cast(value)->value();
9160  }
9161  return FieldType::cast(value);
9162}
9163
9164namespace {
9165
9166bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) {
9167  PropertyDetails details = descriptors->GetDetails(descriptor);
9168  switch (details.type()) {
9169    case DATA:
9170      return value->FitsRepresentation(details.representation()) &&
9171             descriptors->GetFieldType(descriptor)->NowContains(value);
9172
9173    case DATA_CONSTANT:
9174      DCHECK(descriptors->GetConstant(descriptor) != value ||
9175             value->FitsRepresentation(details.representation()));
9176      return descriptors->GetConstant(descriptor) == value;
9177
9178    case ACCESSOR:
9179    case ACCESSOR_CONSTANT:
9180      return false;
9181  }
9182
9183  UNREACHABLE();
9184  return false;
9185}
9186
9187Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
9188                                     Handle<Object> value) {
9189  if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map;
9190
9191  Isolate* isolate = map->GetIsolate();
9192  PropertyAttributes attributes =
9193      map->instance_descriptors()->GetDetails(descriptor).attributes();
9194  Representation representation = value->OptimalRepresentation();
9195  Handle<FieldType> type = value->OptimalType(isolate, representation);
9196
9197  return Map::ReconfigureProperty(map, descriptor, kData, attributes,
9198                                  representation, type, FORCE_FIELD);
9199}
9200
9201}  // namespace
9202
9203// static
9204Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
9205                                        Handle<Object> value) {
9206  // Dictionaries can store any property value.
9207  DCHECK(!map->is_dictionary_map());
9208  // Update to the newest map before storing the property.
9209  return UpdateDescriptorForValue(Update(map), descriptor, value);
9210}
9211
9212
9213Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
9214                                          Handle<Object> value,
9215                                          PropertyAttributes attributes,
9216                                          StoreFromKeyed store_mode) {
9217  RuntimeCallTimerScope stats_scope(
9218      *map, map->is_prototype_map()
9219                ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
9220                : &RuntimeCallStats::Map_TransitionToDataProperty);
9221
9222  DCHECK(name->IsUniqueName());
9223  DCHECK(!map->is_dictionary_map());
9224
9225  // Migrate to the newest map before storing the property.
9226  map = Update(map);
9227
9228  Map* maybe_transition =
9229      TransitionArray::SearchTransition(*map, kData, *name, attributes);
9230  if (maybe_transition != NULL) {
9231    Handle<Map> transition(maybe_transition);
9232    int descriptor = transition->LastAdded();
9233
9234    DCHECK_EQ(attributes, transition->instance_descriptors()
9235                              ->GetDetails(descriptor)
9236                              .attributes());
9237
9238    return UpdateDescriptorForValue(transition, descriptor, value);
9239  }
9240
9241  TransitionFlag flag = INSERT_TRANSITION;
9242  MaybeHandle<Map> maybe_map;
9243  if (value->IsJSFunction()) {
9244    maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
9245  } else if (!map->TooManyFastProperties(store_mode)) {
9246    Isolate* isolate = name->GetIsolate();
9247    Representation representation = value->OptimalRepresentation();
9248    Handle<FieldType> type = value->OptimalType(isolate, representation);
9249    maybe_map =
9250        Map::CopyWithField(map, name, type, attributes, representation, flag);
9251  }
9252
9253  Handle<Map> result;
9254  if (!maybe_map.ToHandle(&result)) {
9255#if TRACE_MAPS
9256    if (FLAG_trace_maps) {
9257      Vector<char> name_buffer = Vector<char>::New(100);
9258      name->NameShortPrint(name_buffer);
9259      Vector<char> buffer = Vector<char>::New(128);
9260      SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
9261      return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
9262    }
9263#endif
9264    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
9265                          "TooManyFastProperties");
9266  }
9267
9268  return result;
9269}
9270
9271
9272Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
9273                                             PropertyKind kind,
9274                                             PropertyAttributes attributes) {
9275  // Dictionaries have to be reconfigured in-place.
9276  DCHECK(!map->is_dictionary_map());
9277
9278  if (!map->GetBackPointer()->IsMap()) {
9279    // There is no benefit from reconstructing transition tree for maps without
9280    // back pointers.
9281    return CopyGeneralizeAllRepresentations(
9282        map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
9283        "GenAll_AttributesMismatchProtoMap");
9284  }
9285
9286  if (FLAG_trace_generalization) {
9287    map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9288  }
9289
9290  Isolate* isolate = map->GetIsolate();
9291  Handle<Map> new_map = ReconfigureProperty(
9292      map, descriptor, kind, attributes, Representation::None(),
9293      FieldType::None(isolate), FORCE_FIELD);
9294  return new_map;
9295}
9296
9297Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
9298                                              Handle<Name> name, int descriptor,
9299                                              Handle<Object> getter,
9300                                              Handle<Object> setter,
9301                                              PropertyAttributes attributes) {
9302  RuntimeCallTimerScope stats_scope(
9303      isolate,
9304      map->is_prototype_map()
9305          ? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty
9306          : &RuntimeCallStats::Map_TransitionToAccessorProperty);
9307
9308  // At least one of the accessors needs to be a new value.
9309  DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
9310  DCHECK(name->IsUniqueName());
9311
9312  // Dictionary maps can always have additional data properties.
9313  if (map->is_dictionary_map()) return map;
9314
9315  // Migrate to the newest map before transitioning to the new property.
9316  map = Update(map);
9317
9318  PropertyNormalizationMode mode = map->is_prototype_map()
9319                                       ? KEEP_INOBJECT_PROPERTIES
9320                                       : CLEAR_INOBJECT_PROPERTIES;
9321
9322  Map* maybe_transition =
9323      TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
9324  if (maybe_transition != NULL) {
9325    Handle<Map> transition(maybe_transition, isolate);
9326    DescriptorArray* descriptors = transition->instance_descriptors();
9327    int descriptor = transition->LastAdded();
9328    DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
9329
9330    DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
9331    DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
9332
9333    Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
9334    if (!maybe_pair->IsAccessorPair()) {
9335      return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
9336    }
9337
9338    Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
9339    if (!pair->Equals(*getter, *setter)) {
9340      return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
9341    }
9342
9343    return transition;
9344  }
9345
9346  Handle<AccessorPair> pair;
9347  DescriptorArray* old_descriptors = map->instance_descriptors();
9348  if (descriptor != DescriptorArray::kNotFound) {
9349    if (descriptor != map->LastAdded()) {
9350      return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
9351    }
9352    PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
9353    if (old_details.type() != ACCESSOR_CONSTANT) {
9354      return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
9355    }
9356
9357    if (old_details.attributes() != attributes) {
9358      return Map::Normalize(map, mode, "AccessorsWithAttributes");
9359    }
9360
9361    Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
9362    if (!maybe_pair->IsAccessorPair()) {
9363      return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
9364    }
9365
9366    Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
9367    if (current_pair->Equals(*getter, *setter)) return map;
9368
9369    bool overwriting_accessor = false;
9370    if (!getter->IsNull(isolate) &&
9371        !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
9372        current_pair->get(ACCESSOR_GETTER) != *getter) {
9373      overwriting_accessor = true;
9374    }
9375    if (!setter->IsNull(isolate) &&
9376        !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
9377        current_pair->get(ACCESSOR_SETTER) != *setter) {
9378      overwriting_accessor = true;
9379    }
9380    if (overwriting_accessor) {
9381      return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
9382    }
9383
9384    pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
9385  } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
9386             map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
9387    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
9388  } else {
9389    pair = isolate->factory()->NewAccessorPair();
9390  }
9391
9392  pair->SetComponents(*getter, *setter);
9393
9394  TransitionFlag flag = INSERT_TRANSITION;
9395  AccessorConstantDescriptor new_desc(name, pair, attributes);
9396  return Map::CopyInsertDescriptor(map, &new_desc, flag);
9397}
9398
9399
9400Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
9401                                   Descriptor* descriptor,
9402                                   TransitionFlag flag) {
9403  Handle<DescriptorArray> descriptors(map->instance_descriptors());
9404
9405  // Share descriptors only if map owns descriptors and it not an initial map.
9406  if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
9407      !map->GetBackPointer()->IsUndefined(map->GetIsolate()) &&
9408      TransitionArray::CanHaveMoreTransitions(map)) {
9409    return ShareDescriptor(map, descriptors, descriptor);
9410  }
9411
9412  int nof = map->NumberOfOwnDescriptors();
9413  Handle<DescriptorArray> new_descriptors =
9414      DescriptorArray::CopyUpTo(descriptors, nof, 1);
9415  new_descriptors->Append(descriptor);
9416
9417  Handle<LayoutDescriptor> new_layout_descriptor =
9418      FLAG_unbox_double_fields
9419          ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
9420          : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
9421
9422  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
9423                                flag, descriptor->GetKey(), "CopyAddDescriptor",
9424                                SIMPLE_PROPERTY_TRANSITION);
9425}
9426
9427
9428Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
9429                                      Descriptor* descriptor,
9430                                      TransitionFlag flag) {
9431  Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
9432
9433  // We replace the key if it is already present.
9434  int index = old_descriptors->SearchWithCache(map->GetIsolate(),
9435                                               *descriptor->GetKey(), *map);
9436  if (index != DescriptorArray::kNotFound) {
9437    return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
9438  }
9439  return CopyAddDescriptor(map, descriptor, flag);
9440}
9441
9442
9443Handle<DescriptorArray> DescriptorArray::CopyUpTo(
9444    Handle<DescriptorArray> desc,
9445    int enumeration_index,
9446    int slack) {
9447  return DescriptorArray::CopyUpToAddAttributes(
9448      desc, enumeration_index, NONE, slack);
9449}
9450
9451
9452Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
9453    Handle<DescriptorArray> desc,
9454    int enumeration_index,
9455    PropertyAttributes attributes,
9456    int slack) {
9457  if (enumeration_index + slack == 0) {
9458    return desc->GetIsolate()->factory()->empty_descriptor_array();
9459  }
9460
9461  int size = enumeration_index;
9462
9463  Handle<DescriptorArray> descriptors =
9464      DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
9465
9466  if (attributes != NONE) {
9467    for (int i = 0; i < size; ++i) {
9468      Object* value = desc->GetValue(i);
9469      Name* key = desc->GetKey(i);
9470      PropertyDetails details = desc->GetDetails(i);
9471      // Bulk attribute changes never affect private properties.
9472      if (!key->IsPrivate()) {
9473        int mask = DONT_DELETE | DONT_ENUM;
9474        // READ_ONLY is an invalid attribute for JS setters/getters.
9475        if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
9476          mask |= READ_ONLY;
9477        }
9478        details = details.CopyAddAttributes(
9479            static_cast<PropertyAttributes>(attributes & mask));
9480      }
9481      Descriptor inner_desc(
9482          handle(key), handle(value, desc->GetIsolate()), details);
9483      descriptors->SetDescriptor(i, &inner_desc);
9484    }
9485  } else {
9486    for (int i = 0; i < size; ++i) {
9487      descriptors->CopyFrom(i, *desc);
9488    }
9489  }
9490
9491  if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
9492
9493  return descriptors;
9494}
9495
9496
9497bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
9498  for (int i = 0; i < nof_descriptors; i++) {
9499    if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
9500      return false;
9501    }
9502    PropertyDetails details = GetDetails(i);
9503    PropertyDetails other_details = desc->GetDetails(i);
9504    if (details.type() != other_details.type() ||
9505        !details.representation().Equals(other_details.representation())) {
9506      return false;
9507    }
9508  }
9509  return true;
9510}
9511
9512
9513Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
9514                                       Handle<DescriptorArray> descriptors,
9515                                       Descriptor* descriptor,
9516                                       int insertion_index,
9517                                       TransitionFlag flag) {
9518  Handle<Name> key = descriptor->GetKey();
9519  DCHECK(*key == descriptors->GetKey(insertion_index));
9520
9521  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
9522      descriptors, map->NumberOfOwnDescriptors());
9523
9524  new_descriptors->Replace(insertion_index, descriptor);
9525  Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
9526      map, new_descriptors, new_descriptors->number_of_descriptors());
9527
9528  SimpleTransitionFlag simple_flag =
9529      (insertion_index == descriptors->number_of_descriptors() - 1)
9530          ? SIMPLE_PROPERTY_TRANSITION
9531          : PROPERTY_TRANSITION;
9532  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
9533                                flag, key, "CopyReplaceDescriptor",
9534                                simple_flag);
9535}
9536
9537// Helper class to manage a Map's code cache. The layout depends on the number
9538// of entries; this is worthwhile because most code caches are very small,
9539// but some are huge (thousands of entries).
9540// For zero entries, the EmptyFixedArray is used.
9541// For one entry, we use a 2-element FixedArray containing [name, code].
9542// For 2..100 entries, we use a FixedArray with linear lookups, the layout is:
9543//   [0] - number of slots that are currently in use
9544//   [1] - first name
9545//   [2] - first code
9546//   [3] - second name
9547//   [4] - second code
9548//   etc.
9549// For more than 128 entries, we use a CodeCacheHashTable.
9550class CodeCache : public AllStatic {
9551 public:
9552  // Returns the new cache, to be stored on the map.
9553  static Handle<FixedArray> Put(Isolate* isolate, Handle<FixedArray> cache,
9554                                Handle<Name> name, Handle<Code> code) {
9555    int length = cache->length();
9556    if (length == 0) return PutFirstElement(isolate, name, code);
9557    if (length == kEntrySize) {
9558      return PutSecondElement(isolate, cache, name, code);
9559    }
9560    if (length <= kLinearMaxSize) {
9561      Handle<FixedArray> result = PutLinearElement(isolate, cache, name, code);
9562      if (!result.is_null()) return result;
9563      // Fall through if linear storage is getting too large.
9564    }
9565    return PutHashTableElement(isolate, cache, name, code);
9566  }
9567
9568  static Code* Lookup(FixedArray* cache, Name* name, Code::Flags flags) {
9569    int length = cache->length();
9570    if (length == 0) return nullptr;
9571    if (length == kEntrySize) return OneElementLookup(cache, name, flags);
9572    if (!cache->IsCodeCacheHashTable()) {
9573      return LinearLookup(cache, name, flags);
9574    } else {
9575      return CodeCacheHashTable::cast(cache)->Lookup(name, flags);
9576    }
9577  }
9578
9579 private:
9580  static const int kNameIndex = 0;
9581  static const int kCodeIndex = 1;
9582  static const int kEntrySize = 2;
9583
9584  static const int kLinearUsageIndex = 0;
9585  static const int kLinearReservedSlots = 1;
9586  static const int kLinearInitialCapacity = 2;
9587  static const int kLinearMaxSize = 257;  // == LinearSizeFor(128);
9588
9589  static const int kHashTableInitialCapacity = 200;  // Number of entries.
9590
9591  static int LinearSizeFor(int entries) {
9592    return kLinearReservedSlots + kEntrySize * entries;
9593  }
9594
9595  static int LinearNewSize(int old_size) {
9596    int old_entries = (old_size - kLinearReservedSlots) / kEntrySize;
9597    return LinearSizeFor(old_entries * 2);
9598  }
9599
9600  static Code* OneElementLookup(FixedArray* cache, Name* name,
9601                                Code::Flags flags) {
9602    DCHECK_EQ(cache->length(), kEntrySize);
9603    if (cache->get(kNameIndex) != name) return nullptr;
9604    Code* maybe_code = Code::cast(cache->get(kCodeIndex));
9605    if (maybe_code->flags() != flags) return nullptr;
9606    return maybe_code;
9607  }
9608
9609  static Code* LinearLookup(FixedArray* cache, Name* name, Code::Flags flags) {
9610    DCHECK_GE(cache->length(), kEntrySize);
9611    DCHECK(!cache->IsCodeCacheHashTable());
9612    int usage = GetLinearUsage(cache);
9613    for (int i = kLinearReservedSlots; i < usage; i += kEntrySize) {
9614      if (cache->get(i + kNameIndex) != name) continue;
9615      Code* code = Code::cast(cache->get(i + kCodeIndex));
9616      if (code->flags() == flags) return code;
9617    }
9618    return nullptr;
9619  }
9620
9621  static Handle<FixedArray> PutFirstElement(Isolate* isolate, Handle<Name> name,
9622                                            Handle<Code> code) {
9623    Handle<FixedArray> cache = isolate->factory()->NewFixedArray(kEntrySize);
9624    cache->set(kNameIndex, *name);
9625    cache->set(kCodeIndex, *code);
9626    return cache;
9627  }
9628
9629  static Handle<FixedArray> PutSecondElement(Isolate* isolate,
9630                                             Handle<FixedArray> cache,
9631                                             Handle<Name> name,
9632                                             Handle<Code> code) {
9633    DCHECK_EQ(cache->length(), kEntrySize);
9634    Handle<FixedArray> new_cache = isolate->factory()->NewFixedArray(
9635        LinearSizeFor(kLinearInitialCapacity));
9636    new_cache->set(kLinearReservedSlots + kNameIndex, cache->get(kNameIndex));
9637    new_cache->set(kLinearReservedSlots + kCodeIndex, cache->get(kCodeIndex));
9638    new_cache->set(LinearSizeFor(1) + kNameIndex, *name);
9639    new_cache->set(LinearSizeFor(1) + kCodeIndex, *code);
9640    new_cache->set(kLinearUsageIndex, Smi::FromInt(LinearSizeFor(2)));
9641    return new_cache;
9642  }
9643
9644  static Handle<FixedArray> PutLinearElement(Isolate* isolate,
9645                                             Handle<FixedArray> cache,
9646                                             Handle<Name> name,
9647                                             Handle<Code> code) {
9648    int length = cache->length();
9649    int usage = GetLinearUsage(*cache);
9650    DCHECK_LE(usage, length);
9651    // Check if we need to grow.
9652    if (usage == length) {
9653      int new_length = LinearNewSize(length);
9654      if (new_length > kLinearMaxSize) return Handle<FixedArray>::null();
9655      Handle<FixedArray> new_cache =
9656          isolate->factory()->NewFixedArray(new_length);
9657      for (int i = kLinearReservedSlots; i < length; i++) {
9658        new_cache->set(i, cache->get(i));
9659      }
9660      cache = new_cache;
9661    }
9662    // Store new entry.
9663    DCHECK_GE(cache->length(), usage + kEntrySize);
9664    cache->set(usage + kNameIndex, *name);
9665    cache->set(usage + kCodeIndex, *code);
9666    cache->set(kLinearUsageIndex, Smi::FromInt(usage + kEntrySize));
9667    return cache;
9668  }
9669
9670  static Handle<FixedArray> PutHashTableElement(Isolate* isolate,
9671                                                Handle<FixedArray> cache,
9672                                                Handle<Name> name,
9673                                                Handle<Code> code) {
9674    // Check if we need to transition from linear to hash table storage.
9675    if (!cache->IsCodeCacheHashTable()) {
9676      // Check that the initial hash table capacity is large enough.
9677      DCHECK_EQ(kLinearMaxSize, LinearSizeFor(128));
9678      STATIC_ASSERT(kHashTableInitialCapacity > 128);
9679
9680      int length = cache->length();
9681      // Only migrate from linear storage when it's full.
9682      DCHECK_EQ(length, GetLinearUsage(*cache));
9683      DCHECK_EQ(length, kLinearMaxSize);
9684      Handle<CodeCacheHashTable> table =
9685          CodeCacheHashTable::New(isolate, kHashTableInitialCapacity);
9686      HandleScope scope(isolate);
9687      for (int i = kLinearReservedSlots; i < length; i += kEntrySize) {
9688        Handle<Name> old_name(Name::cast(cache->get(i + kNameIndex)), isolate);
9689        Handle<Code> old_code(Code::cast(cache->get(i + kCodeIndex)), isolate);
9690        CodeCacheHashTable::Put(table, old_name, old_code);
9691      }
9692      cache = table;
9693    }
9694    // Store new entry.
9695    DCHECK(cache->IsCodeCacheHashTable());
9696    return CodeCacheHashTable::Put(Handle<CodeCacheHashTable>::cast(cache),
9697                                   name, code);
9698  }
9699
9700  static inline int GetLinearUsage(FixedArray* linear_cache) {
9701    DCHECK_GT(linear_cache->length(), kEntrySize);
9702    return Smi::cast(linear_cache->get(kLinearUsageIndex))->value();
9703  }
9704};
9705
9706void Map::UpdateCodeCache(Handle<Map> map,
9707                          Handle<Name> name,
9708                          Handle<Code> code) {
9709  Isolate* isolate = map->GetIsolate();
9710  Handle<FixedArray> cache(map->code_cache(), isolate);
9711  Handle<FixedArray> new_cache = CodeCache::Put(isolate, cache, name, code);
9712  map->set_code_cache(*new_cache);
9713}
9714
9715Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
9716  return CodeCache::Lookup(code_cache(), name, flags);
9717}
9718
9719
9720// The key in the code cache hash table consists of the property name and the
9721// code object. The actual match is on the name and the code flags. If a key
9722// is created using the flags and not a code object it can only be used for
9723// lookup not to create a new entry.
9724class CodeCacheHashTableKey : public HashTableKey {
9725 public:
9726  CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
9727      : name_(name), flags_(flags), code_() {
9728    DCHECK(name_->IsUniqueName());
9729  }
9730
9731  CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
9732      : name_(name), flags_(code->flags()), code_(code) {
9733    DCHECK(name_->IsUniqueName());
9734  }
9735
9736  bool IsMatch(Object* other) override {
9737    DCHECK(other->IsFixedArray());
9738    FixedArray* pair = FixedArray::cast(other);
9739    Name* name = Name::cast(pair->get(0));
9740    Code::Flags flags = Code::cast(pair->get(1))->flags();
9741    if (flags != flags_) return false;
9742    DCHECK(name->IsUniqueName());
9743    return *name_ == name;
9744  }
9745
9746  static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
9747    return name->Hash() ^ flags;
9748  }
9749
9750  uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
9751
9752  uint32_t HashForObject(Object* obj) override {
9753    FixedArray* pair = FixedArray::cast(obj);
9754    Name* name = Name::cast(pair->get(0));
9755    Code* code = Code::cast(pair->get(1));
9756    return NameFlagsHashHelper(name, code->flags());
9757  }
9758
9759  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
9760    Handle<Code> code = code_.ToHandleChecked();
9761    Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
9762    pair->set(0, *name_);
9763    pair->set(1, *code);
9764    return pair;
9765  }
9766
9767 private:
9768  Handle<Name> name_;
9769  Code::Flags flags_;
9770  // TODO(jkummerow): We should be able to get by without this.
9771  MaybeHandle<Code> code_;
9772};
9773
9774
9775Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
9776    Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
9777  CodeCacheHashTableKey key(name, code);
9778
9779  Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
9780
9781  int entry = new_cache->FindInsertionEntry(key.Hash());
9782  Handle<Object> k = key.AsHandle(cache->GetIsolate());
9783
9784  new_cache->set(EntryToIndex(entry), *k);
9785  new_cache->ElementAdded();
9786  return new_cache;
9787}
9788
9789Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
9790  DisallowHeapAllocation no_alloc;
9791  CodeCacheHashTableKey key(handle(name), flags);
9792  int entry = FindEntry(&key);
9793  if (entry == kNotFound) return nullptr;
9794  return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
9795}
9796
9797void FixedArray::Shrink(int new_length) {
9798  DCHECK(0 <= new_length && new_length <= length());
9799  if (new_length < length()) {
9800    GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
9801        this, length() - new_length);
9802  }
9803}
9804
9805
9806void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
9807  DisallowHeapAllocation no_gc;
9808  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
9809  for (int index = 0; index < len; index++) {
9810    dest->set(dest_pos+index, get(pos+index), mode);
9811  }
9812}
9813
9814
9815#ifdef DEBUG
9816bool FixedArray::IsEqualTo(FixedArray* other) {
9817  if (length() != other->length()) return false;
9818  for (int i = 0 ; i < length(); ++i) {
9819    if (get(i) != other->get(i)) return false;
9820  }
9821  return true;
9822}
9823#endif
9824
9825
9826// static
9827void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
9828                         Handle<HeapObject> value) {
9829  DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
9830  Handle<WeakCell> cell =
9831      value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
9832                     : array->GetIsolate()->factory()->NewWeakCell(value);
9833  Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
9834  if (FLAG_trace_weak_arrays) {
9835    PrintF("[WeakFixedArray: storing at index %d ]\n", index);
9836  }
9837  array->set_last_used_index(index);
9838}
9839
9840
9841// static
9842Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array,
9843                                           Handle<HeapObject> value,
9844                                           int* assigned_index) {
9845  Handle<WeakFixedArray> array =
9846      (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
9847          ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
9848          : Handle<WeakFixedArray>::cast(maybe_array);
9849  // Try to store the new entry if there's room. Optimize for consecutive
9850  // accesses.
9851  int first_index = array->last_used_index();
9852  int length = array->Length();
9853  if (length > 0) {
9854    for (int i = first_index;;) {
9855      if (array->IsEmptySlot((i))) {
9856        WeakFixedArray::Set(array, i, value);
9857        if (assigned_index != NULL) *assigned_index = i;
9858        return array;
9859      }
9860      if (FLAG_trace_weak_arrays) {
9861        PrintF("[WeakFixedArray: searching for free slot]\n");
9862      }
9863      i = (i + 1) % length;
9864      if (i == first_index) break;
9865    }
9866  }
9867
9868  // No usable slot found, grow the array.
9869  int new_length = length == 0 ? 1 : length + (length >> 1) + 4;
9870  Handle<WeakFixedArray> new_array =
9871      Allocate(array->GetIsolate(), new_length, array);
9872  if (FLAG_trace_weak_arrays) {
9873    PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
9874  }
9875  WeakFixedArray::Set(new_array, length, value);
9876  if (assigned_index != NULL) *assigned_index = length;
9877  return new_array;
9878}
9879
9880
9881template <class CompactionCallback>
9882void WeakFixedArray::Compact() {
9883  FixedArray* array = FixedArray::cast(this);
9884  int new_length = kFirstIndex;
9885  for (int i = kFirstIndex; i < array->length(); i++) {
9886    Object* element = array->get(i);
9887    if (element->IsSmi()) continue;
9888    if (WeakCell::cast(element)->cleared()) continue;
9889    Object* value = WeakCell::cast(element)->value();
9890    CompactionCallback::Callback(value, i - kFirstIndex,
9891                                 new_length - kFirstIndex);
9892    array->set(new_length++, element);
9893  }
9894  array->Shrink(new_length);
9895  set_last_used_index(0);
9896}
9897
9898
9899void WeakFixedArray::Iterator::Reset(Object* maybe_array) {
9900  if (maybe_array->IsWeakFixedArray()) {
9901    list_ = WeakFixedArray::cast(maybe_array);
9902    index_ = 0;
9903#ifdef DEBUG
9904    last_used_index_ = list_->last_used_index();
9905#endif  // DEBUG
9906  }
9907}
9908
9909
9910void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value,
9911                                                             int old_index,
9912                                                             int new_index) {
9913  DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
9914  Map* map = Map::cast(value);
9915  DCHECK(map->prototype_info()->IsPrototypeInfo());
9916  PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
9917  DCHECK_EQ(old_index, proto_info->registry_slot());
9918  proto_info->set_registry_slot(new_index);
9919}
9920
9921
9922template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>();
9923template void
9924WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>();
9925
9926
9927bool WeakFixedArray::Remove(Handle<HeapObject> value) {
9928  if (Length() == 0) return false;
9929  // Optimize for the most recently added element to be removed again.
9930  int first_index = last_used_index();
9931  for (int i = first_index;;) {
9932    if (Get(i) == *value) {
9933      Clear(i);
9934      // Users of WeakFixedArray should make sure that there are no duplicates.
9935      return true;
9936    }
9937    i = (i + 1) % Length();
9938    if (i == first_index) return false;
9939  }
9940  UNREACHABLE();
9941}
9942
9943
9944// static
9945Handle<WeakFixedArray> WeakFixedArray::Allocate(
9946    Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
9947  DCHECK(0 <= size);
9948  Handle<FixedArray> result =
9949      isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
9950  int index = 0;
9951  if (!initialize_from.is_null()) {
9952    DCHECK(initialize_from->Length() <= size);
9953    Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
9954    // Copy the entries without compacting, since the PrototypeInfo relies on
9955    // the index of the entries not to change.
9956    while (index < raw_source->length()) {
9957      result->set(index, raw_source->get(index));
9958      index++;
9959    }
9960  }
9961  while (index < result->length()) {
9962    result->set(index, Smi::FromInt(0));
9963    index++;
9964  }
9965  return Handle<WeakFixedArray>::cast(result);
9966}
9967
9968
9969Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
9970                                 AddMode mode) {
9971  int length = array->Length();
9972  array = EnsureSpace(array, length + 1);
9973  if (mode == kReloadLengthAfterAllocation) {
9974    DCHECK(array->Length() <= length);
9975    length = array->Length();
9976  }
9977  array->Set(length, *obj);
9978  array->SetLength(length + 1);
9979  return array;
9980}
9981
9982Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
9983                                 Handle<Object> obj2, AddMode mode) {
9984  int length = array->Length();
9985  array = EnsureSpace(array, length + 2);
9986  if (mode == kReloadLengthAfterAllocation) {
9987    length = array->Length();
9988  }
9989  array->Set(length, *obj1);
9990  array->Set(length + 1, *obj2);
9991  array->SetLength(length + 2);
9992  return array;
9993}
9994
9995
9996bool ArrayList::IsFull() {
9997  int capacity = length();
9998  return kFirstIndex + Length() == capacity;
9999}
10000
10001
10002Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
10003  int capacity = array->length();
10004  bool empty = (capacity == 0);
10005  if (capacity < kFirstIndex + length) {
10006    Isolate* isolate = array->GetIsolate();
10007    int new_capacity = kFirstIndex + length;
10008    new_capacity = new_capacity + Max(new_capacity / 2, 2);
10009    int grow_by = new_capacity - capacity;
10010    array = Handle<ArrayList>::cast(
10011        isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
10012    if (empty) array->SetLength(0);
10013  }
10014  return array;
10015}
10016
10017Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
10018                                                  int number_of_descriptors,
10019                                                  int slack,
10020                                                  PretenureFlag pretenure) {
10021  DCHECK(0 <= number_of_descriptors);
10022  Factory* factory = isolate->factory();
10023  // Do not use DescriptorArray::cast on incomplete object.
10024  int size = number_of_descriptors + slack;
10025  if (size == 0) return factory->empty_descriptor_array();
10026  // Allocate the array of keys.
10027  Handle<FixedArray> result =
10028      factory->NewFixedArray(LengthFor(size), pretenure);
10029
10030  result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
10031  result->set(kEnumCacheIndex, Smi::FromInt(0));
10032  return Handle<DescriptorArray>::cast(result);
10033}
10034
10035
10036void DescriptorArray::ClearEnumCache() {
10037  set(kEnumCacheIndex, Smi::FromInt(0));
10038}
10039
10040
10041void DescriptorArray::Replace(int index, Descriptor* descriptor) {
10042  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
10043  Set(index, descriptor);
10044}
10045
10046
10047// static
10048void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
10049                                   Isolate* isolate,
10050                                   Handle<FixedArray> new_cache,
10051                                   Handle<FixedArray> new_index_cache) {
10052  DCHECK(!descriptors->IsEmpty());
10053  FixedArray* bridge_storage;
10054  bool needs_new_enum_cache = !descriptors->HasEnumCache();
10055  if (needs_new_enum_cache) {
10056    bridge_storage = *isolate->factory()->NewFixedArray(
10057        DescriptorArray::kEnumCacheBridgeLength);
10058  } else {
10059    bridge_storage = FixedArray::cast(descriptors->get(kEnumCacheIndex));
10060  }
10061  bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
10062  bridge_storage->set(kEnumCacheBridgeIndicesCacheIndex,
10063                      new_index_cache.is_null() ? Object::cast(Smi::FromInt(0))
10064                                                : *new_index_cache);
10065  if (needs_new_enum_cache) {
10066    descriptors->set(kEnumCacheIndex, bridge_storage);
10067  }
10068}
10069
10070
10071void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
10072  Object* value = src->GetValue(index);
10073  PropertyDetails details = src->GetDetails(index);
10074  Descriptor desc(handle(src->GetKey(index)),
10075                  handle(value, src->GetIsolate()),
10076                  details);
10077  SetDescriptor(index, &desc);
10078}
10079
10080
10081void DescriptorArray::Sort() {
10082  // In-place heap sort.
10083  int len = number_of_descriptors();
10084  // Reset sorting since the descriptor array might contain invalid pointers.
10085  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
10086  // Bottom-up max-heap construction.
10087  // Index of the last node with children
10088  const int max_parent_index = (len / 2) - 1;
10089  for (int i = max_parent_index; i >= 0; --i) {
10090    int parent_index = i;
10091    const uint32_t parent_hash = GetSortedKey(i)->Hash();
10092    while (parent_index <= max_parent_index) {
10093      int child_index = 2 * parent_index + 1;
10094      uint32_t child_hash = GetSortedKey(child_index)->Hash();
10095      if (child_index + 1 < len) {
10096        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10097        if (right_child_hash > child_hash) {
10098          child_index++;
10099          child_hash = right_child_hash;
10100        }
10101      }
10102      if (child_hash <= parent_hash) break;
10103      SwapSortedKeys(parent_index, child_index);
10104      // Now element at child_index could be < its children.
10105      parent_index = child_index;  // parent_hash remains correct.
10106    }
10107  }
10108
10109  // Extract elements and create sorted array.
10110  for (int i = len - 1; i > 0; --i) {
10111    // Put max element at the back of the array.
10112    SwapSortedKeys(0, i);
10113    // Shift down the new top element.
10114    int parent_index = 0;
10115    const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
10116    const int max_parent_index = (i / 2) - 1;
10117    while (parent_index <= max_parent_index) {
10118      int child_index = parent_index * 2 + 1;
10119      uint32_t child_hash = GetSortedKey(child_index)->Hash();
10120      if (child_index + 1 < i) {
10121        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10122        if (right_child_hash > child_hash) {
10123          child_index++;
10124          child_hash = right_child_hash;
10125        }
10126      }
10127      if (child_hash <= parent_hash) break;
10128      SwapSortedKeys(parent_index, child_index);
10129      parent_index = child_index;
10130    }
10131  }
10132  DCHECK(IsSortedNoDuplicates());
10133}
10134
10135
10136Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
10137  Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
10138  copy->set_getter(pair->getter());
10139  copy->set_setter(pair->setter());
10140  return copy;
10141}
10142
10143Handle<Object> AccessorPair::GetComponent(Handle<AccessorPair> accessor_pair,
10144                                          AccessorComponent component) {
10145  Object* accessor = accessor_pair->get(component);
10146  if (accessor->IsFunctionTemplateInfo()) {
10147    return ApiNatives::InstantiateFunction(
10148               handle(FunctionTemplateInfo::cast(accessor)))
10149        .ToHandleChecked();
10150  }
10151  Isolate* isolate = accessor_pair->GetIsolate();
10152  if (accessor->IsNull(isolate)) {
10153    return isolate->factory()->undefined_value();
10154  }
10155  return handle(accessor, isolate);
10156}
10157
10158Handle<DeoptimizationInputData> DeoptimizationInputData::New(
10159    Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
10160  return Handle<DeoptimizationInputData>::cast(
10161      isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
10162                                        pretenure));
10163}
10164
10165
10166Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
10167    Isolate* isolate,
10168    int number_of_deopt_points,
10169    PretenureFlag pretenure) {
10170  Handle<FixedArray> result;
10171  if (number_of_deopt_points == 0) {
10172    result = isolate->factory()->empty_fixed_array();
10173  } else {
10174    result = isolate->factory()->NewFixedArray(
10175        LengthOfFixedArray(number_of_deopt_points), pretenure);
10176  }
10177  return Handle<DeoptimizationOutputData>::cast(result);
10178}
10179
10180const int LiteralsArray::kFeedbackVectorOffset =
10181    LiteralsArray::OffsetOfElementAt(LiteralsArray::kVectorIndex);
10182
10183const int LiteralsArray::kOffsetToFirstLiteral =
10184    LiteralsArray::OffsetOfElementAt(LiteralsArray::kFirstLiteralIndex);
10185
10186// static
10187Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate,
10188                                         Handle<TypeFeedbackVector> vector,
10189                                         int number_of_literals,
10190                                         PretenureFlag pretenure) {
10191  if (vector->is_empty() && number_of_literals == 0) {
10192    return Handle<LiteralsArray>::cast(
10193        isolate->factory()->empty_literals_array());
10194  }
10195  Handle<FixedArray> literals = isolate->factory()->NewFixedArray(
10196      number_of_literals + kFirstLiteralIndex, pretenure);
10197  Handle<LiteralsArray> casted_literals = Handle<LiteralsArray>::cast(literals);
10198  casted_literals->set_feedback_vector(*vector);
10199  return casted_literals;
10200}
10201
10202int HandlerTable::LookupRange(int pc_offset, int* data_out,
10203                              CatchPrediction* prediction_out) {
10204  int innermost_handler = -1;
10205#ifdef DEBUG
10206  // Assuming that ranges are well nested, we don't need to track the innermost
10207  // offsets. This is just to verify that the table is actually well nested.
10208  int innermost_start = std::numeric_limits<int>::min();
10209  int innermost_end = std::numeric_limits<int>::max();
10210#endif
10211  for (int i = 0; i < length(); i += kRangeEntrySize) {
10212    int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
10213    int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
10214    int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
10215    int handler_offset = HandlerOffsetField::decode(handler_field);
10216    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
10217    int handler_data = Smi::cast(get(i + kRangeDataIndex))->value();
10218    if (pc_offset > start_offset && pc_offset <= end_offset) {
10219      DCHECK_GE(start_offset, innermost_start);
10220      DCHECK_LT(end_offset, innermost_end);
10221      innermost_handler = handler_offset;
10222#ifdef DEBUG
10223      innermost_start = start_offset;
10224      innermost_end = end_offset;
10225#endif
10226      if (data_out) *data_out = handler_data;
10227      if (prediction_out) *prediction_out = prediction;
10228    }
10229  }
10230  return innermost_handler;
10231}
10232
10233
10234// TODO(turbofan): Make sure table is sorted and use binary search.
10235int HandlerTable::LookupReturn(int pc_offset, CatchPrediction* prediction_out) {
10236  for (int i = 0; i < length(); i += kReturnEntrySize) {
10237    int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
10238    int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
10239    if (pc_offset == return_offset) {
10240      if (prediction_out) {
10241        *prediction_out = HandlerPredictionField::decode(handler_field);
10242      }
10243      return HandlerOffsetField::decode(handler_field);
10244    }
10245  }
10246  return -1;
10247}
10248
10249
10250#ifdef DEBUG
10251bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
10252  if (IsEmpty()) return other->IsEmpty();
10253  if (other->IsEmpty()) return false;
10254  if (length() != other->length()) return false;
10255  for (int i = 0; i < length(); ++i) {
10256    if (get(i) != other->get(i)) return false;
10257  }
10258  return true;
10259}
10260#endif
10261
10262// static
10263Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
10264  Isolate* const isolate = string->GetIsolate();
10265  string = String::Flatten(string);
10266  int const length = string->length();
10267
10268  // Perform left trimming if requested.
10269  int left = 0;
10270  UnicodeCache* unicode_cache = isolate->unicode_cache();
10271  if (mode == kTrim || mode == kTrimLeft) {
10272    while (left < length &&
10273           unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
10274      left++;
10275    }
10276  }
10277
10278  // Perform right trimming if requested.
10279  int right = length;
10280  if (mode == kTrim || mode == kTrimRight) {
10281    while (
10282        right > left &&
10283        unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
10284      right--;
10285    }
10286  }
10287
10288  return isolate->factory()->NewSubString(string, left, right);
10289}
10290
10291bool String::LooksValid() {
10292  if (!GetIsolate()->heap()->Contains(this)) return false;
10293  return true;
10294}
10295
10296
10297// static
10298MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
10299  if (name->IsString()) return Handle<String>::cast(name);
10300  // ES6 section 9.2.11 SetFunctionName, step 4.
10301  Isolate* const isolate = name->GetIsolate();
10302  Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
10303  if (description->IsUndefined(isolate)) {
10304    return isolate->factory()->empty_string();
10305  }
10306  IncrementalStringBuilder builder(isolate);
10307  builder.AppendCharacter('[');
10308  builder.AppendString(Handle<String>::cast(description));
10309  builder.AppendCharacter(']');
10310  return builder.Finish();
10311}
10312
10313// static
10314MaybeHandle<String> Name::ToFunctionName(Handle<Name> name,
10315                                         Handle<String> prefix) {
10316  Handle<String> name_string;
10317  Isolate* const isolate = name->GetIsolate();
10318  ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string, ToFunctionName(name),
10319                             String);
10320  IncrementalStringBuilder builder(isolate);
10321  builder.AppendString(prefix);
10322  builder.AppendCharacter(' ');
10323  builder.AppendString(name_string);
10324  return builder.Finish();
10325}
10326
10327namespace {
10328
10329bool AreDigits(const uint8_t* s, int from, int to) {
10330  for (int i = from; i < to; i++) {
10331    if (s[i] < '0' || s[i] > '9') return false;
10332  }
10333
10334  return true;
10335}
10336
10337
10338int ParseDecimalInteger(const uint8_t* s, int from, int to) {
10339  DCHECK(to - from < 10);  // Overflow is not possible.
10340  DCHECK(from < to);
10341  int d = s[from] - '0';
10342
10343  for (int i = from + 1; i < to; i++) {
10344    d = 10 * d + (s[i] - '0');
10345  }
10346
10347  return d;
10348}
10349
10350}  // namespace
10351
10352
10353// static
10354Handle<Object> String::ToNumber(Handle<String> subject) {
10355  Isolate* const isolate = subject->GetIsolate();
10356
10357  // Flatten {subject} string first.
10358  subject = String::Flatten(subject);
10359
10360  // Fast array index case.
10361  uint32_t index;
10362  if (subject->AsArrayIndex(&index)) {
10363    return isolate->factory()->NewNumberFromUint(index);
10364  }
10365
10366  // Fast case: short integer or some sorts of junk values.
10367  if (subject->IsSeqOneByteString()) {
10368    int len = subject->length();
10369    if (len == 0) return handle(Smi::FromInt(0), isolate);
10370
10371    DisallowHeapAllocation no_gc;
10372    uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
10373    bool minus = (data[0] == '-');
10374    int start_pos = (minus ? 1 : 0);
10375
10376    if (start_pos == len) {
10377      return isolate->factory()->nan_value();
10378    } else if (data[start_pos] > '9') {
10379      // Fast check for a junk value. A valid string may start from a
10380      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
10381      // or the 'I' character ('Infinity'). All of that have codes not greater
10382      // than '9' except 'I' and &nbsp;.
10383      if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
10384        return isolate->factory()->nan_value();
10385      }
10386    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
10387      // The maximal/minimal smi has 10 digits. If the string has less digits
10388      // we know it will fit into the smi-data type.
10389      int d = ParseDecimalInteger(data, start_pos, len);
10390      if (minus) {
10391        if (d == 0) return isolate->factory()->minus_zero_value();
10392        d = -d;
10393      } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
10394                 (len == 1 || data[0] != '0')) {
10395        // String hash is not calculated yet but all the data are present.
10396        // Update the hash field to speed up sequential convertions.
10397        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
10398#ifdef DEBUG
10399        subject->Hash();  // Force hash calculation.
10400        DCHECK_EQ(static_cast<int>(subject->hash_field()),
10401                  static_cast<int>(hash));
10402#endif
10403        subject->set_hash_field(hash);
10404      }
10405      return handle(Smi::FromInt(d), isolate);
10406    }
10407  }
10408
10409  // Slower case.
10410  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
10411  return isolate->factory()->NewNumber(
10412      StringToDouble(isolate->unicode_cache(), subject, flags));
10413}
10414
10415
10416String::FlatContent String::GetFlatContent() {
10417  DCHECK(!AllowHeapAllocation::IsAllowed());
10418  int length = this->length();
10419  StringShape shape(this);
10420  String* string = this;
10421  int offset = 0;
10422  if (shape.representation_tag() == kConsStringTag) {
10423    ConsString* cons = ConsString::cast(string);
10424    if (cons->second()->length() != 0) {
10425      return FlatContent();
10426    }
10427    string = cons->first();
10428    shape = StringShape(string);
10429  }
10430  if (shape.representation_tag() == kSlicedStringTag) {
10431    SlicedString* slice = SlicedString::cast(string);
10432    offset = slice->offset();
10433    string = slice->parent();
10434    shape = StringShape(string);
10435    DCHECK(shape.representation_tag() != kConsStringTag &&
10436           shape.representation_tag() != kSlicedStringTag);
10437  }
10438  if (shape.encoding_tag() == kOneByteStringTag) {
10439    const uint8_t* start;
10440    if (shape.representation_tag() == kSeqStringTag) {
10441      start = SeqOneByteString::cast(string)->GetChars();
10442    } else {
10443      start = ExternalOneByteString::cast(string)->GetChars();
10444    }
10445    return FlatContent(start + offset, length);
10446  } else {
10447    DCHECK(shape.encoding_tag() == kTwoByteStringTag);
10448    const uc16* start;
10449    if (shape.representation_tag() == kSeqStringTag) {
10450      start = SeqTwoByteString::cast(string)->GetChars();
10451    } else {
10452      start = ExternalTwoByteString::cast(string)->GetChars();
10453    }
10454    return FlatContent(start + offset, length);
10455  }
10456}
10457
10458
10459base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
10460                                                RobustnessFlag robust_flag,
10461                                                int offset, int length,
10462                                                int* length_return) {
10463  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
10464    return base::SmartArrayPointer<char>(NULL);
10465  }
10466  // Negative length means the to the end of the string.
10467  if (length < 0) length = kMaxInt - offset;
10468
10469  // Compute the size of the UTF-8 string. Start at the specified offset.
10470  StringCharacterStream stream(this, offset);
10471  int character_position = offset;
10472  int utf8_bytes = 0;
10473  int last = unibrow::Utf16::kNoPreviousCharacter;
10474  while (stream.HasMore() && character_position++ < offset + length) {
10475    uint16_t character = stream.GetNext();
10476    utf8_bytes += unibrow::Utf8::Length(character, last);
10477    last = character;
10478  }
10479
10480  if (length_return) {
10481    *length_return = utf8_bytes;
10482  }
10483
10484  char* result = NewArray<char>(utf8_bytes + 1);
10485
10486  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
10487  stream.Reset(this, offset);
10488  character_position = offset;
10489  int utf8_byte_position = 0;
10490  last = unibrow::Utf16::kNoPreviousCharacter;
10491  while (stream.HasMore() && character_position++ < offset + length) {
10492    uint16_t character = stream.GetNext();
10493    if (allow_nulls == DISALLOW_NULLS && character == 0) {
10494      character = ' ';
10495    }
10496    utf8_byte_position +=
10497        unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
10498    last = character;
10499  }
10500  result[utf8_byte_position] = 0;
10501  return base::SmartArrayPointer<char>(result);
10502}
10503
10504
10505base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
10506                                                RobustnessFlag robust_flag,
10507                                                int* length_return) {
10508  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
10509}
10510
10511
10512const uc16* String::GetTwoByteData(unsigned start) {
10513  DCHECK(!IsOneByteRepresentationUnderneath());
10514  switch (StringShape(this).representation_tag()) {
10515    case kSeqStringTag:
10516      return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
10517    case kExternalStringTag:
10518      return ExternalTwoByteString::cast(this)->
10519        ExternalTwoByteStringGetData(start);
10520    case kSlicedStringTag: {
10521      SlicedString* slice = SlicedString::cast(this);
10522      return slice->parent()->GetTwoByteData(start + slice->offset());
10523    }
10524    case kConsStringTag:
10525      UNREACHABLE();
10526      return NULL;
10527  }
10528  UNREACHABLE();
10529  return NULL;
10530}
10531
10532
10533const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
10534  return reinterpret_cast<uc16*>(
10535      reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
10536}
10537
10538
10539void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
10540  Relocatable* current = isolate->relocatable_top();
10541  while (current != NULL) {
10542    current->PostGarbageCollection();
10543    current = current->prev_;
10544  }
10545}
10546
10547
10548// Reserve space for statics needing saving and restoring.
10549int Relocatable::ArchiveSpacePerThread() {
10550  return sizeof(Relocatable*);  // NOLINT
10551}
10552
10553
10554// Archive statics that are thread-local.
10555char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
10556  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
10557  isolate->set_relocatable_top(NULL);
10558  return to + ArchiveSpacePerThread();
10559}
10560
10561
10562// Restore statics that are thread-local.
10563char* Relocatable::RestoreState(Isolate* isolate, char* from) {
10564  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
10565  return from + ArchiveSpacePerThread();
10566}
10567
10568
10569char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
10570  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
10571  Iterate(v, top);
10572  return thread_storage + ArchiveSpacePerThread();
10573}
10574
10575
10576void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
10577  Iterate(v, isolate->relocatable_top());
10578}
10579
10580
10581void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
10582  Relocatable* current = top;
10583  while (current != NULL) {
10584    current->IterateInstance(v);
10585    current = current->prev_;
10586  }
10587}
10588
10589
10590FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
10591    : Relocatable(isolate),
10592      str_(str.location()),
10593      length_(str->length()) {
10594  PostGarbageCollection();
10595}
10596
10597
10598FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
10599    : Relocatable(isolate),
10600      str_(0),
10601      is_one_byte_(true),
10602      length_(input.length()),
10603      start_(input.start()) {}
10604
10605
10606void FlatStringReader::PostGarbageCollection() {
10607  if (str_ == NULL) return;
10608  Handle<String> str(str_);
10609  DCHECK(str->IsFlat());
10610  DisallowHeapAllocation no_gc;
10611  // This does not actually prevent the vector from being relocated later.
10612  String::FlatContent content = str->GetFlatContent();
10613  DCHECK(content.IsFlat());
10614  is_one_byte_ = content.IsOneByte();
10615  if (is_one_byte_) {
10616    start_ = content.ToOneByteVector().start();
10617  } else {
10618    start_ = content.ToUC16Vector().start();
10619  }
10620}
10621
10622
10623void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
10624  DCHECK(cons_string != NULL);
10625  root_ = cons_string;
10626  consumed_ = offset;
10627  // Force stack blown condition to trigger restart.
10628  depth_ = 1;
10629  maximum_depth_ = kStackSize + depth_;
10630  DCHECK(StackBlown());
10631}
10632
10633
10634String* ConsStringIterator::Continue(int* offset_out) {
10635  DCHECK(depth_ != 0);
10636  DCHECK_EQ(0, *offset_out);
10637  bool blew_stack = StackBlown();
10638  String* string = NULL;
10639  // Get the next leaf if there is one.
10640  if (!blew_stack) string = NextLeaf(&blew_stack);
10641  // Restart search from root.
10642  if (blew_stack) {
10643    DCHECK(string == NULL);
10644    string = Search(offset_out);
10645  }
10646  // Ensure future calls return null immediately.
10647  if (string == NULL) Reset(NULL);
10648  return string;
10649}
10650
10651
10652String* ConsStringIterator::Search(int* offset_out) {
10653  ConsString* cons_string = root_;
10654  // Reset the stack, pushing the root string.
10655  depth_ = 1;
10656  maximum_depth_ = 1;
10657  frames_[0] = cons_string;
10658  const int consumed = consumed_;
10659  int offset = 0;
10660  while (true) {
10661    // Loop until the string is found which contains the target offset.
10662    String* string = cons_string->first();
10663    int length = string->length();
10664    int32_t type;
10665    if (consumed < offset + length) {
10666      // Target offset is in the left branch.
10667      // Keep going if we're still in a ConString.
10668      type = string->map()->instance_type();
10669      if ((type & kStringRepresentationMask) == kConsStringTag) {
10670        cons_string = ConsString::cast(string);
10671        PushLeft(cons_string);
10672        continue;
10673      }
10674      // Tell the stack we're done descending.
10675      AdjustMaximumDepth();
10676    } else {
10677      // Descend right.
10678      // Update progress through the string.
10679      offset += length;
10680      // Keep going if we're still in a ConString.
10681      string = cons_string->second();
10682      type = string->map()->instance_type();
10683      if ((type & kStringRepresentationMask) == kConsStringTag) {
10684        cons_string = ConsString::cast(string);
10685        PushRight(cons_string);
10686        continue;
10687      }
10688      // Need this to be updated for the current string.
10689      length = string->length();
10690      // Account for the possibility of an empty right leaf.
10691      // This happens only if we have asked for an offset outside the string.
10692      if (length == 0) {
10693        // Reset so future operations will return null immediately.
10694        Reset(NULL);
10695        return NULL;
10696      }
10697      // Tell the stack we're done descending.
10698      AdjustMaximumDepth();
10699      // Pop stack so next iteration is in correct place.
10700      Pop();
10701    }
10702    DCHECK(length != 0);
10703    // Adjust return values and exit.
10704    consumed_ = offset + length;
10705    *offset_out = consumed - offset;
10706    return string;
10707  }
10708  UNREACHABLE();
10709  return NULL;
10710}
10711
10712
10713String* ConsStringIterator::NextLeaf(bool* blew_stack) {
10714  while (true) {
10715    // Tree traversal complete.
10716    if (depth_ == 0) {
10717      *blew_stack = false;
10718      return NULL;
10719    }
10720    // We've lost track of higher nodes.
10721    if (StackBlown()) {
10722      *blew_stack = true;
10723      return NULL;
10724    }
10725    // Go right.
10726    ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
10727    String* string = cons_string->second();
10728    int32_t type = string->map()->instance_type();
10729    if ((type & kStringRepresentationMask) != kConsStringTag) {
10730      // Pop stack so next iteration is in correct place.
10731      Pop();
10732      int length = string->length();
10733      // Could be a flattened ConsString.
10734      if (length == 0) continue;
10735      consumed_ += length;
10736      return string;
10737    }
10738    cons_string = ConsString::cast(string);
10739    PushRight(cons_string);
10740    // Need to traverse all the way left.
10741    while (true) {
10742      // Continue left.
10743      string = cons_string->first();
10744      type = string->map()->instance_type();
10745      if ((type & kStringRepresentationMask) != kConsStringTag) {
10746        AdjustMaximumDepth();
10747        int length = string->length();
10748        DCHECK(length != 0);
10749        consumed_ += length;
10750        return string;
10751      }
10752      cons_string = ConsString::cast(string);
10753      PushLeft(cons_string);
10754    }
10755  }
10756  UNREACHABLE();
10757  return NULL;
10758}
10759
10760
10761uint16_t ConsString::ConsStringGet(int index) {
10762  DCHECK(index >= 0 && index < this->length());
10763
10764  // Check for a flattened cons string
10765  if (second()->length() == 0) {
10766    String* left = first();
10767    return left->Get(index);
10768  }
10769
10770  String* string = String::cast(this);
10771
10772  while (true) {
10773    if (StringShape(string).IsCons()) {
10774      ConsString* cons_string = ConsString::cast(string);
10775      String* left = cons_string->first();
10776      if (left->length() > index) {
10777        string = left;
10778      } else {
10779        index -= left->length();
10780        string = cons_string->second();
10781      }
10782    } else {
10783      return string->Get(index);
10784    }
10785  }
10786
10787  UNREACHABLE();
10788  return 0;
10789}
10790
10791
10792uint16_t SlicedString::SlicedStringGet(int index) {
10793  return parent()->Get(offset() + index);
10794}
10795
10796
10797template <typename sinkchar>
10798void String::WriteToFlat(String* src,
10799                         sinkchar* sink,
10800                         int f,
10801                         int t) {
10802  String* source = src;
10803  int from = f;
10804  int to = t;
10805  while (true) {
10806    DCHECK(0 <= from && from <= to && to <= source->length());
10807    switch (StringShape(source).full_representation_tag()) {
10808      case kOneByteStringTag | kExternalStringTag: {
10809        CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
10810                  to - from);
10811        return;
10812      }
10813      case kTwoByteStringTag | kExternalStringTag: {
10814        const uc16* data =
10815            ExternalTwoByteString::cast(source)->GetChars();
10816        CopyChars(sink,
10817                  data + from,
10818                  to - from);
10819        return;
10820      }
10821      case kOneByteStringTag | kSeqStringTag: {
10822        CopyChars(sink,
10823                  SeqOneByteString::cast(source)->GetChars() + from,
10824                  to - from);
10825        return;
10826      }
10827      case kTwoByteStringTag | kSeqStringTag: {
10828        CopyChars(sink,
10829                  SeqTwoByteString::cast(source)->GetChars() + from,
10830                  to - from);
10831        return;
10832      }
10833      case kOneByteStringTag | kConsStringTag:
10834      case kTwoByteStringTag | kConsStringTag: {
10835        ConsString* cons_string = ConsString::cast(source);
10836        String* first = cons_string->first();
10837        int boundary = first->length();
10838        if (to - boundary >= boundary - from) {
10839          // Right hand side is longer.  Recurse over left.
10840          if (from < boundary) {
10841            WriteToFlat(first, sink, from, boundary);
10842            if (from == 0 && cons_string->second() == first) {
10843              CopyChars(sink + boundary, sink, boundary);
10844              return;
10845            }
10846            sink += boundary - from;
10847            from = 0;
10848          } else {
10849            from -= boundary;
10850          }
10851          to -= boundary;
10852          source = cons_string->second();
10853        } else {
10854          // Left hand side is longer.  Recurse over right.
10855          if (to > boundary) {
10856            String* second = cons_string->second();
10857            // When repeatedly appending to a string, we get a cons string that
10858            // is unbalanced to the left, a list, essentially.  We inline the
10859            // common case of sequential one-byte right child.
10860            if (to - boundary == 1) {
10861              sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
10862            } else if (second->IsSeqOneByteString()) {
10863              CopyChars(sink + boundary - from,
10864                        SeqOneByteString::cast(second)->GetChars(),
10865                        to - boundary);
10866            } else {
10867              WriteToFlat(second,
10868                          sink + boundary - from,
10869                          0,
10870                          to - boundary);
10871            }
10872            to = boundary;
10873          }
10874          source = first;
10875        }
10876        break;
10877      }
10878      case kOneByteStringTag | kSlicedStringTag:
10879      case kTwoByteStringTag | kSlicedStringTag: {
10880        SlicedString* slice = SlicedString::cast(source);
10881        unsigned offset = slice->offset();
10882        WriteToFlat(slice->parent(), sink, from + offset, to + offset);
10883        return;
10884      }
10885    }
10886  }
10887}
10888
10889
10890
10891template <typename SourceChar>
10892static void CalculateLineEndsImpl(Isolate* isolate,
10893                                  List<int>* line_ends,
10894                                  Vector<const SourceChar> src,
10895                                  bool include_ending_line) {
10896  const int src_len = src.length();
10897  UnicodeCache* cache = isolate->unicode_cache();
10898  for (int i = 0; i < src_len - 1; i++) {
10899    SourceChar current = src[i];
10900    SourceChar next = src[i + 1];
10901    if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
10902  }
10903
10904  if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
10905    line_ends->Add(src_len - 1);
10906  }
10907  if (include_ending_line) {
10908    // Include one character beyond the end of script. The rewriter uses that
10909    // position for the implicit return statement.
10910    line_ends->Add(src_len);
10911  }
10912}
10913
10914
10915Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
10916                                             bool include_ending_line) {
10917  src = Flatten(src);
10918  // Rough estimate of line count based on a roughly estimated average
10919  // length of (unpacked) code.
10920  int line_count_estimate = src->length() >> 4;
10921  List<int> line_ends(line_count_estimate);
10922  Isolate* isolate = src->GetIsolate();
10923  { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
10924    // Dispatch on type of strings.
10925    String::FlatContent content = src->GetFlatContent();
10926    DCHECK(content.IsFlat());
10927    if (content.IsOneByte()) {
10928      CalculateLineEndsImpl(isolate,
10929                            &line_ends,
10930                            content.ToOneByteVector(),
10931                            include_ending_line);
10932    } else {
10933      CalculateLineEndsImpl(isolate,
10934                            &line_ends,
10935                            content.ToUC16Vector(),
10936                            include_ending_line);
10937    }
10938  }
10939  int line_count = line_ends.length();
10940  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
10941  for (int i = 0; i < line_count; i++) {
10942    array->set(i, Smi::FromInt(line_ends[i]));
10943  }
10944  return array;
10945}
10946
10947
10948// Compares the contents of two strings by reading and comparing
10949// int-sized blocks of characters.
10950template <typename Char>
10951static inline bool CompareRawStringContents(const Char* const a,
10952                                            const Char* const b,
10953                                            int length) {
10954  return CompareChars(a, b, length) == 0;
10955}
10956
10957
10958template<typename Chars1, typename Chars2>
10959class RawStringComparator : public AllStatic {
10960 public:
10961  static inline bool compare(const Chars1* a, const Chars2* b, int len) {
10962    DCHECK(sizeof(Chars1) != sizeof(Chars2));
10963    for (int i = 0; i < len; i++) {
10964      if (a[i] != b[i]) {
10965        return false;
10966      }
10967    }
10968    return true;
10969  }
10970};
10971
10972
10973template<>
10974class RawStringComparator<uint16_t, uint16_t> {
10975 public:
10976  static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
10977    return CompareRawStringContents(a, b, len);
10978  }
10979};
10980
10981
10982template<>
10983class RawStringComparator<uint8_t, uint8_t> {
10984 public:
10985  static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
10986    return CompareRawStringContents(a, b, len);
10987  }
10988};
10989
10990
10991class StringComparator {
10992  class State {
10993   public:
10994    State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
10995
10996    void Init(String* string) {
10997      ConsString* cons_string = String::VisitFlat(this, string);
10998      iter_.Reset(cons_string);
10999      if (cons_string != NULL) {
11000        int offset;
11001        string = iter_.Next(&offset);
11002        String::VisitFlat(this, string, offset);
11003      }
11004    }
11005
11006    inline void VisitOneByteString(const uint8_t* chars, int length) {
11007      is_one_byte_ = true;
11008      buffer8_ = chars;
11009      length_ = length;
11010    }
11011
11012    inline void VisitTwoByteString(const uint16_t* chars, int length) {
11013      is_one_byte_ = false;
11014      buffer16_ = chars;
11015      length_ = length;
11016    }
11017
11018    void Advance(int consumed) {
11019      DCHECK(consumed <= length_);
11020      // Still in buffer.
11021      if (length_ != consumed) {
11022        if (is_one_byte_) {
11023          buffer8_ += consumed;
11024        } else {
11025          buffer16_ += consumed;
11026        }
11027        length_ -= consumed;
11028        return;
11029      }
11030      // Advance state.
11031      int offset;
11032      String* next = iter_.Next(&offset);
11033      DCHECK_EQ(0, offset);
11034      DCHECK(next != NULL);
11035      String::VisitFlat(this, next);
11036    }
11037
11038    ConsStringIterator iter_;
11039    bool is_one_byte_;
11040    int length_;
11041    union {
11042      const uint8_t* buffer8_;
11043      const uint16_t* buffer16_;
11044    };
11045
11046   private:
11047    DISALLOW_COPY_AND_ASSIGN(State);
11048  };
11049
11050 public:
11051  inline StringComparator() {}
11052
11053  template<typename Chars1, typename Chars2>
11054  static inline bool Equals(State* state_1, State* state_2, int to_check) {
11055    const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
11056    const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
11057    return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
11058  }
11059
11060  bool Equals(String* string_1, String* string_2) {
11061    int length = string_1->length();
11062    state_1_.Init(string_1);
11063    state_2_.Init(string_2);
11064    while (true) {
11065      int to_check = Min(state_1_.length_, state_2_.length_);
11066      DCHECK(to_check > 0 && to_check <= length);
11067      bool is_equal;
11068      if (state_1_.is_one_byte_) {
11069        if (state_2_.is_one_byte_) {
11070          is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
11071        } else {
11072          is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
11073        }
11074      } else {
11075        if (state_2_.is_one_byte_) {
11076          is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
11077        } else {
11078          is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
11079        }
11080      }
11081      // Looping done.
11082      if (!is_equal) return false;
11083      length -= to_check;
11084      // Exit condition. Strings are equal.
11085      if (length == 0) return true;
11086      state_1_.Advance(to_check);
11087      state_2_.Advance(to_check);
11088    }
11089  }
11090
11091 private:
11092  State state_1_;
11093  State state_2_;
11094
11095  DISALLOW_COPY_AND_ASSIGN(StringComparator);
11096};
11097
11098
11099bool String::SlowEquals(String* other) {
11100  DisallowHeapAllocation no_gc;
11101  // Fast check: negative check with lengths.
11102  int len = length();
11103  if (len != other->length()) return false;
11104  if (len == 0) return true;
11105
11106  // Fast check: if hash code is computed for both strings
11107  // a fast negative check can be performed.
11108  if (HasHashCode() && other->HasHashCode()) {
11109#ifdef ENABLE_SLOW_DCHECKS
11110    if (FLAG_enable_slow_asserts) {
11111      if (Hash() != other->Hash()) {
11112        bool found_difference = false;
11113        for (int i = 0; i < len; i++) {
11114          if (Get(i) != other->Get(i)) {
11115            found_difference = true;
11116            break;
11117          }
11118        }
11119        DCHECK(found_difference);
11120      }
11121    }
11122#endif
11123    if (Hash() != other->Hash()) return false;
11124  }
11125
11126  // We know the strings are both non-empty. Compare the first chars
11127  // before we try to flatten the strings.
11128  if (this->Get(0) != other->Get(0)) return false;
11129
11130  if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
11131    const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
11132    const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
11133    return CompareRawStringContents(str1, str2, len);
11134  }
11135
11136  StringComparator comparator;
11137  return comparator.Equals(this, other);
11138}
11139
11140
11141bool String::SlowEquals(Handle<String> one, Handle<String> two) {
11142  // Fast check: negative check with lengths.
11143  int one_length = one->length();
11144  if (one_length != two->length()) return false;
11145  if (one_length == 0) return true;
11146
11147  // Fast check: if hash code is computed for both strings
11148  // a fast negative check can be performed.
11149  if (one->HasHashCode() && two->HasHashCode()) {
11150#ifdef ENABLE_SLOW_DCHECKS
11151    if (FLAG_enable_slow_asserts) {
11152      if (one->Hash() != two->Hash()) {
11153        bool found_difference = false;
11154        for (int i = 0; i < one_length; i++) {
11155          if (one->Get(i) != two->Get(i)) {
11156            found_difference = true;
11157            break;
11158          }
11159        }
11160        DCHECK(found_difference);
11161      }
11162    }
11163#endif
11164    if (one->Hash() != two->Hash()) return false;
11165  }
11166
11167  // We know the strings are both non-empty. Compare the first chars
11168  // before we try to flatten the strings.
11169  if (one->Get(0) != two->Get(0)) return false;
11170
11171  one = String::Flatten(one);
11172  two = String::Flatten(two);
11173
11174  DisallowHeapAllocation no_gc;
11175  String::FlatContent flat1 = one->GetFlatContent();
11176  String::FlatContent flat2 = two->GetFlatContent();
11177
11178  if (flat1.IsOneByte() && flat2.IsOneByte()) {
11179      return CompareRawStringContents(flat1.ToOneByteVector().start(),
11180                                      flat2.ToOneByteVector().start(),
11181                                      one_length);
11182  } else {
11183    for (int i = 0; i < one_length; i++) {
11184      if (flat1.Get(i) != flat2.Get(i)) return false;
11185    }
11186    return true;
11187  }
11188}
11189
11190
11191// static
11192ComparisonResult String::Compare(Handle<String> x, Handle<String> y) {
11193  // A few fast case tests before we flatten.
11194  if (x.is_identical_to(y)) {
11195    return ComparisonResult::kEqual;
11196  } else if (y->length() == 0) {
11197    return x->length() == 0 ? ComparisonResult::kEqual
11198                            : ComparisonResult::kGreaterThan;
11199  } else if (x->length() == 0) {
11200    return ComparisonResult::kLessThan;
11201  }
11202
11203  int const d = x->Get(0) - y->Get(0);
11204  if (d < 0) {
11205    return ComparisonResult::kLessThan;
11206  } else if (d > 0) {
11207    return ComparisonResult::kGreaterThan;
11208  }
11209
11210  // Slow case.
11211  x = String::Flatten(x);
11212  y = String::Flatten(y);
11213
11214  DisallowHeapAllocation no_gc;
11215  ComparisonResult result = ComparisonResult::kEqual;
11216  int prefix_length = x->length();
11217  if (y->length() < prefix_length) {
11218    prefix_length = y->length();
11219    result = ComparisonResult::kGreaterThan;
11220  } else if (y->length() > prefix_length) {
11221    result = ComparisonResult::kLessThan;
11222  }
11223  int r;
11224  String::FlatContent x_content = x->GetFlatContent();
11225  String::FlatContent y_content = y->GetFlatContent();
11226  if (x_content.IsOneByte()) {
11227    Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
11228    if (y_content.IsOneByte()) {
11229      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11230      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11231    } else {
11232      Vector<const uc16> y_chars = y_content.ToUC16Vector();
11233      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11234    }
11235  } else {
11236    Vector<const uc16> x_chars = x_content.ToUC16Vector();
11237    if (y_content.IsOneByte()) {
11238      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11239      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11240    } else {
11241      Vector<const uc16> y_chars = y_content.ToUC16Vector();
11242      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11243    }
11244  }
11245  if (r < 0) {
11246    result = ComparisonResult::kLessThan;
11247  } else if (r > 0) {
11248    result = ComparisonResult::kGreaterThan;
11249  }
11250  return result;
11251}
11252
11253
11254bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
11255  int slen = length();
11256  // Can't check exact length equality, but we can check bounds.
11257  int str_len = str.length();
11258  if (!allow_prefix_match &&
11259      (str_len < slen ||
11260          str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
11261    return false;
11262  }
11263  int i;
11264  size_t remaining_in_str = static_cast<size_t>(str_len);
11265  const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
11266  for (i = 0; i < slen && remaining_in_str > 0; i++) {
11267    size_t cursor = 0;
11268    uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
11269    DCHECK(cursor > 0 && cursor <= remaining_in_str);
11270    if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
11271      if (i > slen - 1) return false;
11272      if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
11273      if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
11274    } else {
11275      if (Get(i) != r) return false;
11276    }
11277    utf8_data += cursor;
11278    remaining_in_str -= cursor;
11279  }
11280  return (allow_prefix_match || i == slen) && remaining_in_str == 0;
11281}
11282
11283
11284bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
11285  int slen = length();
11286  if (str.length() != slen) return false;
11287  DisallowHeapAllocation no_gc;
11288  FlatContent content = GetFlatContent();
11289  if (content.IsOneByte()) {
11290    return CompareChars(content.ToOneByteVector().start(),
11291                        str.start(), slen) == 0;
11292  }
11293  for (int i = 0; i < slen; i++) {
11294    if (Get(i) != static_cast<uint16_t>(str[i])) return false;
11295  }
11296  return true;
11297}
11298
11299
11300bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
11301  int slen = length();
11302  if (str.length() != slen) return false;
11303  DisallowHeapAllocation no_gc;
11304  FlatContent content = GetFlatContent();
11305  if (content.IsTwoByte()) {
11306    return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
11307  }
11308  for (int i = 0; i < slen; i++) {
11309    if (Get(i) != str[i]) return false;
11310  }
11311  return true;
11312}
11313
11314
11315uint32_t String::ComputeAndSetHash() {
11316  // Should only be called if hash code has not yet been computed.
11317  DCHECK(!HasHashCode());
11318
11319  // Store the hash code in the object.
11320  uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
11321  set_hash_field(field);
11322
11323  // Check the hash code is there.
11324  DCHECK(HasHashCode());
11325  uint32_t result = field >> kHashShift;
11326  DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
11327  return result;
11328}
11329
11330
11331bool String::ComputeArrayIndex(uint32_t* index) {
11332  int length = this->length();
11333  if (length == 0 || length > kMaxArrayIndexSize) return false;
11334  StringCharacterStream stream(this);
11335  return StringToArrayIndex(&stream, index);
11336}
11337
11338
11339bool String::SlowAsArrayIndex(uint32_t* index) {
11340  if (length() <= kMaxCachedArrayIndexLength) {
11341    Hash();  // force computation of hash code
11342    uint32_t field = hash_field();
11343    if ((field & kIsNotArrayIndexMask) != 0) return false;
11344    // Isolate the array index form the full hash field.
11345    *index = ArrayIndexValueBits::decode(field);
11346    return true;
11347  } else {
11348    return ComputeArrayIndex(index);
11349  }
11350}
11351
11352
11353Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
11354  int new_size, old_size;
11355  int old_length = string->length();
11356  if (old_length <= new_length) return string;
11357
11358  if (string->IsSeqOneByteString()) {
11359    old_size = SeqOneByteString::SizeFor(old_length);
11360    new_size = SeqOneByteString::SizeFor(new_length);
11361  } else {
11362    DCHECK(string->IsSeqTwoByteString());
11363    old_size = SeqTwoByteString::SizeFor(old_length);
11364    new_size = SeqTwoByteString::SizeFor(new_length);
11365  }
11366
11367  int delta = old_size - new_size;
11368
11369  Address start_of_string = string->address();
11370  DCHECK_OBJECT_ALIGNED(start_of_string);
11371  DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
11372
11373  Heap* heap = string->GetHeap();
11374  // Sizes are pointer size aligned, so that we can use filler objects
11375  // that are a multiple of pointer size.
11376  heap->CreateFillerObjectAt(start_of_string + new_size, delta,
11377                             ClearRecordedSlots::kNo);
11378  heap->AdjustLiveBytes(*string, -delta, Heap::CONCURRENT_TO_SWEEPER);
11379
11380  // We are storing the new length using release store after creating a filler
11381  // for the left-over space to avoid races with the sweeper thread.
11382  string->synchronized_set_length(new_length);
11383
11384  if (new_length == 0) return heap->isolate()->factory()->empty_string();
11385  return string;
11386}
11387
11388
11389uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
11390  // For array indexes mix the length into the hash as an array index could
11391  // be zero.
11392  DCHECK(length > 0);
11393  DCHECK(length <= String::kMaxArrayIndexSize);
11394  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
11395         (1 << String::kArrayIndexValueBits));
11396
11397  value <<= String::ArrayIndexValueBits::kShift;
11398  value |= length << String::ArrayIndexLengthBits::kShift;
11399
11400  DCHECK((value & String::kIsNotArrayIndexMask) == 0);
11401  DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
11402            (value & String::kContainsCachedArrayIndexMask) == 0);
11403  return value;
11404}
11405
11406
11407uint32_t StringHasher::GetHashField() {
11408  if (length_ <= String::kMaxHashCalcLength) {
11409    if (is_array_index_) {
11410      return MakeArrayIndexHash(array_index_, length_);
11411    }
11412    return (GetHashCore(raw_running_hash_) << String::kHashShift) |
11413           String::kIsNotArrayIndexMask;
11414  } else {
11415    return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
11416  }
11417}
11418
11419
11420uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
11421                                       uint32_t seed,
11422                                       int* utf16_length_out) {
11423  int vector_length = chars.length();
11424  // Handle some edge cases
11425  if (vector_length <= 1) {
11426    DCHECK(vector_length == 0 ||
11427           static_cast<uint8_t>(chars.start()[0]) <=
11428               unibrow::Utf8::kMaxOneByteChar);
11429    *utf16_length_out = vector_length;
11430    return HashSequentialString(chars.start(), vector_length, seed);
11431  }
11432  // Start with a fake length which won't affect computation.
11433  // It will be updated later.
11434  StringHasher hasher(String::kMaxArrayIndexSize, seed);
11435  size_t remaining = static_cast<size_t>(vector_length);
11436  const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
11437  int utf16_length = 0;
11438  bool is_index = true;
11439  DCHECK(hasher.is_array_index_);
11440  while (remaining > 0) {
11441    size_t consumed = 0;
11442    uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
11443    DCHECK(consumed > 0 && consumed <= remaining);
11444    stream += consumed;
11445    remaining -= consumed;
11446    bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
11447    utf16_length += is_two_characters ? 2 : 1;
11448    // No need to keep hashing. But we do need to calculate utf16_length.
11449    if (utf16_length > String::kMaxHashCalcLength) continue;
11450    if (is_two_characters) {
11451      uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
11452      uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
11453      hasher.AddCharacter(c1);
11454      hasher.AddCharacter(c2);
11455      if (is_index) is_index = hasher.UpdateIndex(c1);
11456      if (is_index) is_index = hasher.UpdateIndex(c2);
11457    } else {
11458      hasher.AddCharacter(c);
11459      if (is_index) is_index = hasher.UpdateIndex(c);
11460    }
11461  }
11462  *utf16_length_out = static_cast<int>(utf16_length);
11463  // Must set length here so that hash computation is correct.
11464  hasher.length_ = utf16_length;
11465  return hasher.GetHashField();
11466}
11467
11468
11469void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
11470  // Run small ConsStrings through ConsStringIterator.
11471  if (cons_string->length() < 64) {
11472    ConsStringIterator iter(cons_string);
11473    int offset;
11474    String* string;
11475    while (nullptr != (string = iter.Next(&offset))) {
11476      DCHECK_EQ(0, offset);
11477      String::VisitFlat(this, string, 0);
11478    }
11479    return;
11480  }
11481  // Slow case.
11482  const int max_length = String::kMaxHashCalcLength;
11483  int length = std::min(cons_string->length(), max_length);
11484  if (cons_string->HasOnlyOneByteChars()) {
11485    uint8_t* buffer = new uint8_t[length];
11486    String::WriteToFlat(cons_string, buffer, 0, length);
11487    AddCharacters(buffer, length);
11488    delete[] buffer;
11489  } else {
11490    uint16_t* buffer = new uint16_t[length];
11491    String::WriteToFlat(cons_string, buffer, 0, length);
11492    AddCharacters(buffer, length);
11493    delete[] buffer;
11494  }
11495}
11496
11497
11498void String::PrintOn(FILE* file) {
11499  int length = this->length();
11500  for (int i = 0; i < length; i++) {
11501    PrintF(file, "%c", Get(i));
11502  }
11503}
11504
11505
11506int Map::Hash() {
11507  // For performance reasons we only hash the 3 most variable fields of a map:
11508  // constructor, prototype and bit_field2. For predictability reasons we
11509  // use objects' offsets in respective pages for hashing instead of raw
11510  // addresses.
11511
11512  // Shift away the tag.
11513  int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
11514
11515  // XOR-ing the prototype and constructor directly yields too many zero bits
11516  // when the two pointers are close (which is fairly common).
11517  // To avoid this we shift the prototype bits relatively to the constructor.
11518  hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
11519
11520  return hash ^ (hash >> 16) ^ bit_field2();
11521}
11522
11523
11524namespace {
11525
11526bool CheckEquivalent(Map* first, Map* second) {
11527  return first->GetConstructor() == second->GetConstructor() &&
11528         first->prototype() == second->prototype() &&
11529         first->instance_type() == second->instance_type() &&
11530         first->bit_field() == second->bit_field() &&
11531         first->is_extensible() == second->is_extensible() &&
11532         first->new_target_is_base() == second->new_target_is_base() &&
11533         first->has_hidden_prototype() == second->has_hidden_prototype();
11534}
11535
11536}  // namespace
11537
11538
11539bool Map::EquivalentToForTransition(Map* other) {
11540  if (!CheckEquivalent(this, other)) return false;
11541  if (instance_type() == JS_FUNCTION_TYPE) {
11542    // JSFunctions require more checks to ensure that sloppy function is
11543    // not equvalent to strict function.
11544    int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
11545    return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
11546                                               nof);
11547  }
11548  return true;
11549}
11550
11551
11552bool Map::EquivalentToForNormalization(Map* other,
11553                                       PropertyNormalizationMode mode) {
11554  int properties =
11555      mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
11556  return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
11557         GetInObjectProperties() == properties;
11558}
11559
11560
11561bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
11562  DisallowHeapAllocation no_gc;
11563  if (shared() == candidate) return true;
11564  if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
11565  DeoptimizationInputData* const data =
11566      DeoptimizationInputData::cast(code()->deoptimization_data());
11567  if (data->length() == 0) return false;
11568  FixedArray* const literals = data->LiteralArray();
11569  int const inlined_count = data->InlinedFunctionCount()->value();
11570  for (int i = 0; i < inlined_count; ++i) {
11571    if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
11572      return true;
11573    }
11574  }
11575  return false;
11576}
11577
11578void JSFunction::MarkForBaseline() {
11579  Isolate* isolate = GetIsolate();
11580  set_code_no_write_barrier(
11581      isolate->builtins()->builtin(Builtins::kCompileBaseline));
11582  // No write barrier required, since the builtin is part of the root set.
11583}
11584
11585void JSFunction::MarkForOptimization() {
11586  Isolate* isolate = GetIsolate();
11587  DCHECK(!IsOptimized());
11588  DCHECK(shared()->allows_lazy_compilation() ||
11589         !shared()->optimization_disabled());
11590  set_code_no_write_barrier(
11591      isolate->builtins()->builtin(Builtins::kCompileOptimized));
11592  // No write barrier required, since the builtin is part of the root set.
11593}
11594
11595
11596void JSFunction::AttemptConcurrentOptimization() {
11597  Isolate* isolate = GetIsolate();
11598  if (!isolate->concurrent_recompilation_enabled() ||
11599      isolate->bootstrapper()->IsActive()) {
11600    MarkForOptimization();
11601    return;
11602  }
11603  DCHECK(!IsInOptimizationQueue());
11604  DCHECK(!IsOptimized());
11605  DCHECK(shared()->allows_lazy_compilation() ||
11606         !shared()->optimization_disabled());
11607  DCHECK(isolate->concurrent_recompilation_enabled());
11608  if (FLAG_trace_concurrent_recompilation) {
11609    PrintF("  ** Marking ");
11610    ShortPrint();
11611    PrintF(" for concurrent recompilation.\n");
11612  }
11613  set_code_no_write_barrier(
11614      isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
11615  // No write barrier required, since the builtin is part of the root set.
11616}
11617
11618// static
11619Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals(
11620    Handle<SharedFunctionInfo> shared, Handle<Context> native_context) {
11621  Isolate* isolate = shared->GetIsolate();
11622  CodeAndLiterals result =
11623      shared->SearchOptimizedCodeMap(*native_context, BailoutId::None());
11624  if (result.literals != nullptr) {
11625    DCHECK(shared->feedback_metadata()->is_empty() ||
11626           !result.literals->feedback_vector()->is_empty());
11627    return handle(result.literals, isolate);
11628  }
11629
11630  Handle<TypeFeedbackVector> feedback_vector =
11631      TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
11632  Handle<LiteralsArray> literals = LiteralsArray::New(
11633      isolate, feedback_vector, shared->num_literals(), TENURED);
11634  Handle<Code> code;
11635  if (result.code != nullptr) {
11636    code = Handle<Code>(result.code, isolate);
11637  }
11638  AddToOptimizedCodeMap(shared, native_context, code, literals,
11639                        BailoutId::None());
11640  return literals;
11641}
11642
11643void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
11644    Handle<SharedFunctionInfo> shared, Handle<Code> code) {
11645  Isolate* isolate = shared->GetIsolate();
11646  if (isolate->serializer_enabled()) return;
11647  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
11648  // Empty code maps are unsupported.
11649  if (!shared->OptimizedCodeMapIsCleared()) {
11650    Handle<WeakCell> cell = isolate->factory()->NewWeakCell(code);
11651    // A collection may have occured and cleared the optimized code map in the
11652    // allocation above.
11653    if (!shared->OptimizedCodeMapIsCleared()) {
11654      shared->optimized_code_map()->set(kSharedCodeIndex, *cell);
11655    }
11656  }
11657}
11658
11659// static
11660void SharedFunctionInfo::AddToOptimizedCodeMap(
11661    Handle<SharedFunctionInfo> shared, Handle<Context> native_context,
11662    MaybeHandle<Code> code, Handle<LiteralsArray> literals,
11663    BailoutId osr_ast_id) {
11664  Isolate* isolate = shared->GetIsolate();
11665  if (isolate->serializer_enabled()) return;
11666  DCHECK(code.is_null() ||
11667         code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION);
11668  DCHECK(native_context->IsNativeContext());
11669  STATIC_ASSERT(kEntryLength == 4);
11670  Handle<FixedArray> new_code_map;
11671  int entry;
11672
11673  if (shared->OptimizedCodeMapIsCleared()) {
11674    new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED);
11675    new_code_map->set(kSharedCodeIndex, *isolate->factory()->empty_weak_cell(),
11676                      SKIP_WRITE_BARRIER);
11677    entry = kEntriesStart;
11678  } else {
11679    Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate);
11680    entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id);
11681    if (entry > kSharedCodeIndex) {
11682      // Just set the code and literals of the entry.
11683      if (!code.is_null()) {
11684        Handle<WeakCell> code_cell =
11685            isolate->factory()->NewWeakCell(code.ToHandleChecked());
11686        old_code_map->set(entry + kCachedCodeOffset, *code_cell);
11687      }
11688      if (literals->literals_count() == 0) {
11689        old_code_map->set(entry + kLiteralsOffset, *literals);
11690      } else {
11691        Handle<WeakCell> literals_cell =
11692            isolate->factory()->NewWeakCell(literals);
11693        old_code_map->set(entry + kLiteralsOffset, *literals_cell);
11694      }
11695      return;
11696    }
11697
11698    // Can we reuse an entry?
11699    DCHECK(entry < kEntriesStart);
11700    int length = old_code_map->length();
11701    for (int i = kEntriesStart; i < length; i += kEntryLength) {
11702      if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) {
11703        new_code_map = old_code_map;
11704        entry = i;
11705        break;
11706      }
11707    }
11708
11709    if (entry < kEntriesStart) {
11710      // Copy old optimized code map and append one new entry.
11711      new_code_map = isolate->factory()->CopyFixedArrayAndGrow(
11712          old_code_map, kEntryLength, TENURED);
11713      // TODO(mstarzinger): Temporary workaround. The allocation above might
11714      // have flushed the optimized code map and the copy we created is full of
11715      // holes. For now we just give up on adding the entry and pretend it got
11716      // flushed.
11717      if (shared->OptimizedCodeMapIsCleared()) return;
11718      entry = old_code_map->length();
11719    }
11720  }
11721
11722  Handle<WeakCell> code_cell =
11723      code.is_null() ? isolate->factory()->empty_weak_cell()
11724                     : isolate->factory()->NewWeakCell(code.ToHandleChecked());
11725  WeakCell* context_cell = native_context->self_weak_cell();
11726
11727  new_code_map->set(entry + kContextOffset, context_cell);
11728  new_code_map->set(entry + kCachedCodeOffset, *code_cell);
11729
11730  if (literals->literals_count() == 0) {
11731    new_code_map->set(entry + kLiteralsOffset, *literals);
11732  } else {
11733    Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
11734    new_code_map->set(entry + kLiteralsOffset, *literals_cell);
11735  }
11736
11737  new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt()));
11738
11739#ifdef DEBUG
11740  for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
11741    WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset));
11742    DCHECK(cell->cleared() || cell->value()->IsNativeContext());
11743    cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset));
11744    DCHECK(cell->cleared() ||
11745           (cell->value()->IsCode() &&
11746            Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
11747    Object* lits = new_code_map->get(i + kLiteralsOffset);
11748    if (lits->IsWeakCell()) {
11749      cell = WeakCell::cast(lits);
11750      DCHECK(cell->cleared() ||
11751             (cell->value()->IsLiteralsArray() &&
11752              LiteralsArray::cast(cell->value())->literals_count() > 0));
11753    } else {
11754      DCHECK(lits->IsLiteralsArray() &&
11755             LiteralsArray::cast(lits)->literals_count() == 0);
11756    }
11757    DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
11758  }
11759#endif
11760
11761  FixedArray* old_code_map = shared->optimized_code_map();
11762  if (old_code_map != *new_code_map) {
11763    shared->set_optimized_code_map(*new_code_map);
11764  }
11765}
11766
11767
11768void SharedFunctionInfo::ClearOptimizedCodeMap() {
11769  FixedArray* cleared_map = GetHeap()->cleared_optimized_code_map();
11770  set_optimized_code_map(cleared_map, SKIP_WRITE_BARRIER);
11771}
11772
11773
11774void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
11775                                                   const char* reason) {
11776  DisallowHeapAllocation no_gc;
11777  if (OptimizedCodeMapIsCleared()) return;
11778
11779  Heap* heap = GetHeap();
11780  FixedArray* code_map = optimized_code_map();
11781  int dst = kEntriesStart;
11782  int length = code_map->length();
11783  for (int src = kEntriesStart; src < length; src += kEntryLength) {
11784    DCHECK(WeakCell::cast(code_map->get(src))->cleared() ||
11785           WeakCell::cast(code_map->get(src))->value()->IsNativeContext());
11786    if (WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() ==
11787        optimized_code) {
11788      BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
11789      if (FLAG_trace_opt) {
11790        PrintF("[evicting entry from optimizing code map (%s) for ", reason);
11791        ShortPrint();
11792        if (osr.IsNone()) {
11793          PrintF("]\n");
11794        } else {
11795          PrintF(" (osr ast id %d)]\n", osr.ToInt());
11796        }
11797      }
11798      if (!osr.IsNone()) {
11799        // Evict the src entry by not copying it to the dst entry.
11800        continue;
11801      }
11802      // In case of non-OSR entry just clear the code in order to proceed
11803      // sharing literals.
11804      code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(),
11805                    SKIP_WRITE_BARRIER);
11806    }
11807
11808    // Keep the src entry by copying it to the dst entry.
11809    if (dst != src) {
11810      code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset));
11811      code_map->set(dst + kCachedCodeOffset,
11812                    code_map->get(src + kCachedCodeOffset));
11813      code_map->set(dst + kLiteralsOffset,
11814                    code_map->get(src + kLiteralsOffset));
11815      code_map->set(dst + kOsrAstIdOffset,
11816                    code_map->get(src + kOsrAstIdOffset));
11817    }
11818    dst += kEntryLength;
11819  }
11820  if (WeakCell::cast(code_map->get(kSharedCodeIndex))->value() ==
11821      optimized_code) {
11822    // Evict context-independent code as well.
11823    code_map->set(kSharedCodeIndex, heap->empty_weak_cell(),
11824                  SKIP_WRITE_BARRIER);
11825    if (FLAG_trace_opt) {
11826      PrintF("[evicting entry from optimizing code map (%s) for ", reason);
11827      ShortPrint();
11828      PrintF(" (context-independent code)]\n");
11829    }
11830  }
11831  if (dst != length) {
11832    // Always trim even when array is cleared because of heap verifier.
11833    heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
11834                                                           length - dst);
11835    if (code_map->length() == kEntriesStart &&
11836        WeakCell::cast(code_map->get(kSharedCodeIndex))->cleared()) {
11837      ClearOptimizedCodeMap();
11838    }
11839  }
11840}
11841
11842
11843void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
11844  FixedArray* code_map = optimized_code_map();
11845  DCHECK(shrink_by % kEntryLength == 0);
11846  DCHECK(shrink_by <= code_map->length() - kEntriesStart);
11847  // Always trim even when array is cleared because of heap verifier.
11848  GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
11849                                                              shrink_by);
11850  if (code_map->length() == kEntriesStart &&
11851      WeakCell::cast(code_map->get(kSharedCodeIndex))->cleared()) {
11852    ClearOptimizedCodeMap();
11853  }
11854}
11855
11856// static
11857void JSFunction::EnsureLiterals(Handle<JSFunction> function) {
11858  Handle<SharedFunctionInfo> shared(function->shared());
11859  Handle<Context> native_context(function->context()->native_context());
11860  if (function->literals() ==
11861      function->GetIsolate()->heap()->empty_literals_array()) {
11862    Handle<LiteralsArray> literals =
11863        SharedFunctionInfo::FindOrCreateLiterals(shared, native_context);
11864    function->set_literals(*literals);
11865  }
11866}
11867
11868static void GetMinInobjectSlack(Map* map, void* data) {
11869  int slack = map->unused_property_fields();
11870  if (*reinterpret_cast<int*>(data) > slack) {
11871    *reinterpret_cast<int*>(data) = slack;
11872  }
11873}
11874
11875
11876static void ShrinkInstanceSize(Map* map, void* data) {
11877  int slack = *reinterpret_cast<int*>(data);
11878  map->SetInObjectProperties(map->GetInObjectProperties() - slack);
11879  map->set_unused_property_fields(map->unused_property_fields() - slack);
11880  map->set_instance_size(map->instance_size() - slack * kPointerSize);
11881  map->set_construction_counter(Map::kNoSlackTracking);
11882
11883  // Visitor id might depend on the instance size, recalculate it.
11884  map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map));
11885}
11886
11887static void StopSlackTracking(Map* map, void* data) {
11888  map->set_construction_counter(Map::kNoSlackTracking);
11889}
11890
11891void Map::CompleteInobjectSlackTracking() {
11892  // Has to be an initial map.
11893  DCHECK(GetBackPointer()->IsUndefined(GetIsolate()));
11894
11895  int slack = unused_property_fields();
11896  TransitionArray::TraverseTransitionTree(this, &GetMinInobjectSlack, &slack);
11897  if (slack != 0) {
11898    // Resize the initial map and all maps in its transition tree.
11899    TransitionArray::TraverseTransitionTree(this, &ShrinkInstanceSize, &slack);
11900  } else {
11901    TransitionArray::TraverseTransitionTree(this, &StopSlackTracking, nullptr);
11902  }
11903}
11904
11905
11906static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
11907  DisallowHeapAllocation no_gc;
11908  if (!object->HasFastProperties()) return false;
11909  Map* map = object->map();
11910  if (map->is_prototype_map()) return false;
11911  DescriptorArray* descriptors = map->instance_descriptors();
11912  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
11913    PropertyDetails details = descriptors->GetDetails(i);
11914    if (details.location() == kDescriptor) continue;
11915    if (details.representation().IsHeapObject() ||
11916        details.representation().IsTagged()) {
11917      FieldIndex index = FieldIndex::ForDescriptor(map, i);
11918      if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
11919    }
11920  }
11921  return false;
11922}
11923
11924// static
11925void JSObject::MakePrototypesFast(Handle<Object> receiver,
11926                                  WhereToStart where_to_start,
11927                                  Isolate* isolate) {
11928  if (!receiver->IsJSReceiver()) return;
11929  for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
11930                              where_to_start);
11931       !iter.IsAtEnd(); iter.Advance()) {
11932    Handle<Object> current = PrototypeIterator::GetCurrent(iter);
11933    if (!current->IsJSObject()) return;
11934    Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
11935    Map* current_map = current_obj->map();
11936    if (current_map->is_prototype_map() &&
11937        !current_map->should_be_fast_prototype_map()) {
11938      Handle<Map> map(current_map);
11939      Map::SetShouldBeFastPrototypeMap(map, true, isolate);
11940      JSObject::OptimizeAsPrototype(current_obj, FAST_PROTOTYPE);
11941    }
11942  }
11943}
11944
11945// static
11946void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
11947                                   PrototypeOptimizationMode mode) {
11948  if (object->IsJSGlobalObject()) return;
11949  if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
11950    // First normalize to ensure all JSFunctions are DATA_CONSTANT.
11951    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
11952                                  "NormalizeAsPrototype");
11953  }
11954  Handle<Map> previous_map(object->map());
11955  if (object->map()->is_prototype_map()) {
11956    if (object->map()->should_be_fast_prototype_map() &&
11957        !object->HasFastProperties()) {
11958      JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
11959    }
11960  } else {
11961    if (object->map() == *previous_map) {
11962      Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
11963      JSObject::MigrateToMap(object, new_map);
11964    }
11965    object->map()->set_is_prototype_map(true);
11966
11967    // Replace the pointer to the exact constructor with the Object function
11968    // from the same context if undetectable from JS. This is to avoid keeping
11969    // memory alive unnecessarily.
11970    Object* maybe_constructor = object->map()->GetConstructor();
11971    if (maybe_constructor->IsJSFunction()) {
11972      JSFunction* constructor = JSFunction::cast(maybe_constructor);
11973      Isolate* isolate = object->GetIsolate();
11974      if (!constructor->shared()->IsApiFunction() &&
11975          object->class_name() == isolate->heap()->Object_string()) {
11976        Context* context = constructor->context()->native_context();
11977        JSFunction* object_function = context->object_function();
11978        object->map()->SetConstructor(object_function);
11979      }
11980    }
11981  }
11982}
11983
11984
11985// static
11986void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
11987  if (!object->map()->is_prototype_map()) return;
11988  if (!object->map()->should_be_fast_prototype_map()) return;
11989  OptimizeAsPrototype(object, FAST_PROTOTYPE);
11990}
11991
11992
11993// static
11994void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
11995  // Contract: In line with InvalidatePrototypeChains()'s requirements,
11996  // leaf maps don't need to register as users, only prototypes do.
11997  DCHECK(user->is_prototype_map());
11998
11999  Handle<Map> current_user = user;
12000  Handle<PrototypeInfo> current_user_info =
12001      Map::GetOrCreatePrototypeInfo(user, isolate);
12002  for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
12003    // Walk up the prototype chain as far as links haven't been registered yet.
12004    if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
12005      break;
12006    }
12007    Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
12008    // Proxies on the prototype chain are not supported. They make it
12009    // impossible to make any assumptions about the prototype chain anyway.
12010    if (maybe_proto->IsJSProxy()) return;
12011    Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
12012    Handle<PrototypeInfo> proto_info =
12013        Map::GetOrCreatePrototypeInfo(proto, isolate);
12014    Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
12015    int slot = 0;
12016    Handle<WeakFixedArray> new_array =
12017        WeakFixedArray::Add(maybe_registry, current_user, &slot);
12018    current_user_info->set_registry_slot(slot);
12019    if (!maybe_registry.is_identical_to(new_array)) {
12020      proto_info->set_prototype_users(*new_array);
12021    }
12022    if (FLAG_trace_prototype_users) {
12023      PrintF("Registering %p as a user of prototype %p (map=%p).\n",
12024             reinterpret_cast<void*>(*current_user),
12025             reinterpret_cast<void*>(*proto),
12026             reinterpret_cast<void*>(proto->map()));
12027    }
12028
12029    current_user = handle(proto->map(), isolate);
12030    current_user_info = proto_info;
12031  }
12032}
12033
12034
12035// Can be called regardless of whether |user| was actually registered with
12036// |prototype|. Returns true when there was a registration.
12037// static
12038bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12039  DCHECK(user->is_prototype_map());
12040  // If it doesn't have a PrototypeInfo, it was never registered.
12041  if (!user->prototype_info()->IsPrototypeInfo()) return false;
12042  // If it had no prototype before, see if it had users that might expect
12043  // registration.
12044  if (!user->prototype()->IsJSObject()) {
12045    Object* users =
12046        PrototypeInfo::cast(user->prototype_info())->prototype_users();
12047    return users->IsWeakFixedArray();
12048  }
12049  Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
12050  Handle<PrototypeInfo> user_info =
12051      Map::GetOrCreatePrototypeInfo(user, isolate);
12052  int slot = user_info->registry_slot();
12053  if (slot == PrototypeInfo::UNREGISTERED) return false;
12054  DCHECK(prototype->map()->is_prototype_map());
12055  Object* maybe_proto_info = prototype->map()->prototype_info();
12056  // User knows its registry slot, prototype info and user registry must exist.
12057  DCHECK(maybe_proto_info->IsPrototypeInfo());
12058  Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
12059                                   isolate);
12060  Object* maybe_registry = proto_info->prototype_users();
12061  DCHECK(maybe_registry->IsWeakFixedArray());
12062  DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user);
12063  WeakFixedArray::cast(maybe_registry)->Clear(slot);
12064  if (FLAG_trace_prototype_users) {
12065    PrintF("Unregistering %p as a user of prototype %p.\n",
12066           reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
12067  }
12068  return true;
12069}
12070
12071
12072static void InvalidatePrototypeChainsInternal(Map* map) {
12073  if (!map->is_prototype_map()) return;
12074  if (FLAG_trace_prototype_users) {
12075    PrintF("Invalidating prototype map %p 's cell\n",
12076           reinterpret_cast<void*>(map));
12077  }
12078  Object* maybe_proto_info = map->prototype_info();
12079  if (!maybe_proto_info->IsPrototypeInfo()) return;
12080  PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
12081  Object* maybe_cell = proto_info->validity_cell();
12082  if (maybe_cell->IsCell()) {
12083    // Just set the value; the cell will be replaced lazily.
12084    Cell* cell = Cell::cast(maybe_cell);
12085    cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
12086  }
12087
12088  WeakFixedArray::Iterator iterator(proto_info->prototype_users());
12089  // For now, only maps register themselves as users.
12090  Map* user;
12091  while ((user = iterator.Next<Map>())) {
12092    // Walk the prototype chain (backwards, towards leaf objects) if necessary.
12093    InvalidatePrototypeChainsInternal(user);
12094  }
12095}
12096
12097
12098// static
12099void JSObject::InvalidatePrototypeChains(Map* map) {
12100  DisallowHeapAllocation no_gc;
12101  InvalidatePrototypeChainsInternal(map);
12102}
12103
12104
12105// static
12106Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
12107                                                    Isolate* isolate) {
12108  Object* maybe_proto_info = prototype->map()->prototype_info();
12109  if (maybe_proto_info->IsPrototypeInfo()) {
12110    return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12111  }
12112  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12113  prototype->map()->set_prototype_info(*proto_info);
12114  return proto_info;
12115}
12116
12117
12118// static
12119Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
12120                                                    Isolate* isolate) {
12121  Object* maybe_proto_info = prototype_map->prototype_info();
12122  if (maybe_proto_info->IsPrototypeInfo()) {
12123    return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12124  }
12125  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12126  prototype_map->set_prototype_info(*proto_info);
12127  return proto_info;
12128}
12129
12130// static
12131void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
12132                                      Isolate* isolate) {
12133  if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
12134    // "False" is the implicit default value, so there's nothing to do.
12135    return;
12136  }
12137  GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
12138}
12139
12140// static
12141Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
12142                                                        Isolate* isolate) {
12143  Handle<Object> maybe_prototype(map->prototype(), isolate);
12144  if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
12145  Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
12146  // Ensure the prototype is registered with its own prototypes so its cell
12147  // will be invalidated when necessary.
12148  JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
12149                                      isolate);
12150  Handle<PrototypeInfo> proto_info =
12151      GetOrCreatePrototypeInfo(prototype, isolate);
12152  Object* maybe_cell = proto_info->validity_cell();
12153  // Return existing cell if it's still valid.
12154  if (maybe_cell->IsCell()) {
12155    Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
12156    if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
12157      return cell;
12158    }
12159  }
12160  // Otherwise create a new cell.
12161  Handle<Cell> cell = isolate->factory()->NewCell(
12162      handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
12163  proto_info->set_validity_cell(*cell);
12164  return cell;
12165}
12166
12167
12168// static
12169void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
12170                       PrototypeOptimizationMode proto_mode) {
12171  RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
12172
12173  bool is_hidden = false;
12174  if (prototype->IsJSObject()) {
12175    Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
12176    JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
12177
12178    Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
12179    if (maybe_constructor->IsJSFunction()) {
12180      JSFunction* constructor = JSFunction::cast(maybe_constructor);
12181      Object* data = constructor->shared()->function_data();
12182      is_hidden = (data->IsFunctionTemplateInfo() &&
12183                   FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
12184                  prototype->IsJSGlobalObject();
12185    }
12186  }
12187  map->set_has_hidden_prototype(is_hidden);
12188
12189  WriteBarrierMode wb_mode = prototype->IsNull(map->GetIsolate())
12190                                 ? SKIP_WRITE_BARRIER
12191                                 : UPDATE_WRITE_BARRIER;
12192  map->set_prototype(*prototype, wb_mode);
12193}
12194
12195
12196Handle<Object> CacheInitialJSArrayMaps(
12197    Handle<Context> native_context, Handle<Map> initial_map) {
12198  // Replace all of the cached initial array maps in the native context with
12199  // the appropriate transitioned elements kind maps.
12200  Handle<Map> current_map = initial_map;
12201  ElementsKind kind = current_map->elements_kind();
12202  DCHECK_EQ(GetInitialFastElementsKind(), kind);
12203  native_context->set(Context::ArrayMapIndex(kind), *current_map);
12204  for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
12205       i < kFastElementsKindCount; ++i) {
12206    Handle<Map> new_map;
12207    ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
12208    if (Map* maybe_elements_transition = current_map->ElementsTransitionMap()) {
12209      new_map = handle(maybe_elements_transition);
12210    } else {
12211      new_map = Map::CopyAsElementsKind(
12212          current_map, next_kind, INSERT_TRANSITION);
12213    }
12214    DCHECK_EQ(next_kind, new_map->elements_kind());
12215    native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
12216    current_map = new_map;
12217  }
12218  return initial_map;
12219}
12220
12221
12222void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
12223                                      Handle<Object> value) {
12224  Isolate* isolate = function->GetIsolate();
12225
12226  DCHECK(value->IsJSReceiver());
12227
12228  // Now some logic for the maps of the objects that are created by using this
12229  // function as a constructor.
12230  if (function->has_initial_map()) {
12231    // If the function has allocated the initial map replace it with a
12232    // copy containing the new prototype.  Also complete any in-object
12233    // slack tracking that is in progress at this point because it is
12234    // still tracking the old copy.
12235    function->CompleteInobjectSlackTrackingIfActive();
12236
12237    Handle<Map> initial_map(function->initial_map(), isolate);
12238
12239    if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
12240        initial_map->instance_type() == JS_OBJECT_TYPE) {
12241      // Put the value in the initial map field until an initial map is needed.
12242      // At that point, a new initial map is created and the prototype is put
12243      // into the initial map where it belongs.
12244      function->set_prototype_or_initial_map(*value);
12245    } else {
12246      Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
12247      JSFunction::SetInitialMap(function, new_map, value);
12248
12249      // If the function is used as the global Array function, cache the
12250      // updated initial maps (and transitioned versions) in the native context.
12251      Handle<Context> native_context(function->context()->native_context(),
12252                                     isolate);
12253      Handle<Object> array_function(
12254          native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
12255      if (array_function->IsJSFunction() &&
12256          *function == JSFunction::cast(*array_function)) {
12257        CacheInitialJSArrayMaps(native_context, new_map);
12258      }
12259    }
12260
12261    // Deoptimize all code that embeds the previous initial map.
12262    initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
12263        isolate, DependentCode::kInitialMapChangedGroup);
12264  } else {
12265    // Put the value in the initial map field until an initial map is
12266    // needed.  At that point, a new initial map is created and the
12267    // prototype is put into the initial map where it belongs.
12268    function->set_prototype_or_initial_map(*value);
12269    if (value->IsJSObject()) {
12270      // Optimize as prototype to detach it from its transition tree.
12271      JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
12272                                    FAST_PROTOTYPE);
12273    }
12274  }
12275  isolate->heap()->ClearInstanceofCache();
12276}
12277
12278
12279void JSFunction::SetPrototype(Handle<JSFunction> function,
12280                              Handle<Object> value) {
12281  DCHECK(function->IsConstructor() ||
12282         IsGeneratorFunction(function->shared()->kind()));
12283  Handle<Object> construct_prototype = value;
12284
12285  // If the value is not a JSReceiver, store the value in the map's
12286  // constructor field so it can be accessed.  Also, set the prototype
12287  // used for constructing objects to the original object prototype.
12288  // See ECMA-262 13.2.2.
12289  if (!value->IsJSReceiver()) {
12290    // Copy the map so this does not affect unrelated functions.
12291    // Remove map transitions because they point to maps with a
12292    // different prototype.
12293    Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
12294
12295    JSObject::MigrateToMap(function, new_map);
12296    new_map->SetConstructor(*value);
12297    new_map->set_non_instance_prototype(true);
12298    Isolate* isolate = new_map->GetIsolate();
12299
12300    construct_prototype = handle(
12301        IsGeneratorFunction(function->shared()->kind())
12302            ? function->context()
12303                  ->native_context()
12304                  ->initial_generator_prototype()
12305            : function->context()->native_context()->initial_object_prototype(),
12306        isolate);
12307  } else {
12308    function->map()->set_non_instance_prototype(false);
12309  }
12310
12311  return SetInstancePrototype(function, construct_prototype);
12312}
12313
12314
12315bool JSFunction::RemovePrototype() {
12316  Context* native_context = context()->native_context();
12317  Map* no_prototype_map =
12318      is_strict(shared()->language_mode())
12319          ? native_context->strict_function_without_prototype_map()
12320          : native_context->sloppy_function_without_prototype_map();
12321
12322  if (map() == no_prototype_map) return true;
12323
12324#ifdef DEBUG
12325  if (map() != (is_strict(shared()->language_mode())
12326                    ? native_context->strict_function_map()
12327                    : native_context->sloppy_function_map())) {
12328    return false;
12329  }
12330#endif
12331
12332  set_map(no_prototype_map);
12333  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
12334  return true;
12335}
12336
12337
12338void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
12339                               Handle<Object> prototype) {
12340  if (map->prototype() != *prototype) {
12341    Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
12342  }
12343  function->set_prototype_or_initial_map(*map);
12344  map->SetConstructor(*function);
12345#if TRACE_MAPS
12346  if (FLAG_trace_maps) {
12347    PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
12348           reinterpret_cast<void*>(*map), function->shared()->unique_id(),
12349           function->shared()->DebugName()->ToCString().get());
12350  }
12351#endif
12352}
12353
12354
12355#ifdef DEBUG
12356namespace {
12357
12358bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
12359  switch (instance_type) {
12360    case JS_API_OBJECT_TYPE:
12361    case JS_ARRAY_BUFFER_TYPE:
12362    case JS_ARRAY_TYPE:
12363    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
12364    case JS_DATA_VIEW_TYPE:
12365    case JS_DATE_TYPE:
12366    case JS_FUNCTION_TYPE:
12367    case JS_GENERATOR_OBJECT_TYPE:
12368    case JS_MAP_ITERATOR_TYPE:
12369    case JS_MAP_TYPE:
12370    case JS_MESSAGE_OBJECT_TYPE:
12371    case JS_MODULE_TYPE:
12372    case JS_OBJECT_TYPE:
12373    case JS_ERROR_TYPE:
12374    case JS_ARGUMENTS_TYPE:
12375    case JS_PROMISE_TYPE:
12376    case JS_REGEXP_TYPE:
12377    case JS_SET_ITERATOR_TYPE:
12378    case JS_SET_TYPE:
12379    case JS_SPECIAL_API_OBJECT_TYPE:
12380    case JS_TYPED_ARRAY_TYPE:
12381    case JS_VALUE_TYPE:
12382    case JS_WEAK_MAP_TYPE:
12383    case JS_WEAK_SET_TYPE:
12384      return true;
12385
12386    case BYTECODE_ARRAY_TYPE:
12387    case BYTE_ARRAY_TYPE:
12388    case CELL_TYPE:
12389    case CODE_TYPE:
12390    case FILLER_TYPE:
12391    case FIXED_ARRAY_TYPE:
12392    case FIXED_DOUBLE_ARRAY_TYPE:
12393    case FOREIGN_TYPE:
12394    case FREE_SPACE_TYPE:
12395    case HEAP_NUMBER_TYPE:
12396    case JS_BOUND_FUNCTION_TYPE:
12397    case JS_GLOBAL_OBJECT_TYPE:
12398    case JS_GLOBAL_PROXY_TYPE:
12399    case JS_PROXY_TYPE:
12400    case MAP_TYPE:
12401    case MUTABLE_HEAP_NUMBER_TYPE:
12402    case ODDBALL_TYPE:
12403    case PROPERTY_CELL_TYPE:
12404    case SHARED_FUNCTION_INFO_TYPE:
12405    case SIMD128_VALUE_TYPE:
12406    case SYMBOL_TYPE:
12407    case WEAK_CELL_TYPE:
12408
12409#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12410  case FIXED_##TYPE##_ARRAY_TYPE:
12411#undef TYPED_ARRAY_CASE
12412
12413#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
12414      STRUCT_LIST(MAKE_STRUCT_CASE)
12415#undef MAKE_STRUCT_CASE
12416      // We must not end up here for these instance types at all.
12417      UNREACHABLE();
12418    // Fall through.
12419    default:
12420      return false;
12421  }
12422}
12423
12424}  // namespace
12425#endif
12426
12427
12428void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
12429  DCHECK(function->IsConstructor() || function->shared()->is_resumable());
12430  if (function->has_initial_map()) return;
12431  Isolate* isolate = function->GetIsolate();
12432
12433  // The constructor should be compiled for the optimization hints to be
12434  // available.
12435  Compiler::Compile(function, Compiler::CLEAR_EXCEPTION);
12436
12437  // First create a new map with the size and number of in-object properties
12438  // suggested by the function.
12439  InstanceType instance_type;
12440  if (function->shared()->is_resumable()) {
12441    instance_type = JS_GENERATOR_OBJECT_TYPE;
12442  } else {
12443    instance_type = JS_OBJECT_TYPE;
12444  }
12445  int instance_size;
12446  int in_object_properties;
12447  function->CalculateInstanceSize(instance_type, 0, &instance_size,
12448                                  &in_object_properties);
12449
12450  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
12451
12452  // Fetch or allocate prototype.
12453  Handle<Object> prototype;
12454  if (function->has_instance_prototype()) {
12455    prototype = handle(function->instance_prototype(), isolate);
12456  } else {
12457    prototype = isolate->factory()->NewFunctionPrototype(function);
12458  }
12459  map->SetInObjectProperties(in_object_properties);
12460  map->set_unused_property_fields(in_object_properties);
12461  DCHECK(map->has_fast_object_elements());
12462
12463  // Finally link initial map and constructor function.
12464  DCHECK(prototype->IsJSReceiver());
12465  JSFunction::SetInitialMap(function, map, prototype);
12466  map->StartInobjectSlackTracking();
12467}
12468
12469
12470// static
12471MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
12472                                           Handle<JSFunction> constructor,
12473                                           Handle<JSReceiver> new_target) {
12474  EnsureHasInitialMap(constructor);
12475
12476  Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
12477  if (*new_target == *constructor) return constructor_initial_map;
12478
12479  // Fast case, new.target is a subclass of constructor. The map is cacheable
12480  // (and may already have been cached). new.target.prototype is guaranteed to
12481  // be a JSReceiver.
12482  if (new_target->IsJSFunction()) {
12483    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
12484
12485    // Check that |function|'s initial map still in sync with the |constructor|,
12486    // otherwise we must create a new initial map for |function|.
12487    if (function->has_initial_map() &&
12488        function->initial_map()->GetConstructor() == *constructor) {
12489      return handle(function->initial_map(), isolate);
12490    }
12491
12492    // Create a new map with the size and number of in-object properties
12493    // suggested by |function|.
12494
12495    // Link initial map and constructor function if the new.target is actually a
12496    // subclass constructor.
12497    if (IsSubclassConstructor(function->shared()->kind())) {
12498      Handle<Object> prototype(function->instance_prototype(), isolate);
12499      InstanceType instance_type = constructor_initial_map->instance_type();
12500      DCHECK(CanSubclassHaveInobjectProperties(instance_type));
12501      int internal_fields =
12502          JSObject::GetInternalFieldCount(*constructor_initial_map);
12503      int pre_allocated = constructor_initial_map->GetInObjectProperties() -
12504                          constructor_initial_map->unused_property_fields();
12505      int instance_size;
12506      int in_object_properties;
12507      function->CalculateInstanceSizeForDerivedClass(
12508          instance_type, internal_fields, &instance_size,
12509          &in_object_properties);
12510
12511      int unused_property_fields = in_object_properties - pre_allocated;
12512      Handle<Map> map =
12513          Map::CopyInitialMap(constructor_initial_map, instance_size,
12514                              in_object_properties, unused_property_fields);
12515      map->set_new_target_is_base(false);
12516
12517      JSFunction::SetInitialMap(function, map, prototype);
12518      map->SetConstructor(*constructor);
12519      map->set_construction_counter(Map::kNoSlackTracking);
12520      map->StartInobjectSlackTracking();
12521      return map;
12522    }
12523  }
12524
12525  // Slow path, new.target is either a proxy or can't cache the map.
12526  // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
12527  // fall back to the intrinsicDefaultProto.
12528  Handle<Object> prototype;
12529  if (new_target->IsJSFunction()) {
12530    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
12531    // Make sure the new.target.prototype is cached.
12532    EnsureHasInitialMap(function);
12533    prototype = handle(function->prototype(), isolate);
12534  } else {
12535    Handle<String> prototype_string = isolate->factory()->prototype_string();
12536    ASSIGN_RETURN_ON_EXCEPTION(
12537        isolate, prototype,
12538        JSReceiver::GetProperty(new_target, prototype_string), Map);
12539    // The above prototype lookup might change the constructor and its
12540    // prototype, hence we have to reload the initial map.
12541    EnsureHasInitialMap(constructor);
12542    constructor_initial_map = handle(constructor->initial_map(), isolate);
12543  }
12544
12545  // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
12546  // correct realm. Rather than directly fetching the .prototype, we fetch the
12547  // constructor that points to the .prototype. This relies on
12548  // constructor.prototype being FROZEN for those constructors.
12549  if (!prototype->IsJSReceiver()) {
12550    Handle<Context> context;
12551    ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
12552                               JSReceiver::GetFunctionRealm(new_target), Map);
12553    DCHECK(context->IsNativeContext());
12554    Handle<Object> maybe_index = JSReceiver::GetDataProperty(
12555        constructor, isolate->factory()->native_context_index_symbol());
12556    int index = maybe_index->IsSmi() ? Smi::cast(*maybe_index)->value()
12557                                     : Context::OBJECT_FUNCTION_INDEX;
12558    Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)));
12559    prototype = handle(realm_constructor->prototype(), isolate);
12560  }
12561
12562  Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
12563  map->set_new_target_is_base(false);
12564  DCHECK(prototype->IsJSReceiver());
12565  if (map->prototype() != *prototype) {
12566    Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
12567  }
12568  map->SetConstructor(*constructor);
12569  return map;
12570}
12571
12572
12573void JSFunction::PrintName(FILE* out) {
12574  base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
12575  PrintF(out, "%s", name.get());
12576}
12577
12578
12579Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
12580  Isolate* isolate = function->GetIsolate();
12581  Handle<Object> name =
12582      JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
12583  if (name->IsString()) return Handle<String>::cast(name);
12584  return handle(function->shared()->DebugName(), isolate);
12585}
12586
12587
12588Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
12589  Isolate* isolate = function->GetIsolate();
12590  Handle<Object> name = JSReceiver::GetDataProperty(
12591      function, isolate->factory()->display_name_string());
12592  if (name->IsString()) return Handle<String>::cast(name);
12593  return JSFunction::GetName(function);
12594}
12595
12596void JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
12597                         Handle<String> prefix) {
12598  Isolate* isolate = function->GetIsolate();
12599  Handle<String> function_name = Name::ToFunctionName(name).ToHandleChecked();
12600  if (prefix->length() > 0) {
12601    IncrementalStringBuilder builder(isolate);
12602    builder.AppendString(prefix);
12603    builder.AppendCharacter(' ');
12604    builder.AppendString(function_name);
12605    function_name = builder.Finish().ToHandleChecked();
12606  }
12607  JSObject::DefinePropertyOrElementIgnoreAttributes(
12608      function, isolate->factory()->name_string(), function_name,
12609      static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY))
12610      .ToHandleChecked();
12611}
12612
12613namespace {
12614
12615char const kNativeCodeSource[] = "function () { [native code] }";
12616
12617
12618Handle<String> NativeCodeFunctionSourceString(
12619    Handle<SharedFunctionInfo> shared_info) {
12620  Isolate* const isolate = shared_info->GetIsolate();
12621  if (shared_info->name()->IsString()) {
12622    IncrementalStringBuilder builder(isolate);
12623    builder.AppendCString("function ");
12624    builder.AppendString(handle(String::cast(shared_info->name()), isolate));
12625    builder.AppendCString("() { [native code] }");
12626    return builder.Finish().ToHandleChecked();
12627  }
12628  return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
12629}
12630
12631}  // namespace
12632
12633
12634// static
12635Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
12636  Isolate* const isolate = function->GetIsolate();
12637  return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
12638}
12639
12640
12641// static
12642Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
12643  Isolate* const isolate = function->GetIsolate();
12644  Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
12645
12646  // Check if {function} should hide its source code.
12647  if (!shared_info->script()->IsScript() ||
12648      Script::cast(shared_info->script())->hide_source()) {
12649    return NativeCodeFunctionSourceString(shared_info);
12650  }
12651
12652  // Check if we should print {function} as a class.
12653  Handle<Object> class_start_position = JSReceiver::GetDataProperty(
12654      function, isolate->factory()->class_start_position_symbol());
12655  if (class_start_position->IsSmi()) {
12656    Handle<Object> class_end_position = JSReceiver::GetDataProperty(
12657        function, isolate->factory()->class_end_position_symbol());
12658    Handle<String> script_source(
12659        String::cast(Script::cast(shared_info->script())->source()), isolate);
12660    return isolate->factory()->NewSubString(
12661        script_source, Handle<Smi>::cast(class_start_position)->value(),
12662        Handle<Smi>::cast(class_end_position)->value());
12663  }
12664
12665  // Check if we have source code for the {function}.
12666  if (!shared_info->HasSourceCode()) {
12667    return NativeCodeFunctionSourceString(shared_info);
12668  }
12669
12670  IncrementalStringBuilder builder(isolate);
12671  if (!shared_info->is_arrow()) {
12672    if (shared_info->is_concise_method()) {
12673      if (shared_info->is_generator()) {
12674        builder.AppendCharacter('*');
12675      } else if (shared_info->is_async()) {
12676        builder.AppendCString("async ");
12677      }
12678    } else {
12679      if (shared_info->is_generator()) {
12680        builder.AppendCString("function* ");
12681      } else if (shared_info->is_async()) {
12682        builder.AppendCString("async function ");
12683      } else {
12684        builder.AppendCString("function ");
12685      }
12686    }
12687    if (shared_info->name_should_print_as_anonymous()) {
12688      builder.AppendCString("anonymous");
12689    } else if (!shared_info->is_anonymous_expression()) {
12690      builder.AppendString(handle(String::cast(shared_info->name()), isolate));
12691    }
12692  }
12693  builder.AppendString(Handle<String>::cast(shared_info->GetSourceCode()));
12694  return builder.Finish().ToHandleChecked();
12695}
12696
12697void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
12698                         const char* to_string, Handle<Object> to_number,
12699                         bool to_boolean, const char* type_of, byte kind) {
12700  Handle<String> internalized_to_string =
12701      isolate->factory()->InternalizeUtf8String(to_string);
12702  Handle<String> internalized_type_of =
12703      isolate->factory()->InternalizeUtf8String(type_of);
12704  oddball->set_to_number_raw(to_number->Number());
12705  oddball->set_to_boolean(isolate->heap()->ToBoolean(to_boolean));
12706  oddball->set_to_number(*to_number);
12707  oddball->set_to_string(*internalized_to_string);
12708  oddball->set_type_of(*internalized_type_of);
12709  oddball->set_kind(kind);
12710}
12711
12712void Script::SetEvalOrigin(Handle<Script> script,
12713                           Handle<SharedFunctionInfo> outer_info,
12714                           int eval_position) {
12715  if (eval_position == RelocInfo::kNoPosition) {
12716    // If the position is missing, attempt to get the code offset from the
12717    // current activation.  Do not translate the code offset into source
12718    // position, but store it as negative value for lazy translation.
12719    StackTraceFrameIterator it(script->GetIsolate());
12720    if (!it.done() && it.is_javascript()) {
12721      FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame());
12722      script->set_eval_from_shared(summary.function()->shared());
12723      script->set_eval_from_position(-summary.code_offset());
12724      return;
12725    }
12726    eval_position = 0;
12727  }
12728  script->set_eval_from_shared(*outer_info);
12729  script->set_eval_from_position(eval_position);
12730}
12731
12732int Script::GetEvalPosition() {
12733  DisallowHeapAllocation no_gc;
12734  DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
12735  int position = eval_from_position();
12736  if (position < 0) {
12737    // Due to laziness, the position may not have been translated from code
12738    // offset yet, which would be encoded as negative integer. In that case,
12739    // translate and set the position.
12740    if (eval_from_shared()->IsUndefined(GetIsolate())) {
12741      position = 0;
12742    } else {
12743      SharedFunctionInfo* shared = SharedFunctionInfo::cast(eval_from_shared());
12744      position = shared->abstract_code()->SourcePosition(-position);
12745    }
12746    DCHECK(position >= 0);
12747    set_eval_from_position(position);
12748  }
12749  return position;
12750}
12751
12752void Script::InitLineEnds(Handle<Script> script) {
12753  Isolate* isolate = script->GetIsolate();
12754  if (!script->line_ends()->IsUndefined(isolate)) return;
12755
12756  if (!script->source()->IsString()) {
12757    DCHECK(script->source()->IsUndefined(isolate));
12758    Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
12759    script->set_line_ends(*empty);
12760    DCHECK(script->line_ends()->IsFixedArray());
12761    return;
12762  }
12763
12764  Handle<String> src(String::cast(script->source()), isolate);
12765
12766  Handle<FixedArray> array = String::CalculateLineEnds(src, true);
12767
12768  if (*array != isolate->heap()->empty_fixed_array()) {
12769    array->set_map(isolate->heap()->fixed_cow_array_map());
12770  }
12771
12772  script->set_line_ends(*array);
12773  DCHECK(script->line_ends()->IsFixedArray());
12774}
12775
12776#define SMI_VALUE(x) (Smi::cast(x)->value())
12777bool Script::GetPositionInfo(int position, PositionInfo* info,
12778                             OffsetFlag offset_flag) {
12779  Handle<Script> script(this);
12780  InitLineEnds(script);
12781
12782  DisallowHeapAllocation no_allocation;
12783
12784  DCHECK(script->line_ends()->IsFixedArray());
12785  FixedArray* ends = FixedArray::cast(script->line_ends());
12786
12787  const int ends_len = ends->length();
12788  if (ends_len == 0) return false;
12789
12790  // Return early on invalid positions. Negative positions behave as if 0 was
12791  // passed, and positions beyond the end of the script return as failure.
12792  if (position < 0) {
12793    position = 0;
12794  } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
12795    return false;
12796  }
12797
12798  // Determine line number by doing a binary search on the line ends array.
12799  if (SMI_VALUE(ends->get(0)) >= position) {
12800    info->line = 0;
12801    info->line_start = 0;
12802    info->column = position;
12803  } else {
12804    int left = 0;
12805    int right = ends_len - 1;
12806
12807    while (right > 0) {
12808      DCHECK_LE(left, right);
12809      const int mid = (left + right) / 2;
12810      if (position > SMI_VALUE(ends->get(mid))) {
12811        left = mid + 1;
12812      } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
12813        right = mid - 1;
12814      } else {
12815        info->line = mid;
12816        break;
12817      }
12818    }
12819    DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
12820           SMI_VALUE(ends->get(info->line - 1)) < position);
12821    info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
12822    info->column = position - info->line_start;
12823  }
12824
12825  // Line end is position of the linebreak character.
12826  info->line_end = SMI_VALUE(ends->get(info->line));
12827  if (info->line_end > 0) {
12828    DCHECK(script->source()->IsString());
12829    Handle<String> src(String::cast(script->source()));
12830    if (src->Get(info->line_end - 1) == '\r') {
12831      info->line_end--;
12832    }
12833  }
12834
12835  // Add offsets if requested.
12836  if (offset_flag == WITH_OFFSET) {
12837    if (info->line == 0) {
12838      info->column += script->column_offset();
12839    }
12840    info->line += script->line_offset();
12841  }
12842
12843  return true;
12844}
12845#undef SMI_VALUE
12846
12847int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
12848  PositionInfo info;
12849  if (!script->GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
12850    return -1;
12851  }
12852
12853  return info.column;
12854}
12855
12856int Script::GetLineNumberWithArray(int code_pos) {
12857  PositionInfo info;
12858  if (!GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
12859    return -1;
12860  }
12861
12862  return info.line;
12863}
12864
12865
12866int Script::GetLineNumber(Handle<Script> script, int code_pos) {
12867  InitLineEnds(script);
12868  return script->GetLineNumberWithArray(code_pos);
12869}
12870
12871
12872int Script::GetLineNumber(int code_pos) {
12873  DisallowHeapAllocation no_allocation;
12874  if (!line_ends()->IsUndefined(GetIsolate())) {
12875    return GetLineNumberWithArray(code_pos);
12876  }
12877
12878  // Slow mode: we do not have line_ends. We have to iterate through source.
12879  if (!source()->IsString()) return -1;
12880
12881  String* source_string = String::cast(source());
12882  int line = 0;
12883  int len = source_string->length();
12884  for (int pos = 0; pos < len; pos++) {
12885    if (pos == code_pos) break;
12886    if (source_string->Get(pos) == '\n') line++;
12887  }
12888  return line;
12889}
12890
12891
12892Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
12893  Isolate* isolate = script->GetIsolate();
12894  Handle<String> name_or_source_url_key =
12895      isolate->factory()->InternalizeOneByteString(
12896          STATIC_CHAR_VECTOR("nameOrSourceURL"));
12897  Handle<JSObject> script_wrapper = Script::GetWrapper(script);
12898  Handle<Object> property =
12899      JSReceiver::GetProperty(script_wrapper, name_or_source_url_key)
12900          .ToHandleChecked();
12901  DCHECK(property->IsJSFunction());
12902  Handle<Object> result;
12903  // Do not check against pending exception, since this function may be called
12904  // when an exception has already been pending.
12905  if (!Execution::TryCall(isolate, property, script_wrapper, 0, NULL)
12906           .ToHandle(&result)) {
12907    return isolate->factory()->undefined_value();
12908  }
12909  return result;
12910}
12911
12912
12913Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
12914  Isolate* isolate = script->GetIsolate();
12915  if (!script->wrapper()->IsUndefined(isolate)) {
12916    DCHECK(script->wrapper()->IsWeakCell());
12917    Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
12918    if (!cell->cleared()) {
12919      // Return a handle for the existing script wrapper from the cache.
12920      return handle(JSObject::cast(cell->value()));
12921    }
12922    // If we found an empty WeakCell, that means the script wrapper was
12923    // GCed.  We are not notified directly of that, so we decrement here
12924    // so that we at least don't count double for any given script.
12925    isolate->counters()->script_wrappers()->Decrement();
12926  }
12927  // Construct a new script wrapper.
12928  isolate->counters()->script_wrappers()->Increment();
12929  Handle<JSFunction> constructor = isolate->script_function();
12930  Handle<JSValue> result =
12931      Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
12932  result->set_value(*script);
12933  Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
12934  script->set_wrapper(*cell);
12935  return result;
12936}
12937
12938
12939MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
12940    FunctionLiteral* fun) {
12941  WeakFixedArray::Iterator iterator(shared_function_infos());
12942  SharedFunctionInfo* shared;
12943  while ((shared = iterator.Next<SharedFunctionInfo>())) {
12944    if (fun->function_token_position() == shared->function_token_position() &&
12945        fun->start_position() == shared->start_position() &&
12946        fun->end_position() == shared->end_position()) {
12947      return Handle<SharedFunctionInfo>(shared);
12948    }
12949  }
12950  return MaybeHandle<SharedFunctionInfo>();
12951}
12952
12953
12954Script::Iterator::Iterator(Isolate* isolate)
12955    : iterator_(isolate->heap()->script_list()) {}
12956
12957
12958Script* Script::Iterator::Next() { return iterator_.Next<Script>(); }
12959
12960
12961SharedFunctionInfo::Iterator::Iterator(Isolate* isolate)
12962    : script_iterator_(isolate),
12963      sfi_iterator_(isolate->heap()->noscript_shared_function_infos()) {}
12964
12965
12966bool SharedFunctionInfo::Iterator::NextScript() {
12967  Script* script = script_iterator_.Next();
12968  if (script == NULL) return false;
12969  sfi_iterator_.Reset(script->shared_function_infos());
12970  return true;
12971}
12972
12973
12974SharedFunctionInfo* SharedFunctionInfo::Iterator::Next() {
12975  do {
12976    SharedFunctionInfo* next = sfi_iterator_.Next<SharedFunctionInfo>();
12977    if (next != NULL) return next;
12978  } while (NextScript());
12979  return NULL;
12980}
12981
12982
12983void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
12984                                   Handle<Object> script_object) {
12985  if (shared->script() == *script_object) return;
12986  Isolate* isolate = shared->GetIsolate();
12987
12988  // Add shared function info to new script's list. If a collection occurs,
12989  // the shared function info may be temporarily in two lists.
12990  // This is okay because the gc-time processing of these lists can tolerate
12991  // duplicates.
12992  Handle<Object> list;
12993  if (script_object->IsScript()) {
12994    Handle<Script> script = Handle<Script>::cast(script_object);
12995    list = handle(script->shared_function_infos(), isolate);
12996  } else {
12997    list = isolate->factory()->noscript_shared_function_infos();
12998  }
12999
13000#ifdef DEBUG
13001  if (FLAG_enable_slow_asserts) {
13002    WeakFixedArray::Iterator iterator(*list);
13003    SharedFunctionInfo* next;
13004    while ((next = iterator.Next<SharedFunctionInfo>())) {
13005      DCHECK_NE(next, *shared);
13006    }
13007  }
13008#endif  // DEBUG
13009  list = WeakFixedArray::Add(list, shared);
13010
13011  if (script_object->IsScript()) {
13012    Handle<Script> script = Handle<Script>::cast(script_object);
13013    script->set_shared_function_infos(*list);
13014  } else {
13015    isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
13016  }
13017
13018  // Remove shared function info from old script's list.
13019  if (shared->script()->IsScript()) {
13020    Script* old_script = Script::cast(shared->script());
13021    if (old_script->shared_function_infos()->IsWeakFixedArray()) {
13022      WeakFixedArray* list =
13023          WeakFixedArray::cast(old_script->shared_function_infos());
13024      list->Remove(shared);
13025    }
13026  } else {
13027    // Remove shared function info from root array.
13028    Object* list = isolate->heap()->noscript_shared_function_infos();
13029    CHECK(WeakFixedArray::cast(list)->Remove(shared));
13030  }
13031
13032  // Finally set new script.
13033  shared->set_script(*script_object);
13034}
13035
13036
13037String* SharedFunctionInfo::DebugName() {
13038  Object* n = name();
13039  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
13040  return String::cast(n);
13041}
13042
13043// The filter is a pattern that matches function names in this way:
13044//   "*"      all; the default
13045//   "-"      all but the top-level function
13046//   "-name"  all but the function "name"
13047//   ""       only the top-level function
13048//   "name"   only the function "name"
13049//   "name*"  only functions starting with "name"
13050//   "~"      none; the tilde is not an identifier
13051bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
13052  if (*raw_filter == '*') return true;
13053  String* name = DebugName();
13054  Vector<const char> filter = CStrVector(raw_filter);
13055  if (filter.length() == 0) return name->length() == 0;
13056  if (filter[0] == '-') {
13057    // Negative filter.
13058    if (filter.length() == 1) {
13059      return (name->length() != 0);
13060    } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
13061      return false;
13062    }
13063    if (filter[filter.length() - 1] == '*' &&
13064        name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
13065      return false;
13066    }
13067    return true;
13068
13069  } else if (name->IsUtf8EqualTo(filter)) {
13070    return true;
13071  }
13072  if (filter[filter.length() - 1] == '*' &&
13073      name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
13074    return true;
13075  }
13076  return false;
13077}
13078
13079bool SharedFunctionInfo::HasSourceCode() const {
13080  Isolate* isolate = GetIsolate();
13081  return !script()->IsUndefined(isolate) &&
13082         !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
13083}
13084
13085
13086Handle<Object> SharedFunctionInfo::GetSourceCode() {
13087  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
13088  Handle<String> source(String::cast(Script::cast(script())->source()));
13089  return GetIsolate()->factory()->NewSubString(
13090      source, start_position(), end_position());
13091}
13092
13093
13094bool SharedFunctionInfo::IsInlineable() {
13095  // Check that the function has a script associated with it.
13096  if (!script()->IsScript()) return false;
13097  return !optimization_disabled();
13098}
13099
13100
13101int SharedFunctionInfo::SourceSize() {
13102  return end_position() - start_position();
13103}
13104
13105void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
13106                                             int requested_internal_fields,
13107                                             int requested_in_object_properties,
13108                                             int* instance_size,
13109                                             int* in_object_properties) {
13110  int header_size = JSObject::GetHeaderSize(instance_type);
13111  DCHECK_LE(requested_internal_fields,
13112            (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2);
13113  *instance_size =
13114      Min(header_size +
13115              ((requested_internal_fields + requested_in_object_properties)
13116               << kPointerSizeLog2),
13117          JSObject::kMaxInstanceSize);
13118  *in_object_properties = ((*instance_size - header_size) >> kPointerSizeLog2) -
13119                          requested_internal_fields;
13120}
13121
13122
13123void JSFunction::CalculateInstanceSize(InstanceType instance_type,
13124                                       int requested_internal_fields,
13125                                       int* instance_size,
13126                                       int* in_object_properties) {
13127  CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
13128                              shared()->expected_nof_properties(),
13129                              instance_size, in_object_properties);
13130}
13131
13132
13133void JSFunction::CalculateInstanceSizeForDerivedClass(
13134    InstanceType instance_type, int requested_internal_fields,
13135    int* instance_size, int* in_object_properties) {
13136  Isolate* isolate = GetIsolate();
13137  int expected_nof_properties = 0;
13138  for (PrototypeIterator iter(isolate, this, kStartAtReceiver); !iter.IsAtEnd();
13139       iter.Advance()) {
13140    JSReceiver* current = iter.GetCurrent<JSReceiver>();
13141    if (!current->IsJSFunction()) break;
13142    JSFunction* func = JSFunction::cast(current);
13143    SharedFunctionInfo* shared = func->shared();
13144    expected_nof_properties += shared->expected_nof_properties();
13145    if (!IsSubclassConstructor(shared->kind())) {
13146      break;
13147    }
13148  }
13149  CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
13150                              expected_nof_properties, instance_size,
13151                              in_object_properties);
13152}
13153
13154
13155// Output the source code without any allocation in the heap.
13156std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
13157  const SharedFunctionInfo* s = v.value;
13158  // For some native functions there is no source.
13159  if (!s->HasSourceCode()) return os << "<No Source>";
13160
13161  // Get the source for the script which this function came from.
13162  // Don't use String::cast because we don't want more assertion errors while
13163  // we are already creating a stack dump.
13164  String* script_source =
13165      reinterpret_cast<String*>(Script::cast(s->script())->source());
13166
13167  if (!script_source->LooksValid()) return os << "<Invalid Source>";
13168
13169  if (!s->is_toplevel()) {
13170    os << "function ";
13171    Object* name = s->name();
13172    if (name->IsString() && String::cast(name)->length() > 0) {
13173      String::cast(name)->PrintUC16(os);
13174    }
13175  }
13176
13177  int len = s->end_position() - s->start_position();
13178  if (len <= v.max_length || v.max_length < 0) {
13179    script_source->PrintUC16(os, s->start_position(), s->end_position());
13180    return os;
13181  } else {
13182    script_source->PrintUC16(os, s->start_position(),
13183                             s->start_position() + v.max_length);
13184    return os << "...\n";
13185  }
13186}
13187
13188
13189static bool IsCodeEquivalent(Code* code, Code* recompiled) {
13190  if (code->instruction_size() != recompiled->instruction_size()) return false;
13191  ByteArray* code_relocation = code->relocation_info();
13192  ByteArray* recompiled_relocation = recompiled->relocation_info();
13193  int length = code_relocation->length();
13194  if (length != recompiled_relocation->length()) return false;
13195  int compare = memcmp(code_relocation->GetDataStartAddress(),
13196                       recompiled_relocation->GetDataStartAddress(),
13197                       length);
13198  return compare == 0;
13199}
13200
13201
13202void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
13203  DCHECK(!has_deoptimization_support());
13204  DisallowHeapAllocation no_allocation;
13205  Code* code = this->code();
13206  if (IsCodeEquivalent(code, recompiled)) {
13207    // Copy the deoptimization data from the recompiled code.
13208    code->set_deoptimization_data(recompiled->deoptimization_data());
13209    code->set_has_deoptimization_support(true);
13210  } else {
13211    // TODO(3025757): In case the recompiled isn't equivalent to the
13212    // old code, we have to replace it. We should try to avoid this
13213    // altogether because it flushes valuable type feedback by
13214    // effectively resetting all IC state.
13215    ReplaceCode(recompiled);
13216  }
13217  DCHECK(has_deoptimization_support());
13218}
13219
13220
13221void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
13222  // Disable optimization for the shared function info and mark the
13223  // code as non-optimizable. The marker on the shared function info
13224  // is there because we flush non-optimized code thereby loosing the
13225  // non-optimizable information for the code. When the code is
13226  // regenerated and set on the shared function info it is marked as
13227  // non-optimizable if optimization is disabled for the shared
13228  // function info.
13229  DCHECK(reason != kNoReason);
13230  set_optimization_disabled(true);
13231  set_disable_optimization_reason(reason);
13232  // Code should be the lazy compilation stub or else unoptimized.
13233  DCHECK(abstract_code()->kind() == AbstractCode::FUNCTION ||
13234         abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
13235         abstract_code()->kind() == AbstractCode::BUILTIN);
13236  PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), this));
13237  if (FLAG_trace_opt) {
13238    PrintF("[disabled optimization for ");
13239    ShortPrint();
13240    PrintF(", reason: %s]\n", GetBailoutReason(reason));
13241  }
13242}
13243
13244namespace {
13245
13246// Sets the expected number of properties based on estimate from parser.
13247void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
13248                                          FunctionLiteral* literal) {
13249  int estimate = literal->expected_property_count();
13250
13251  // If no properties are added in the constructor, they are more likely
13252  // to be added later.
13253  if (estimate == 0) estimate = 2;
13254
13255  // TODO(yangguo): check whether those heuristics are still up-to-date.
13256  // We do not shrink objects that go into a snapshot (yet), so we adjust
13257  // the estimate conservatively.
13258  if (shared->GetIsolate()->serializer_enabled()) {
13259    estimate += 2;
13260  } else {
13261    // Inobject slack tracking will reclaim redundant inobject space later,
13262    // so we can afford to adjust the estimate generously.
13263    estimate += 8;
13264  }
13265
13266  shared->set_expected_nof_properties(estimate);
13267}
13268
13269}  // namespace
13270
13271void SharedFunctionInfo::InitFromFunctionLiteral(
13272    Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
13273  shared_info->set_length(lit->scope()->default_function_length());
13274  shared_info->set_internal_formal_parameter_count(lit->parameter_count());
13275  shared_info->set_function_token_position(lit->function_token_position());
13276  shared_info->set_start_position(lit->start_position());
13277  shared_info->set_end_position(lit->end_position());
13278  shared_info->set_is_declaration(lit->is_declaration());
13279  shared_info->set_is_named_expression(lit->is_named_expression());
13280  shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
13281  shared_info->set_inferred_name(*lit->inferred_name());
13282  shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
13283  shared_info->set_allows_lazy_compilation_without_context(
13284      lit->AllowsLazyCompilationWithoutContext());
13285  shared_info->set_language_mode(lit->language_mode());
13286  shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
13287  shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
13288  shared_info->set_is_function(lit->is_function());
13289  shared_info->set_never_compiled(true);
13290  shared_info->set_kind(lit->kind());
13291  if (!IsConstructable(lit->kind(), lit->language_mode())) {
13292    shared_info->set_construct_stub(
13293        *shared_info->GetIsolate()->builtins()->ConstructedNonConstructable());
13294  }
13295  shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
13296  shared_info->set_asm_function(lit->scope()->asm_function());
13297  SetExpectedNofPropertiesFromEstimate(shared_info, lit);
13298}
13299
13300
13301bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
13302  DCHECK(!id.IsNone());
13303  Code* unoptimized = code();
13304  DeoptimizationOutputData* data =
13305      DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
13306  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
13307  USE(ignore);
13308  return true;  // Return true if there was no DCHECK.
13309}
13310
13311
13312void Map::StartInobjectSlackTracking() {
13313  DCHECK(!IsInobjectSlackTrackingInProgress());
13314
13315  // No tracking during the snapshot construction phase.
13316  Isolate* isolate = GetIsolate();
13317  if (isolate->serializer_enabled()) return;
13318
13319  if (unused_property_fields() == 0) return;
13320
13321  set_construction_counter(Map::kSlackTrackingCounterStart);
13322}
13323
13324
13325void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
13326  code()->ClearInlineCaches();
13327  set_ic_age(new_ic_age);
13328  if (code()->kind() == Code::FUNCTION) {
13329    code()->set_profiler_ticks(0);
13330    if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
13331      // Re-enable optimizations if they were disabled due to opt_count limit.
13332      set_optimization_disabled(false);
13333    }
13334    set_opt_count(0);
13335    set_deopt_count(0);
13336  } else if (code()->is_interpreter_trampoline_builtin()) {
13337    set_profiler_ticks(0);
13338    if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
13339      // Re-enable optimizations if they were disabled due to opt_count limit.
13340      set_optimization_disabled(false);
13341    }
13342    set_opt_count(0);
13343    set_deopt_count(0);
13344  }
13345}
13346
13347
13348int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context,
13349                                                    BailoutId osr_ast_id) {
13350  DisallowHeapAllocation no_gc;
13351  DCHECK(native_context->IsNativeContext());
13352  if (!OptimizedCodeMapIsCleared()) {
13353    FixedArray* optimized_code_map = this->optimized_code_map();
13354    int length = optimized_code_map->length();
13355    Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
13356    for (int i = kEntriesStart; i < length; i += kEntryLength) {
13357      if (WeakCell::cast(optimized_code_map->get(i + kContextOffset))
13358                  ->value() == native_context &&
13359          optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
13360        return i;
13361      }
13362    }
13363    Object* shared_code =
13364        WeakCell::cast(optimized_code_map->get(kSharedCodeIndex))->value();
13365    if (shared_code->IsCode() && osr_ast_id.IsNone()) {
13366      return kSharedCodeIndex;
13367    }
13368  }
13369  return -1;
13370}
13371
13372void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() {
13373  if (!OptimizedCodeMapIsCleared()) {
13374    FixedArray* optimized_code_map = this->optimized_code_map();
13375    int length = optimized_code_map->length();
13376    WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell();
13377    for (int i = kEntriesStart; i < length; i += kEntryLength) {
13378      optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell,
13379                              SKIP_WRITE_BARRIER);
13380    }
13381    optimized_code_map->set(kSharedCodeIndex, empty_weak_cell,
13382                            SKIP_WRITE_BARRIER);
13383  }
13384}
13385
13386CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
13387    Context* native_context, BailoutId osr_ast_id) {
13388  CodeAndLiterals result = {nullptr, nullptr};
13389  int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id);
13390  if (entry != kNotFound) {
13391    FixedArray* code_map = optimized_code_map();
13392    if (entry == kSharedCodeIndex) {
13393      // We know the weak cell isn't cleared because we made sure of it in
13394      // SearchOptimizedCodeMapEntry and performed no allocations since that
13395      // call.
13396      result = {
13397          Code::cast(WeakCell::cast(code_map->get(kSharedCodeIndex))->value()),
13398          nullptr};
13399    } else {
13400      DCHECK_LE(entry + kEntryLength, code_map->length());
13401      WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
13402      Object* lits = code_map->get(entry + kLiteralsOffset);
13403      LiteralsArray* literals = nullptr;
13404      if (lits->IsWeakCell()) {
13405        WeakCell* literal_cell = WeakCell::cast(lits);
13406        if (!literal_cell->cleared()) {
13407          literals = LiteralsArray::cast(literal_cell->value());
13408        }
13409      } else {
13410        literals = LiteralsArray::cast(lits);
13411      }
13412      result = {cell->cleared() ? nullptr : Code::cast(cell->value()),
13413                literals};
13414    }
13415  }
13416  return result;
13417}
13418
13419
13420#define DECLARE_TAG(ignore1, name, ignore2) name,
13421const char* const VisitorSynchronization::kTags[
13422    VisitorSynchronization::kNumberOfSyncTags] = {
13423  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
13424};
13425#undef DECLARE_TAG
13426
13427
13428#define DECLARE_TAG(ignore1, ignore2, name) name,
13429const char* const VisitorSynchronization::kTagNames[
13430    VisitorSynchronization::kNumberOfSyncTags] = {
13431  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
13432};
13433#undef DECLARE_TAG
13434
13435
13436void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
13437  DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
13438  Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
13439  Object* new_pointer = old_pointer;
13440  VisitPointer(&new_pointer);
13441  DCHECK_EQ(old_pointer, new_pointer);
13442}
13443
13444
13445void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
13446  DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
13447  Object* old_pointer = rinfo->code_age_stub();
13448  Object* new_pointer = old_pointer;
13449  if (old_pointer != nullptr) {
13450    VisitPointer(&new_pointer);
13451    DCHECK_EQ(old_pointer, new_pointer);
13452  }
13453}
13454
13455
13456void ObjectVisitor::VisitCodeEntry(Address entry_address) {
13457  Object* old_pointer = Code::GetObjectFromEntryAddress(entry_address);
13458  Object* new_pointer = old_pointer;
13459  VisitPointer(&new_pointer);
13460  DCHECK_EQ(old_pointer, new_pointer);
13461}
13462
13463
13464void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
13465  DCHECK(rinfo->rmode() == RelocInfo::CELL);
13466  Object* old_pointer = rinfo->target_cell();
13467  Object* new_pointer = old_pointer;
13468  VisitPointer(&new_pointer);
13469  DCHECK_EQ(old_pointer, new_pointer);
13470}
13471
13472
13473void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
13474  DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
13475         rinfo->IsPatchedDebugBreakSlotSequence());
13476  Object* old_pointer =
13477      Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
13478  Object* new_pointer = old_pointer;
13479  VisitPointer(&new_pointer);
13480  DCHECK_EQ(old_pointer, new_pointer);
13481}
13482
13483
13484void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
13485  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
13486  Object* old_pointer = rinfo->target_object();
13487  Object* new_pointer = old_pointer;
13488  VisitPointer(&new_pointer);
13489  DCHECK_EQ(old_pointer, new_pointer);
13490}
13491
13492
13493void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
13494  Address old_reference = rinfo->target_external_reference();
13495  Address new_reference = old_reference;
13496  VisitExternalReference(&new_reference);
13497  DCHECK_EQ(old_reference, new_reference);
13498}
13499
13500
13501void Code::InvalidateRelocation() {
13502  InvalidateEmbeddedObjects();
13503  set_relocation_info(GetHeap()->empty_byte_array());
13504}
13505
13506
13507void Code::InvalidateEmbeddedObjects() {
13508  Object* undefined = GetHeap()->undefined_value();
13509  Cell* undefined_cell = GetHeap()->undefined_cell();
13510  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
13511                  RelocInfo::ModeMask(RelocInfo::CELL);
13512  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
13513    RelocInfo::Mode mode = it.rinfo()->rmode();
13514    if (mode == RelocInfo::EMBEDDED_OBJECT) {
13515      it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
13516    } else if (mode == RelocInfo::CELL) {
13517      it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
13518    }
13519  }
13520}
13521
13522
13523void Code::Relocate(intptr_t delta) {
13524  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
13525    it.rinfo()->apply(delta);
13526  }
13527  Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
13528}
13529
13530
13531void Code::CopyFrom(const CodeDesc& desc) {
13532  // copy code
13533  CopyBytes(instruction_start(), desc.buffer,
13534            static_cast<size_t>(desc.instr_size));
13535
13536  // copy unwinding info, if any
13537  if (desc.unwinding_info) {
13538    DCHECK_GT(desc.unwinding_info_size, 0);
13539    set_unwinding_info_size(desc.unwinding_info_size);
13540    CopyBytes(unwinding_info_start(), desc.unwinding_info,
13541              static_cast<size_t>(desc.unwinding_info_size));
13542  }
13543
13544  // copy reloc info
13545  CopyBytes(relocation_start(),
13546            desc.buffer + desc.buffer_size - desc.reloc_size,
13547            static_cast<size_t>(desc.reloc_size));
13548
13549  // unbox handles and relocate
13550  intptr_t delta = instruction_start() - desc.buffer;
13551  int mode_mask = RelocInfo::kCodeTargetMask |
13552                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
13553                  RelocInfo::ModeMask(RelocInfo::CELL) |
13554                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
13555                  RelocInfo::kApplyMask;
13556  // Needed to find target_object and runtime_entry on X64
13557  Assembler* origin = desc.origin;
13558  AllowDeferredHandleDereference embedding_raw_address;
13559  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
13560    RelocInfo::Mode mode = it.rinfo()->rmode();
13561    if (mode == RelocInfo::EMBEDDED_OBJECT) {
13562      Handle<Object> p = it.rinfo()->target_object_handle(origin);
13563      it.rinfo()->set_target_object(*p, UPDATE_WRITE_BARRIER,
13564                                    SKIP_ICACHE_FLUSH);
13565    } else if (mode == RelocInfo::CELL) {
13566      Handle<Cell> cell  = it.rinfo()->target_cell_handle();
13567      it.rinfo()->set_target_cell(*cell, UPDATE_WRITE_BARRIER,
13568                                  SKIP_ICACHE_FLUSH);
13569    } else if (RelocInfo::IsCodeTarget(mode)) {
13570      // rewrite code handles in inline cache targets to direct
13571      // pointers to the first instruction in the code object
13572      Handle<Object> p = it.rinfo()->target_object_handle(origin);
13573      Code* code = Code::cast(*p);
13574      it.rinfo()->set_target_address(code->instruction_start(),
13575                                     UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
13576    } else if (RelocInfo::IsRuntimeEntry(mode)) {
13577      Address p = it.rinfo()->target_runtime_entry(origin);
13578      it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
13579                                           SKIP_ICACHE_FLUSH);
13580    } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
13581      Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
13582      Code* code = Code::cast(*p);
13583      it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
13584    } else {
13585      it.rinfo()->apply(delta);
13586    }
13587  }
13588  Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
13589}
13590
13591// Locate the source position which is closest to the code offset. This is
13592// using the source position information embedded in the relocation info.
13593// The position returned is relative to the beginning of the script where the
13594// source for this function is found.
13595int Code::SourcePosition(int code_offset) {
13596  // Subtract one because the current PC is one instruction after the call site.
13597  Address pc = instruction_start() + code_offset - 1;
13598  int position = RelocInfo::kNoPosition;  // Initially no position found.
13599  // Find the closest position attached to a pc lower or equal to the current.
13600  // Note that the pc of reloc infos grow monotonically.
13601  for (RelocIterator it(this, RelocInfo::kPositionMask);
13602       !it.done() && it.rinfo()->pc() <= pc; it.next()) {
13603    position = static_cast<int>(it.rinfo()->data());
13604  }
13605  DCHECK(kind() == FUNCTION || (is_optimized_code() && is_turbofanned()) ||
13606         is_wasm_code() || position == RelocInfo::kNoPosition);
13607  return position;
13608}
13609
13610
13611// Same as Code::SourcePosition above except it only looks for statement
13612// positions.
13613int Code::SourceStatementPosition(int code_offset) {
13614  // First find the closest position.
13615  int position = SourcePosition(code_offset);
13616  // Now find the closest statement position before the position.
13617  int statement_position = 0;
13618  for (RelocIterator it(this, RelocInfo::kPositionMask); !it.done();
13619       it.next()) {
13620    if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
13621      int p = static_cast<int>(it.rinfo()->data());
13622      if (statement_position < p && p <= position) {
13623        statement_position = p;
13624      }
13625    }
13626  }
13627  return statement_position;
13628}
13629
13630
13631SafepointEntry Code::GetSafepointEntry(Address pc) {
13632  SafepointTable table(this);
13633  return table.FindEntry(pc);
13634}
13635
13636
13637Object* Code::FindNthObject(int n, Map* match_map) {
13638  DCHECK(is_inline_cache_stub());
13639  DisallowHeapAllocation no_allocation;
13640  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
13641  for (RelocIterator it(this, mask); !it.done(); it.next()) {
13642    RelocInfo* info = it.rinfo();
13643    Object* object = info->target_object();
13644    if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
13645    if (object->IsHeapObject()) {
13646      if (HeapObject::cast(object)->map() == match_map) {
13647        if (--n == 0) return object;
13648      }
13649    }
13650  }
13651  return NULL;
13652}
13653
13654
13655AllocationSite* Code::FindFirstAllocationSite() {
13656  Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
13657  return (result != NULL) ? AllocationSite::cast(result) : NULL;
13658}
13659
13660
13661Map* Code::FindFirstMap() {
13662  Object* result = FindNthObject(1, GetHeap()->meta_map());
13663  return (result != NULL) ? Map::cast(result) : NULL;
13664}
13665
13666
13667void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
13668  DCHECK(is_inline_cache_stub() || is_handler());
13669  DisallowHeapAllocation no_allocation;
13670  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
13671  STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
13672  int current_pattern = 0;
13673  for (RelocIterator it(this, mask); !it.done(); it.next()) {
13674    RelocInfo* info = it.rinfo();
13675    Object* object = info->target_object();
13676    if (object->IsHeapObject()) {
13677      if (object->IsWeakCell()) {
13678        object = HeapObject::cast(WeakCell::cast(object)->value());
13679      }
13680      Map* map = HeapObject::cast(object)->map();
13681      if (map == *pattern.find_[current_pattern]) {
13682        info->set_target_object(*pattern.replace_[current_pattern]);
13683        if (++current_pattern == pattern.count_) return;
13684      }
13685    }
13686  }
13687  UNREACHABLE();
13688}
13689
13690
13691void Code::ClearInlineCaches() {
13692  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
13693             RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
13694  for (RelocIterator it(this, mask); !it.done(); it.next()) {
13695    RelocInfo* info = it.rinfo();
13696    Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
13697    if (target->is_inline_cache_stub()) {
13698      IC::Clear(this->GetIsolate(), info->pc(), info->host()->constant_pool());
13699    }
13700  }
13701}
13702
13703int AbstractCode::SourcePosition(int offset) {
13704  return IsBytecodeArray() ? GetBytecodeArray()->SourcePosition(offset)
13705                           : GetCode()->SourcePosition(offset);
13706}
13707
13708int AbstractCode::SourceStatementPosition(int offset) {
13709  return IsBytecodeArray() ? GetBytecodeArray()->SourceStatementPosition(offset)
13710                           : GetCode()->SourceStatementPosition(offset);
13711}
13712
13713void JSFunction::ClearTypeFeedbackInfo() {
13714  feedback_vector()->ClearSlots(shared());
13715}
13716
13717void JSFunction::ClearTypeFeedbackInfoAtGCTime() {
13718  feedback_vector()->ClearSlotsAtGCTime(shared());
13719}
13720
13721BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
13722  DisallowHeapAllocation no_gc;
13723  DCHECK(kind() == FUNCTION);
13724  BackEdgeTable back_edges(this, &no_gc);
13725  for (uint32_t i = 0; i < back_edges.length(); i++) {
13726    if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
13727  }
13728  return BailoutId::None();
13729}
13730
13731
13732uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
13733  DisallowHeapAllocation no_gc;
13734  DCHECK(kind() == FUNCTION);
13735  BackEdgeTable back_edges(this, &no_gc);
13736  for (uint32_t i = 0; i < back_edges.length(); i++) {
13737    if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
13738  }
13739  UNREACHABLE();  // We expect to find the back edge.
13740  return 0;
13741}
13742
13743
13744void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
13745  PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
13746}
13747
13748
13749void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
13750  PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
13751      NO_MARKING_PARITY);
13752}
13753
13754
13755// NextAge defines the Code::Age state transitions during a GC cycle.
13756static Code::Age NextAge(Code::Age age) {
13757  switch (age) {
13758    case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
13759    case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
13760    case Code::kLastCodeAge:  // Clamp at last Code::Age value.
13761      return age;
13762    case Code::kExecutedOnceCodeAge:
13763      // Pre-age code that has only been executed once.
13764      return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
13765    default:
13766      return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
13767  }
13768}
13769
13770
13771// IsOldAge defines the collection criteria for a Code object.
13772static bool IsOldAge(Code::Age age) {
13773  return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
13774}
13775
13776
13777void Code::MakeYoung(Isolate* isolate) {
13778  byte* sequence = FindCodeAgeSequence();
13779  if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
13780}
13781
13782void Code::PreAge(Isolate* isolate) {
13783  byte* sequence = FindCodeAgeSequence();
13784  if (sequence != NULL) {
13785    PatchPlatformCodeAge(isolate, sequence, kPreAgedCodeAge, NO_MARKING_PARITY);
13786  }
13787}
13788
13789void Code::MarkToBeExecutedOnce(Isolate* isolate) {
13790  byte* sequence = FindCodeAgeSequence();
13791  if (sequence != NULL) {
13792    PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
13793                         NO_MARKING_PARITY);
13794  }
13795}
13796
13797void Code::MakeOlder(MarkingParity current_parity) {
13798  byte* sequence = FindCodeAgeSequence();
13799  if (sequence != NULL) {
13800    Age age;
13801    MarkingParity code_parity;
13802    Isolate* isolate = GetIsolate();
13803    GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
13804    Age next_age = NextAge(age);
13805    if (age != next_age && code_parity != current_parity) {
13806      PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
13807    }
13808  }
13809}
13810
13811
13812bool Code::IsOld() {
13813  return IsOldAge(GetAge());
13814}
13815
13816
13817byte* Code::FindCodeAgeSequence() {
13818  return FLAG_age_code &&
13819      prologue_offset() != Code::kPrologueOffsetNotSet &&
13820      (kind() == OPTIMIZED_FUNCTION ||
13821       (kind() == FUNCTION && !has_debug_break_slots()))
13822      ? instruction_start() + prologue_offset()
13823      : NULL;
13824}
13825
13826
13827Code::Age Code::GetAge() {
13828  byte* sequence = FindCodeAgeSequence();
13829  if (sequence == NULL) {
13830    return kNoAgeCodeAge;
13831  }
13832  Age age;
13833  MarkingParity parity;
13834  GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
13835  return age;
13836}
13837
13838
13839void Code::GetCodeAgeAndParity(Code* code, Age* age,
13840                               MarkingParity* parity) {
13841  Isolate* isolate = code->GetIsolate();
13842  Builtins* builtins = isolate->builtins();
13843  Code* stub = NULL;
13844#define HANDLE_CODE_AGE(AGE)                                            \
13845  stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
13846  if (code == stub) {                                                   \
13847    *age = k##AGE##CodeAge;                                             \
13848    *parity = EVEN_MARKING_PARITY;                                      \
13849    return;                                                             \
13850  }                                                                     \
13851  stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
13852  if (code == stub) {                                                   \
13853    *age = k##AGE##CodeAge;                                             \
13854    *parity = ODD_MARKING_PARITY;                                       \
13855    return;                                                             \
13856  }
13857  CODE_AGE_LIST(HANDLE_CODE_AGE)
13858#undef HANDLE_CODE_AGE
13859  stub = *builtins->MarkCodeAsExecutedOnce();
13860  if (code == stub) {
13861    *age = kNotExecutedCodeAge;
13862    *parity = NO_MARKING_PARITY;
13863    return;
13864  }
13865  stub = *builtins->MarkCodeAsExecutedTwice();
13866  if (code == stub) {
13867    *age = kExecutedOnceCodeAge;
13868    *parity = NO_MARKING_PARITY;
13869    return;
13870  }
13871  stub = *builtins->MarkCodeAsToBeExecutedOnce();
13872  if (code == stub) {
13873    *age = kToBeExecutedOnceCodeAge;
13874    *parity = NO_MARKING_PARITY;
13875    return;
13876  }
13877  UNREACHABLE();
13878}
13879
13880
13881Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
13882  Builtins* builtins = isolate->builtins();
13883  switch (age) {
13884#define HANDLE_CODE_AGE(AGE)                                            \
13885    case k##AGE##CodeAge: {                                             \
13886      Code* stub = parity == EVEN_MARKING_PARITY                        \
13887          ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
13888          : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
13889      return stub;                                                      \
13890    }
13891    CODE_AGE_LIST(HANDLE_CODE_AGE)
13892#undef HANDLE_CODE_AGE
13893    case kNotExecutedCodeAge: {
13894      DCHECK(parity == NO_MARKING_PARITY);
13895      return *builtins->MarkCodeAsExecutedOnce();
13896    }
13897    case kExecutedOnceCodeAge: {
13898      DCHECK(parity == NO_MARKING_PARITY);
13899      return *builtins->MarkCodeAsExecutedTwice();
13900    }
13901    case kToBeExecutedOnceCodeAge: {
13902      DCHECK(parity == NO_MARKING_PARITY);
13903      return *builtins->MarkCodeAsToBeExecutedOnce();
13904    }
13905    default:
13906      UNREACHABLE();
13907      break;
13908  }
13909  return NULL;
13910}
13911
13912
13913void Code::PrintDeoptLocation(FILE* out, Address pc) {
13914  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
13915  class SourcePosition pos = info.position;
13916  if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
13917    if (FLAG_hydrogen_track_positions) {
13918      PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
13919             pos.inlining_id(), pos.position(),
13920             Deoptimizer::GetDeoptReason(info.deopt_reason));
13921    } else {
13922      PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
13923             Deoptimizer::GetDeoptReason(info.deopt_reason));
13924    }
13925  }
13926}
13927
13928
13929bool Code::CanDeoptAt(Address pc) {
13930  DeoptimizationInputData* deopt_data =
13931      DeoptimizationInputData::cast(deoptimization_data());
13932  Address code_start_address = instruction_start();
13933  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
13934    if (deopt_data->Pc(i)->value() == -1) continue;
13935    Address address = code_start_address + deopt_data->Pc(i)->value();
13936    if (address == pc && deopt_data->AstId(i) != BailoutId::None()) {
13937      return true;
13938    }
13939  }
13940  return false;
13941}
13942
13943
13944// Identify kind of code.
13945const char* Code::Kind2String(Kind kind) {
13946  switch (kind) {
13947#define CASE(name) case name: return #name;
13948    CODE_KIND_LIST(CASE)
13949#undef CASE
13950    case NUMBER_OF_KINDS: break;
13951  }
13952  UNREACHABLE();
13953  return NULL;
13954}
13955
13956// Identify kind of code.
13957const char* AbstractCode::Kind2String(Kind kind) {
13958  if (kind < AbstractCode::INTERPRETED_FUNCTION)
13959    return Code::Kind2String((Code::Kind)kind);
13960  if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
13961  UNREACHABLE();
13962  return NULL;
13963}
13964
13965Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
13966  DCHECK(code->kind() == OPTIMIZED_FUNCTION);
13967  WeakCell* raw_cell = code->CachedWeakCell();
13968  if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
13969  Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
13970  DeoptimizationInputData::cast(code->deoptimization_data())
13971      ->SetWeakCellCache(*cell);
13972  return cell;
13973}
13974
13975
13976WeakCell* Code::CachedWeakCell() {
13977  DCHECK(kind() == OPTIMIZED_FUNCTION);
13978  Object* weak_cell_cache =
13979      DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
13980  if (weak_cell_cache->IsWeakCell()) {
13981    DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
13982    return WeakCell::cast(weak_cell_cache);
13983  }
13984  return NULL;
13985}
13986
13987#ifdef ENABLE_DISASSEMBLER
13988
13989void DeoptimizationInputData::DeoptimizationInputDataPrint(
13990    std::ostream& os) {  // NOLINT
13991  disasm::NameConverter converter;
13992  int const inlined_function_count = InlinedFunctionCount()->value();
13993  os << "Inlined functions (count = " << inlined_function_count << ")\n";
13994  for (int id = 0; id < inlined_function_count; ++id) {
13995    Object* info = LiteralArray()->get(id);
13996    os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
13997  }
13998  os << "\n";
13999  int deopt_count = DeoptCount();
14000  os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
14001  if (0 != deopt_count) {
14002    os << " index  ast id    argc     pc";
14003    if (FLAG_print_code_verbose) os << "  commands";
14004    os << "\n";
14005  }
14006  for (int i = 0; i < deopt_count; i++) {
14007    os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
14008       << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
14009       << std::setw(6) << Pc(i)->value();
14010
14011    if (!FLAG_print_code_verbose) {
14012      os << "\n";
14013      continue;
14014    }
14015    // Print details of the frame translation.
14016    int translation_index = TranslationIndex(i)->value();
14017    TranslationIterator iterator(TranslationByteArray(), translation_index);
14018    Translation::Opcode opcode =
14019        static_cast<Translation::Opcode>(iterator.Next());
14020    DCHECK(Translation::BEGIN == opcode);
14021    int frame_count = iterator.Next();
14022    int jsframe_count = iterator.Next();
14023    os << "  " << Translation::StringFor(opcode)
14024       << " {frame count=" << frame_count
14025       << ", js frame count=" << jsframe_count << "}\n";
14026
14027    while (iterator.HasNext() &&
14028           Translation::BEGIN !=
14029           (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
14030      os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
14031
14032      switch (opcode) {
14033        case Translation::BEGIN:
14034          UNREACHABLE();
14035          break;
14036
14037        case Translation::JS_FRAME: {
14038          int ast_id = iterator.Next();
14039          int shared_info_id = iterator.Next();
14040          unsigned height = iterator.Next();
14041          Object* shared_info = LiteralArray()->get(shared_info_id);
14042          os << "{ast_id=" << ast_id << ", function="
14043             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14044             << ", height=" << height << "}";
14045          break;
14046        }
14047
14048        case Translation::INTERPRETED_FRAME: {
14049          int bytecode_offset = iterator.Next();
14050          int shared_info_id = iterator.Next();
14051          unsigned height = iterator.Next();
14052          Object* shared_info = LiteralArray()->get(shared_info_id);
14053          os << "{bytecode_offset=" << bytecode_offset << ", function="
14054             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14055             << ", height=" << height << "}";
14056          break;
14057        }
14058
14059        case Translation::COMPILED_STUB_FRAME: {
14060          Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
14061          os << "{kind=" << stub_kind << "}";
14062          break;
14063        }
14064
14065        case Translation::ARGUMENTS_ADAPTOR_FRAME:
14066        case Translation::CONSTRUCT_STUB_FRAME: {
14067          int shared_info_id = iterator.Next();
14068          Object* shared_info = LiteralArray()->get(shared_info_id);
14069          unsigned height = iterator.Next();
14070          os << "{function="
14071             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14072             << ", height=" << height << "}";
14073          break;
14074        }
14075
14076        case Translation::TAIL_CALLER_FRAME: {
14077          int shared_info_id = iterator.Next();
14078          Object* shared_info = LiteralArray()->get(shared_info_id);
14079          os << "{function="
14080             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14081             << "}";
14082          break;
14083        }
14084
14085        case Translation::GETTER_STUB_FRAME:
14086        case Translation::SETTER_STUB_FRAME: {
14087          int shared_info_id = iterator.Next();
14088          Object* shared_info = LiteralArray()->get(shared_info_id);
14089          os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
14090                                          ->DebugName()) << "}";
14091          break;
14092        }
14093
14094        case Translation::REGISTER: {
14095          int reg_code = iterator.Next();
14096          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
14097          break;
14098        }
14099
14100        case Translation::INT32_REGISTER: {
14101          int reg_code = iterator.Next();
14102          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
14103          break;
14104        }
14105
14106        case Translation::UINT32_REGISTER: {
14107          int reg_code = iterator.Next();
14108          os << "{input=" << converter.NameOfCPURegister(reg_code)
14109             << " (unsigned)}";
14110          break;
14111        }
14112
14113        case Translation::BOOL_REGISTER: {
14114          int reg_code = iterator.Next();
14115          os << "{input=" << converter.NameOfCPURegister(reg_code)
14116             << " (bool)}";
14117          break;
14118        }
14119
14120        case Translation::FLOAT_REGISTER: {
14121          int reg_code = iterator.Next();
14122          os << "{input="
14123             << RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
14124                    reg_code)
14125             << "}";
14126          break;
14127        }
14128
14129        case Translation::DOUBLE_REGISTER: {
14130          int reg_code = iterator.Next();
14131          os << "{input="
14132             << RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
14133                    reg_code)
14134             << "}";
14135          break;
14136        }
14137
14138        case Translation::STACK_SLOT: {
14139          int input_slot_index = iterator.Next();
14140          os << "{input=" << input_slot_index << "}";
14141          break;
14142        }
14143
14144        case Translation::INT32_STACK_SLOT: {
14145          int input_slot_index = iterator.Next();
14146          os << "{input=" << input_slot_index << "}";
14147          break;
14148        }
14149
14150        case Translation::UINT32_STACK_SLOT: {
14151          int input_slot_index = iterator.Next();
14152          os << "{input=" << input_slot_index << " (unsigned)}";
14153          break;
14154        }
14155
14156        case Translation::BOOL_STACK_SLOT: {
14157          int input_slot_index = iterator.Next();
14158          os << "{input=" << input_slot_index << " (bool)}";
14159          break;
14160        }
14161
14162        case Translation::FLOAT_STACK_SLOT:
14163        case Translation::DOUBLE_STACK_SLOT: {
14164          int input_slot_index = iterator.Next();
14165          os << "{input=" << input_slot_index << "}";
14166          break;
14167        }
14168
14169        case Translation::LITERAL: {
14170          int literal_index = iterator.Next();
14171          Object* literal_value = LiteralArray()->get(literal_index);
14172          os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
14173             << ")}";
14174          break;
14175        }
14176
14177        case Translation::DUPLICATED_OBJECT: {
14178          int object_index = iterator.Next();
14179          os << "{object_index=" << object_index << "}";
14180          break;
14181        }
14182
14183        case Translation::ARGUMENTS_OBJECT:
14184        case Translation::CAPTURED_OBJECT: {
14185          int args_length = iterator.Next();
14186          os << "{length=" << args_length << "}";
14187          break;
14188        }
14189      }
14190      os << "\n";
14191    }
14192  }
14193}
14194
14195
14196void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
14197    std::ostream& os) {  // NOLINT
14198  os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
14199     << ")\n";
14200  if (this->DeoptPoints() == 0) return;
14201
14202  os << "ast id        pc  state\n";
14203  for (int i = 0; i < this->DeoptPoints(); i++) {
14204    int pc_and_state = this->PcAndState(i)->value();
14205    os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
14206       << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
14207       << Deoptimizer::BailoutStateToString(
14208              FullCodeGenerator::BailoutStateField::decode(pc_and_state))
14209       << "\n";
14210  }
14211}
14212
14213
14214void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
14215  os << "   from   to       hdlr\n";
14216  for (int i = 0; i < length(); i += kRangeEntrySize) {
14217    int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
14218    int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
14219    int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
14220    int handler_offset = HandlerOffsetField::decode(handler_field);
14221    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
14222    int data = Smi::cast(get(i + kRangeDataIndex))->value();
14223    os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
14224       << ")  ->  " << std::setw(4) << handler_offset
14225       << " (prediction=" << prediction << ", data=" << data << ")\n";
14226  }
14227}
14228
14229
14230void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
14231  os << "   off      hdlr (c)\n";
14232  for (int i = 0; i < length(); i += kReturnEntrySize) {
14233    int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
14234    int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
14235    int handler_offset = HandlerOffsetField::decode(handler_field);
14236    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
14237    os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
14238       << handler_offset << " (prediction=" << prediction << ")\n";
14239  }
14240}
14241
14242
14243const char* Code::ICState2String(InlineCacheState state) {
14244  switch (state) {
14245    case UNINITIALIZED: return "UNINITIALIZED";
14246    case PREMONOMORPHIC: return "PREMONOMORPHIC";
14247    case MONOMORPHIC: return "MONOMORPHIC";
14248    case RECOMPUTE_HANDLER:
14249      return "RECOMPUTE_HANDLER";
14250    case POLYMORPHIC: return "POLYMORPHIC";
14251    case MEGAMORPHIC: return "MEGAMORPHIC";
14252    case GENERIC: return "GENERIC";
14253  }
14254  UNREACHABLE();
14255  return NULL;
14256}
14257
14258
14259void Code::PrintExtraICState(std::ostream& os,  // NOLINT
14260                             Kind kind, ExtraICState extra) {
14261  os << "extra_ic_state = ";
14262  if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
14263      is_strict(static_cast<LanguageMode>(extra))) {
14264    os << "STRICT\n";
14265  } else {
14266    os << extra << "\n";
14267  }
14268}
14269
14270
14271void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
14272  os << "kind = " << Kind2String(kind()) << "\n";
14273  if (IsCodeStubOrIC()) {
14274    const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
14275    os << "major_key = " << (n == NULL ? "null" : n) << "\n";
14276  }
14277  if (is_inline_cache_stub()) {
14278    if (!IC::ICUseVector(kind())) {
14279      InlineCacheState ic_state = IC::StateFromCode(this);
14280      os << "ic_state = " << ICState2String(ic_state) << "\n";
14281    }
14282    PrintExtraICState(os, kind(), extra_ic_state());
14283    if (is_compare_ic_stub()) {
14284      DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
14285      CompareICStub stub(stub_key(), GetIsolate());
14286      os << "compare_state = " << CompareICState::GetStateName(stub.left())
14287         << "*" << CompareICState::GetStateName(stub.right()) << " -> "
14288         << CompareICState::GetStateName(stub.state()) << "\n";
14289      os << "compare_operation = " << Token::Name(stub.op()) << "\n";
14290    }
14291  }
14292  if ((name != nullptr) && (name[0] != '\0')) {
14293    os << "name = " << name << "\n";
14294  } else if (kind() == BUILTIN) {
14295    name = GetIsolate()->builtins()->Lookup(instruction_start());
14296    if (name != nullptr) {
14297      os << "name = " << name << "\n";
14298    }
14299  } else if (kind() == BYTECODE_HANDLER) {
14300    name = GetIsolate()->interpreter()->LookupNameOfBytecodeHandler(this);
14301    if (name != nullptr) {
14302      os << "name = " << name << "\n";
14303    }
14304  }
14305  if (kind() == OPTIMIZED_FUNCTION) {
14306    os << "stack_slots = " << stack_slots() << "\n";
14307  }
14308  os << "compiler = " << (is_turbofanned()
14309                              ? "turbofan"
14310                              : is_crankshafted() ? "crankshaft"
14311                                                  : kind() == Code::FUNCTION
14312                                                        ? "full-codegen"
14313                                                        : "unknown") << "\n";
14314
14315  os << "Instructions (size = " << instruction_size() << ")\n";
14316  {
14317    Isolate* isolate = GetIsolate();
14318    int size = instruction_size();
14319    int safepoint_offset =
14320        is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
14321    int back_edge_offset = (kind() == Code::FUNCTION)
14322                               ? static_cast<int>(back_edge_table_offset())
14323                               : size;
14324    int constant_pool_offset = FLAG_enable_embedded_constant_pool
14325                                   ? this->constant_pool_offset()
14326                                   : size;
14327
14328    // Stop before reaching any embedded tables
14329    int code_size = Min(safepoint_offset, back_edge_offset);
14330    code_size = Min(code_size, constant_pool_offset);
14331    byte* begin = instruction_start();
14332    byte* end = begin + code_size;
14333    Disassembler::Decode(isolate, &os, begin, end, this);
14334
14335    if (constant_pool_offset < size) {
14336      int constant_pool_size = size - constant_pool_offset;
14337      DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
14338      os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
14339      Vector<char> buf = Vector<char>::New(50);
14340      intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
14341      for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
14342        SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
14343        os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
14344      }
14345    }
14346  }
14347  os << "\n";
14348
14349  if (kind() == FUNCTION) {
14350    DeoptimizationOutputData* data =
14351        DeoptimizationOutputData::cast(this->deoptimization_data());
14352    data->DeoptimizationOutputDataPrint(os);
14353  } else if (kind() == OPTIMIZED_FUNCTION) {
14354    DeoptimizationInputData* data =
14355        DeoptimizationInputData::cast(this->deoptimization_data());
14356    data->DeoptimizationInputDataPrint(os);
14357  }
14358  os << "\n";
14359
14360  if (is_crankshafted()) {
14361    SafepointTable table(this);
14362    os << "Safepoints (size = " << table.size() << ")\n";
14363    for (unsigned i = 0; i < table.length(); i++) {
14364      unsigned pc_offset = table.GetPcOffset(i);
14365      os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
14366      os << std::setw(4) << pc_offset << "  ";
14367      table.PrintEntry(i, os);
14368      os << " (sp -> fp)  ";
14369      SafepointEntry entry = table.GetEntry(i);
14370      if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
14371        os << std::setw(6) << entry.deoptimization_index();
14372      } else {
14373        os << "<none>";
14374      }
14375      if (entry.argument_count() > 0) {
14376        os << " argc: " << entry.argument_count();
14377      }
14378      os << "\n";
14379    }
14380    os << "\n";
14381  } else if (kind() == FUNCTION) {
14382    unsigned offset = back_edge_table_offset();
14383    // If there is no back edge table, the "table start" will be at or after
14384    // (due to alignment) the end of the instruction stream.
14385    if (static_cast<int>(offset) < instruction_size()) {
14386      DisallowHeapAllocation no_gc;
14387      BackEdgeTable back_edges(this, &no_gc);
14388
14389      os << "Back edges (size = " << back_edges.length() << ")\n";
14390      os << "ast_id  pc_offset  loop_depth\n";
14391
14392      for (uint32_t i = 0; i < back_edges.length(); i++) {
14393        os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
14394           << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
14395           << back_edges.loop_depth(i) << "\n";
14396      }
14397
14398      os << "\n";
14399    }
14400#ifdef OBJECT_PRINT
14401    if (!type_feedback_info()->IsUndefined(GetIsolate())) {
14402      TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
14403      os << "\n";
14404    }
14405#endif
14406  }
14407
14408  if (handler_table()->length() > 0) {
14409    os << "Handler Table (size = " << handler_table()->Size() << ")\n";
14410    if (kind() == FUNCTION) {
14411      HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
14412    } else if (kind() == OPTIMIZED_FUNCTION) {
14413      HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
14414    }
14415    os << "\n";
14416  }
14417
14418  os << "RelocInfo (size = " << relocation_size() << ")\n";
14419  for (RelocIterator it(this); !it.done(); it.next()) {
14420    it.rinfo()->Print(GetIsolate(), os);
14421  }
14422  os << "\n";
14423}
14424#endif  // ENABLE_DISASSEMBLER
14425
14426int BytecodeArray::SourcePosition(int offset) {
14427  int last_position = 0;
14428  for (interpreter::SourcePositionTableIterator iterator(
14429           source_position_table());
14430       !iterator.done() && iterator.bytecode_offset() <= offset;
14431       iterator.Advance()) {
14432    last_position = iterator.source_position();
14433  }
14434  return last_position;
14435}
14436
14437int BytecodeArray::SourceStatementPosition(int offset) {
14438  // First find the closest position.
14439  int position = SourcePosition(offset);
14440  // Now find the closest statement position before the position.
14441  int statement_position = 0;
14442  for (interpreter::SourcePositionTableIterator it(source_position_table());
14443       !it.done(); it.Advance()) {
14444    if (it.is_statement()) {
14445      int p = it.source_position();
14446      if (statement_position < p && p <= position) {
14447        statement_position = p;
14448      }
14449    }
14450  }
14451  return statement_position;
14452}
14453
14454void BytecodeArray::Disassemble(std::ostream& os) {
14455  os << "Parameter count " << parameter_count() << "\n";
14456  os << "Frame size " << frame_size() << "\n";
14457
14458  const uint8_t* base_address = GetFirstBytecodeAddress();
14459  interpreter::SourcePositionTableIterator source_positions(
14460      source_position_table());
14461
14462  interpreter::BytecodeArrayIterator iterator(handle(this));
14463  while (!iterator.done()) {
14464    if (!source_positions.done() &&
14465        iterator.current_offset() == source_positions.bytecode_offset()) {
14466      os << std::setw(5) << source_positions.source_position();
14467      os << (source_positions.is_statement() ? " S> " : " E> ");
14468      source_positions.Advance();
14469    } else {
14470      os << "         ";
14471    }
14472    const uint8_t* current_address = base_address + iterator.current_offset();
14473    os << reinterpret_cast<const void*>(current_address) << " @ "
14474       << std::setw(4) << iterator.current_offset() << " : ";
14475    interpreter::Bytecodes::Decode(os, current_address, parameter_count());
14476    if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
14477      const void* jump_target = base_address + iterator.GetJumpTargetOffset();
14478      os << " (" << jump_target << " @ " << iterator.GetJumpTargetOffset()
14479         << ")";
14480    }
14481    os << std::endl;
14482    iterator.Advance();
14483  }
14484
14485  if (constant_pool()->length() > 0) {
14486    os << "Constant pool (size = " << constant_pool()->length() << ")\n";
14487    constant_pool()->Print();
14488  }
14489
14490#ifdef ENABLE_DISASSEMBLER
14491  if (handler_table()->length() > 0) {
14492    os << "Handler Table (size = " << handler_table()->Size() << ")\n";
14493    HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
14494  }
14495#endif
14496}
14497
14498void BytecodeArray::CopyBytecodesTo(BytecodeArray* to) {
14499  BytecodeArray* from = this;
14500  DCHECK_EQ(from->length(), to->length());
14501  CopyBytes(to->GetFirstBytecodeAddress(), from->GetFirstBytecodeAddress(),
14502            from->length());
14503}
14504
14505// static
14506void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
14507  DCHECK(capacity >= 0);
14508  array->GetIsolate()->factory()->NewJSArrayStorage(
14509      array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
14510}
14511
14512void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
14513  // We should never end in here with a pixel or external array.
14514  DCHECK(array->AllowsSetLength());
14515  if (array->SetLengthWouldNormalize(new_length)) {
14516    JSObject::NormalizeElements(array);
14517  }
14518  array->GetElementsAccessor()->SetLength(array, new_length);
14519}
14520
14521
14522// static
14523void Map::AddDependentCode(Handle<Map> map,
14524                           DependentCode::DependencyGroup group,
14525                           Handle<Code> code) {
14526  Handle<WeakCell> cell = Code::WeakCellFor(code);
14527  Handle<DependentCode> codes = DependentCode::InsertWeakCode(
14528      Handle<DependentCode>(map->dependent_code()), group, cell);
14529  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
14530}
14531
14532
14533Handle<DependentCode> DependentCode::InsertCompilationDependencies(
14534    Handle<DependentCode> entries, DependencyGroup group,
14535    Handle<Foreign> info) {
14536  return Insert(entries, group, info);
14537}
14538
14539
14540Handle<DependentCode> DependentCode::InsertWeakCode(
14541    Handle<DependentCode> entries, DependencyGroup group,
14542    Handle<WeakCell> code_cell) {
14543  return Insert(entries, group, code_cell);
14544}
14545
14546
14547Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
14548                                            DependencyGroup group,
14549                                            Handle<Object> object) {
14550  if (entries->length() == 0 || entries->group() > group) {
14551    // There is no such group.
14552    return DependentCode::New(group, object, entries);
14553  }
14554  if (entries->group() < group) {
14555    // The group comes later in the list.
14556    Handle<DependentCode> old_next(entries->next_link());
14557    Handle<DependentCode> new_next = Insert(old_next, group, object);
14558    if (!old_next.is_identical_to(new_next)) {
14559      entries->set_next_link(*new_next);
14560    }
14561    return entries;
14562  }
14563  DCHECK_EQ(group, entries->group());
14564  int count = entries->count();
14565  // Check for existing entry to avoid duplicates.
14566  for (int i = 0; i < count; i++) {
14567    if (entries->object_at(i) == *object) return entries;
14568  }
14569  if (entries->length() < kCodesStartIndex + count + 1) {
14570    entries = EnsureSpace(entries);
14571    // Count could have changed, reload it.
14572    count = entries->count();
14573  }
14574  entries->set_object_at(count, *object);
14575  entries->set_count(count + 1);
14576  return entries;
14577}
14578
14579
14580Handle<DependentCode> DependentCode::New(DependencyGroup group,
14581                                         Handle<Object> object,
14582                                         Handle<DependentCode> next) {
14583  Isolate* isolate = next->GetIsolate();
14584  Handle<DependentCode> result = Handle<DependentCode>::cast(
14585      isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED));
14586  result->set_next_link(*next);
14587  result->set_flags(GroupField::encode(group) | CountField::encode(1));
14588  result->set_object_at(0, *object);
14589  return result;
14590}
14591
14592
14593Handle<DependentCode> DependentCode::EnsureSpace(
14594    Handle<DependentCode> entries) {
14595  if (entries->Compact()) return entries;
14596  Isolate* isolate = entries->GetIsolate();
14597  int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
14598  int grow_by = capacity - entries->length();
14599  return Handle<DependentCode>::cast(
14600      isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED));
14601}
14602
14603
14604bool DependentCode::Compact() {
14605  int old_count = count();
14606  int new_count = 0;
14607  for (int i = 0; i < old_count; i++) {
14608    Object* obj = object_at(i);
14609    if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
14610      if (i != new_count) {
14611        copy(i, new_count);
14612      }
14613      new_count++;
14614    }
14615  }
14616  set_count(new_count);
14617  for (int i = new_count; i < old_count; i++) {
14618    clear_at(i);
14619  }
14620  return new_count < old_count;
14621}
14622
14623
14624void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
14625                                         WeakCell* code_cell) {
14626  if (this->length() == 0 || this->group() > group) {
14627    // There is no such group.
14628    return;
14629  }
14630  if (this->group() < group) {
14631    // The group comes later in the list.
14632    next_link()->UpdateToFinishedCode(group, info, code_cell);
14633    return;
14634  }
14635  DCHECK_EQ(group, this->group());
14636  DisallowHeapAllocation no_gc;
14637  int count = this->count();
14638  for (int i = 0; i < count; i++) {
14639    if (object_at(i) == info) {
14640      set_object_at(i, code_cell);
14641      break;
14642    }
14643  }
14644#ifdef DEBUG
14645  for (int i = 0; i < count; i++) {
14646    DCHECK(object_at(i) != info);
14647  }
14648#endif
14649}
14650
14651
14652void DependentCode::RemoveCompilationDependencies(
14653    DependentCode::DependencyGroup group, Foreign* info) {
14654  if (this->length() == 0 || this->group() > group) {
14655    // There is no such group.
14656    return;
14657  }
14658  if (this->group() < group) {
14659    // The group comes later in the list.
14660    next_link()->RemoveCompilationDependencies(group, info);
14661    return;
14662  }
14663  DCHECK_EQ(group, this->group());
14664  DisallowHeapAllocation no_allocation;
14665  int old_count = count();
14666  // Find compilation info wrapper.
14667  int info_pos = -1;
14668  for (int i = 0; i < old_count; i++) {
14669    if (object_at(i) == info) {
14670      info_pos = i;
14671      break;
14672    }
14673  }
14674  if (info_pos == -1) return;  // Not found.
14675  // Use the last code to fill the gap.
14676  if (info_pos < old_count - 1) {
14677    copy(old_count - 1, info_pos);
14678  }
14679  clear_at(old_count - 1);
14680  set_count(old_count - 1);
14681
14682#ifdef DEBUG
14683  for (int i = 0; i < old_count - 1; i++) {
14684    DCHECK(object_at(i) != info);
14685  }
14686#endif
14687}
14688
14689
14690bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
14691  if (this->length() == 0 || this->group() > group) {
14692    // There is no such group.
14693    return false;
14694  }
14695  if (this->group() < group) {
14696    // The group comes later in the list.
14697    return next_link()->Contains(group, code_cell);
14698  }
14699  DCHECK_EQ(group, this->group());
14700  int count = this->count();
14701  for (int i = 0; i < count; i++) {
14702    if (object_at(i) == code_cell) return true;
14703  }
14704  return false;
14705}
14706
14707
14708bool DependentCode::IsEmpty(DependencyGroup group) {
14709  if (this->length() == 0 || this->group() > group) {
14710    // There is no such group.
14711    return true;
14712  }
14713  if (this->group() < group) {
14714    // The group comes later in the list.
14715    return next_link()->IsEmpty(group);
14716  }
14717  DCHECK_EQ(group, this->group());
14718  return count() == 0;
14719}
14720
14721
14722bool DependentCode::MarkCodeForDeoptimization(
14723    Isolate* isolate,
14724    DependentCode::DependencyGroup group) {
14725  if (this->length() == 0 || this->group() > group) {
14726    // There is no such group.
14727    return false;
14728  }
14729  if (this->group() < group) {
14730    // The group comes later in the list.
14731    return next_link()->MarkCodeForDeoptimization(isolate, group);
14732  }
14733  DCHECK_EQ(group, this->group());
14734  DisallowHeapAllocation no_allocation_scope;
14735  // Mark all the code that needs to be deoptimized.
14736  bool marked = false;
14737  bool invalidate_embedded_objects = group == kWeakCodeGroup;
14738  int count = this->count();
14739  for (int i = 0; i < count; i++) {
14740    Object* obj = object_at(i);
14741    if (obj->IsWeakCell()) {
14742      WeakCell* cell = WeakCell::cast(obj);
14743      if (cell->cleared()) continue;
14744      Code* code = Code::cast(cell->value());
14745      if (!code->marked_for_deoptimization()) {
14746        SetMarkedForDeoptimization(code, group);
14747        if (invalidate_embedded_objects) {
14748          code->InvalidateEmbeddedObjects();
14749        }
14750        marked = true;
14751      }
14752    } else {
14753      DCHECK(obj->IsForeign());
14754      CompilationDependencies* info =
14755          reinterpret_cast<CompilationDependencies*>(
14756              Foreign::cast(obj)->foreign_address());
14757      info->Abort();
14758    }
14759  }
14760  for (int i = 0; i < count; i++) {
14761    clear_at(i);
14762  }
14763  set_count(0);
14764  return marked;
14765}
14766
14767
14768void DependentCode::DeoptimizeDependentCodeGroup(
14769    Isolate* isolate,
14770    DependentCode::DependencyGroup group) {
14771  DCHECK(AllowCodeDependencyChange::IsAllowed());
14772  DisallowHeapAllocation no_allocation_scope;
14773  bool marked = MarkCodeForDeoptimization(isolate, group);
14774  if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
14775}
14776
14777
14778void DependentCode::SetMarkedForDeoptimization(Code* code,
14779                                               DependencyGroup group) {
14780  code->set_marked_for_deoptimization(true);
14781  if (FLAG_trace_deopt &&
14782      (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
14783    DeoptimizationInputData* deopt_data =
14784        DeoptimizationInputData::cast(code->deoptimization_data());
14785    CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
14786    PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
14787                         " (opt #%d) for deoptimization, reason: %s]\n",
14788           reinterpret_cast<intptr_t>(code),
14789           deopt_data->OptimizationId()->value(), DependencyGroupName(group));
14790  }
14791}
14792
14793
14794const char* DependentCode::DependencyGroupName(DependencyGroup group) {
14795  switch (group) {
14796    case kWeakCodeGroup:
14797      return "weak-code";
14798    case kTransitionGroup:
14799      return "transition";
14800    case kPrototypeCheckGroup:
14801      return "prototype-check";
14802    case kPropertyCellChangedGroup:
14803      return "property-cell-changed";
14804    case kFieldTypeGroup:
14805      return "field-type";
14806    case kInitialMapChangedGroup:
14807      return "initial-map-changed";
14808    case kAllocationSiteTenuringChangedGroup:
14809      return "allocation-site-tenuring-changed";
14810    case kAllocationSiteTransitionChangedGroup:
14811      return "allocation-site-transition-changed";
14812  }
14813  UNREACHABLE();
14814  return "?";
14815}
14816
14817
14818Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
14819                                       Handle<Object> prototype,
14820                                       PrototypeOptimizationMode mode) {
14821  Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
14822  if (new_map.is_null()) {
14823    new_map = Copy(map, "TransitionToPrototype");
14824    TransitionArray::PutPrototypeTransition(map, prototype, new_map);
14825    Map::SetPrototype(new_map, prototype, mode);
14826  }
14827  return new_map;
14828}
14829
14830
14831Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
14832                                     Handle<Object> value, bool from_javascript,
14833                                     ShouldThrow should_throw) {
14834  if (object->IsJSProxy()) {
14835    return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
14836                                 from_javascript, should_throw);
14837  }
14838  return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
14839                                from_javascript, should_throw);
14840}
14841
14842
14843// ES6: 9.5.2 [[SetPrototypeOf]] (V)
14844// static
14845Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
14846                                  bool from_javascript,
14847                                  ShouldThrow should_throw) {
14848  Isolate* isolate = proxy->GetIsolate();
14849  STACK_CHECK(isolate, Nothing<bool>());
14850  Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
14851  // 1. Assert: Either Type(V) is Object or Type(V) is Null.
14852  DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
14853  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
14854  Handle<Object> handler(proxy->handler(), isolate);
14855  // 3. If handler is null, throw a TypeError exception.
14856  // 4. Assert: Type(handler) is Object.
14857  if (proxy->IsRevoked()) {
14858    isolate->Throw(*isolate->factory()->NewTypeError(
14859        MessageTemplate::kProxyRevoked, trap_name));
14860    return Nothing<bool>();
14861  }
14862  // 5. Let target be the value of the [[ProxyTarget]] internal slot.
14863  Handle<JSReceiver> target(proxy->target(), isolate);
14864  // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
14865  Handle<Object> trap;
14866  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
14867      isolate, trap,
14868      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
14869      Nothing<bool>());
14870  // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
14871  if (trap->IsUndefined(isolate)) {
14872    return JSReceiver::SetPrototype(target, value, from_javascript,
14873                                    should_throw);
14874  }
14875  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)).
14876  Handle<Object> argv[] = {target, value};
14877  Handle<Object> trap_result;
14878  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
14879      isolate, trap_result,
14880      Execution::Call(isolate, trap, handler, arraysize(argv), argv),
14881      Nothing<bool>());
14882  bool bool_trap_result = trap_result->BooleanValue();
14883  // 9. If booleanTrapResult is false, return false.
14884  if (!bool_trap_result) {
14885    RETURN_FAILURE(
14886        isolate, should_throw,
14887        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
14888  }
14889  // 10. Let extensibleTarget be ? IsExtensible(target).
14890  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
14891  if (is_extensible.IsNothing()) return Nothing<bool>();
14892  // 11. If extensibleTarget is true, return true.
14893  if (is_extensible.FromJust()) {
14894    if (bool_trap_result) return Just(true);
14895    RETURN_FAILURE(
14896        isolate, should_throw,
14897        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
14898  }
14899  // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
14900  Handle<Object> target_proto;
14901  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
14902                                   JSReceiver::GetPrototype(isolate, target),
14903                                   Nothing<bool>());
14904  // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
14905  if (bool_trap_result && !value->SameValue(*target_proto)) {
14906    isolate->Throw(*isolate->factory()->NewTypeError(
14907        MessageTemplate::kProxySetPrototypeOfNonExtensible));
14908    return Nothing<bool>();
14909  }
14910  // 14. Return true.
14911  return Just(true);
14912}
14913
14914
14915Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
14916                                   Handle<Object> value, bool from_javascript,
14917                                   ShouldThrow should_throw) {
14918  Isolate* isolate = object->GetIsolate();
14919
14920#ifdef DEBUG
14921  int size = object->Size();
14922#endif
14923
14924  if (from_javascript) {
14925    if (object->IsAccessCheckNeeded() &&
14926        !isolate->MayAccess(handle(isolate->context()), object)) {
14927      isolate->ReportFailedAccessCheck(object);
14928      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
14929      RETURN_FAILURE(isolate, should_throw,
14930                     NewTypeError(MessageTemplate::kNoAccess));
14931    }
14932  } else {
14933    DCHECK(!object->IsAccessCheckNeeded());
14934  }
14935
14936  Heap* heap = isolate->heap();
14937  // Silently ignore the change if value is not a JSObject or null.
14938  // SpiderMonkey behaves this way.
14939  if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
14940
14941  bool dictionary_elements_in_chain =
14942      object->map()->DictionaryElementsInPrototypeChainOnly();
14943
14944  bool all_extensible = object->map()->is_extensible();
14945  Handle<JSObject> real_receiver = object;
14946  if (from_javascript) {
14947    // Find the first object in the chain whose prototype object is not
14948    // hidden.
14949    PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
14950                           PrototypeIterator::END_AT_NON_HIDDEN);
14951    while (!iter.IsAtEnd()) {
14952      // Casting to JSObject is fine because hidden prototypes are never
14953      // JSProxies.
14954      real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
14955      iter.Advance();
14956      all_extensible = all_extensible && real_receiver->map()->is_extensible();
14957    }
14958  }
14959  Handle<Map> map(real_receiver->map());
14960
14961  // Nothing to do if prototype is already set.
14962  if (map->prototype() == *value) return Just(true);
14963
14964  // From 8.6.2 Object Internal Methods
14965  // ...
14966  // In addition, if [[Extensible]] is false the value of the [[Class]] and
14967  // [[Prototype]] internal properties of the object may not be modified.
14968  // ...
14969  // Implementation specific extensions that modify [[Class]], [[Prototype]]
14970  // or [[Extensible]] must not violate the invariants defined in the preceding
14971  // paragraph.
14972  if (!all_extensible) {
14973    RETURN_FAILURE(isolate, should_throw,
14974                   NewTypeError(MessageTemplate::kNonExtensibleProto, object));
14975  }
14976
14977  // Before we can set the prototype we need to be sure prototype cycles are
14978  // prevented.  It is sufficient to validate that the receiver is not in the
14979  // new prototype chain.
14980  if (value->IsJSReceiver()) {
14981    for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
14982                                kStartAtReceiver);
14983         !iter.IsAtEnd(); iter.Advance()) {
14984      if (iter.GetCurrent<JSReceiver>() == *object) {
14985        // Cycle detected.
14986        RETURN_FAILURE(isolate, should_throw,
14987                       NewTypeError(MessageTemplate::kCyclicProto));
14988      }
14989    }
14990  }
14991
14992  // Set the new prototype of the object.
14993
14994  isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
14995
14996  PrototypeOptimizationMode mode =
14997      from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
14998  Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
14999  DCHECK(new_map->prototype() == *value);
15000  JSObject::MigrateToMap(real_receiver, new_map);
15001
15002  if (from_javascript && !dictionary_elements_in_chain &&
15003      new_map->DictionaryElementsInPrototypeChainOnly()) {
15004    // If the prototype chain didn't previously have element callbacks, then
15005    // KeyedStoreICs need to be cleared to ensure any that involve this
15006    // map go generic.
15007    TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
15008  }
15009
15010  heap->ClearInstanceofCache();
15011  DCHECK(size == object->Size());
15012  return Just(true);
15013}
15014
15015
15016void JSObject::EnsureCanContainElements(Handle<JSObject> object,
15017                                        Arguments* args,
15018                                        uint32_t first_arg,
15019                                        uint32_t arg_count,
15020                                        EnsureElementsMode mode) {
15021  // Elements in |Arguments| are ordered backwards (because they're on the
15022  // stack), but the method that's called here iterates over them in forward
15023  // direction.
15024  return EnsureCanContainElements(
15025      object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
15026}
15027
15028
15029ElementsAccessor* JSObject::GetElementsAccessor() {
15030  return ElementsAccessor::ForKind(GetElementsKind());
15031}
15032
15033
15034void JSObject::ValidateElements(Handle<JSObject> object) {
15035#ifdef ENABLE_SLOW_DCHECKS
15036  if (FLAG_enable_slow_asserts) {
15037    ElementsAccessor* accessor = object->GetElementsAccessor();
15038    accessor->Validate(object);
15039  }
15040#endif
15041}
15042
15043
15044static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
15045                                        uint32_t index,
15046                                        uint32_t* new_capacity) {
15047  STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
15048                JSObject::kMaxUncheckedFastElementsLength);
15049  if (index < capacity) {
15050    *new_capacity = capacity;
15051    return false;
15052  }
15053  if (index - capacity >= JSObject::kMaxGap) return true;
15054  *new_capacity = JSObject::NewElementsCapacity(index + 1);
15055  DCHECK_LT(index, *new_capacity);
15056  if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
15057      (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
15058       object->GetHeap()->InNewSpace(object))) {
15059    return false;
15060  }
15061  // If the fast-case backing storage takes up roughly three times as
15062  // much space (in machine words) as a dictionary backing storage
15063  // would, the object should have slow elements.
15064  int used_elements = object->GetFastElementsUsage();
15065  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
15066                        SeededNumberDictionary::kEntrySize;
15067  return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
15068}
15069
15070
15071bool JSObject::WouldConvertToSlowElements(uint32_t index) {
15072  if (HasFastElements()) {
15073    Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
15074    uint32_t capacity = static_cast<uint32_t>(backing_store->length());
15075    uint32_t new_capacity;
15076    return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
15077  }
15078  return false;
15079}
15080
15081
15082static ElementsKind BestFittingFastElementsKind(JSObject* object) {
15083  if (object->HasSloppyArgumentsElements()) {
15084    return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
15085  }
15086  if (object->HasStringWrapperElements()) {
15087    return FAST_STRING_WRAPPER_ELEMENTS;
15088  }
15089  DCHECK(object->HasDictionaryElements());
15090  SeededNumberDictionary* dictionary = object->element_dictionary();
15091  ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
15092  for (int i = 0; i < dictionary->Capacity(); i++) {
15093    Object* key = dictionary->KeyAt(i);
15094    if (key->IsNumber()) {
15095      Object* value = dictionary->ValueAt(i);
15096      if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
15097      if (!value->IsSmi()) {
15098        if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
15099        kind = FAST_HOLEY_DOUBLE_ELEMENTS;
15100      }
15101    }
15102  }
15103  return kind;
15104}
15105
15106
15107static bool ShouldConvertToFastElements(JSObject* object,
15108                                        SeededNumberDictionary* dictionary,
15109                                        uint32_t index,
15110                                        uint32_t* new_capacity) {
15111  // If properties with non-standard attributes or accessors were added, we
15112  // cannot go back to fast elements.
15113  if (dictionary->requires_slow_elements()) return false;
15114
15115  // Adding a property with this index will require slow elements.
15116  if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
15117
15118  if (object->IsJSArray()) {
15119    Object* length = JSArray::cast(object)->length();
15120    if (!length->IsSmi()) return false;
15121    *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
15122  } else {
15123    *new_capacity = dictionary->max_number_key() + 1;
15124  }
15125  *new_capacity = Max(index + 1, *new_capacity);
15126
15127  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
15128                             SeededNumberDictionary::kEntrySize;
15129
15130  // Turn fast if the dictionary only saves 50% space.
15131  return 2 * dictionary_size >= *new_capacity;
15132}
15133
15134
15135// static
15136MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
15137                                             uint32_t index,
15138                                             Handle<Object> value,
15139                                             PropertyAttributes attributes) {
15140  MAYBE_RETURN_NULL(
15141      AddDataElement(object, index, value, attributes, THROW_ON_ERROR));
15142  return value;
15143}
15144
15145
15146// static
15147Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
15148                                     Handle<Object> value,
15149                                     PropertyAttributes attributes,
15150                                     ShouldThrow should_throw) {
15151  DCHECK(object->map()->is_extensible());
15152
15153  Isolate* isolate = object->GetIsolate();
15154
15155  uint32_t old_length = 0;
15156  uint32_t new_capacity = 0;
15157
15158  if (object->IsJSArray()) {
15159    CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
15160  }
15161
15162  ElementsKind kind = object->GetElementsKind();
15163  FixedArrayBase* elements = object->elements();
15164  ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15165  if (IsSloppyArgumentsElements(kind)) {
15166    elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
15167    dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15168  } else if (IsStringWrapperElementsKind(kind)) {
15169    dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
15170  }
15171
15172  if (attributes != NONE) {
15173    kind = dictionary_kind;
15174  } else if (elements->IsSeededNumberDictionary()) {
15175    kind = ShouldConvertToFastElements(*object,
15176                                       SeededNumberDictionary::cast(elements),
15177                                       index, &new_capacity)
15178               ? BestFittingFastElementsKind(*object)
15179               : dictionary_kind;  // Overwrite in case of arguments.
15180  } else if (ShouldConvertToSlowElements(
15181                 *object, static_cast<uint32_t>(elements->length()), index,
15182                 &new_capacity)) {
15183    kind = dictionary_kind;
15184  }
15185
15186  ElementsKind to = value->OptimalElementsKind();
15187  if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
15188    to = GetHoleyElementsKind(to);
15189    kind = GetHoleyElementsKind(kind);
15190  }
15191  to = GetMoreGeneralElementsKind(kind, to);
15192  ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
15193  accessor->Add(object, index, value, attributes, new_capacity);
15194
15195  uint32_t new_length = old_length;
15196  Handle<Object> new_length_handle;
15197  if (object->IsJSArray() && index >= old_length) {
15198    new_length = index + 1;
15199    new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
15200    JSArray::cast(*object)->set_length(*new_length_handle);
15201  }
15202
15203  return Just(true);
15204}
15205
15206
15207bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
15208  if (!HasFastElements()) return false;
15209  uint32_t capacity = static_cast<uint32_t>(elements()->length());
15210  uint32_t new_capacity;
15211  return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
15212         ShouldConvertToSlowElements(this, capacity, new_length - 1,
15213                                     &new_capacity);
15214}
15215
15216
15217const double AllocationSite::kPretenureRatio = 0.85;
15218
15219
15220void AllocationSite::ResetPretenureDecision() {
15221  set_pretenure_decision(kUndecided);
15222  set_memento_found_count(0);
15223  set_memento_create_count(0);
15224}
15225
15226
15227PretenureFlag AllocationSite::GetPretenureMode() {
15228  PretenureDecision mode = pretenure_decision();
15229  // Zombie objects "decide" to be untenured.
15230  return mode == kTenure ? TENURED : NOT_TENURED;
15231}
15232
15233
15234bool AllocationSite::IsNestedSite() {
15235  DCHECK(FLAG_trace_track_allocation_sites);
15236  Object* current = GetHeap()->allocation_sites_list();
15237  while (current->IsAllocationSite()) {
15238    AllocationSite* current_site = AllocationSite::cast(current);
15239    if (current_site->nested_site() == this) {
15240      return true;
15241    }
15242    current = current_site->weak_next();
15243  }
15244  return false;
15245}
15246
15247
15248void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
15249                                              ElementsKind to_kind) {
15250  Isolate* isolate = site->GetIsolate();
15251
15252  if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
15253    Handle<JSArray> transition_info =
15254        handle(JSArray::cast(site->transition_info()));
15255    ElementsKind kind = transition_info->GetElementsKind();
15256    // if kind is holey ensure that to_kind is as well.
15257    if (IsHoleyElementsKind(kind)) {
15258      to_kind = GetHoleyElementsKind(to_kind);
15259    }
15260    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15261      // If the array is huge, it's not likely to be defined in a local
15262      // function, so we shouldn't make new instances of it very often.
15263      uint32_t length = 0;
15264      CHECK(transition_info->length()->ToArrayLength(&length));
15265      if (length <= kMaximumArrayBytesToPretransition) {
15266        if (FLAG_trace_track_allocation_sites) {
15267          bool is_nested = site->IsNestedSite();
15268          PrintF(
15269              "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
15270              reinterpret_cast<void*>(*site),
15271              is_nested ? "(nested)" : "",
15272              ElementsKindToString(kind),
15273              ElementsKindToString(to_kind));
15274        }
15275        JSObject::TransitionElementsKind(transition_info, to_kind);
15276        site->dependent_code()->DeoptimizeDependentCodeGroup(
15277            isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15278      }
15279    }
15280  } else {
15281    ElementsKind kind = site->GetElementsKind();
15282    // if kind is holey ensure that to_kind is as well.
15283    if (IsHoleyElementsKind(kind)) {
15284      to_kind = GetHoleyElementsKind(to_kind);
15285    }
15286    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15287      if (FLAG_trace_track_allocation_sites) {
15288        PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
15289               reinterpret_cast<void*>(*site),
15290               ElementsKindToString(kind),
15291               ElementsKindToString(to_kind));
15292      }
15293      site->SetElementsKind(to_kind);
15294      site->dependent_code()->DeoptimizeDependentCodeGroup(
15295          isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15296    }
15297  }
15298}
15299
15300
15301const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
15302  switch (decision) {
15303    case kUndecided: return "undecided";
15304    case kDontTenure: return "don't tenure";
15305    case kMaybeTenure: return "maybe tenure";
15306    case kTenure: return "tenure";
15307    case kZombie: return "zombie";
15308    default: UNREACHABLE();
15309  }
15310  return NULL;
15311}
15312
15313
15314void JSObject::UpdateAllocationSite(Handle<JSObject> object,
15315                                    ElementsKind to_kind) {
15316  if (!object->IsJSArray()) return;
15317
15318  Heap* heap = object->GetHeap();
15319  if (!heap->InNewSpace(*object)) return;
15320
15321  Handle<AllocationSite> site;
15322  {
15323    DisallowHeapAllocation no_allocation;
15324
15325    AllocationMemento* memento =
15326        heap->FindAllocationMemento<Heap::kForRuntime>(*object);
15327    if (memento == NULL) return;
15328
15329    // Walk through to the Allocation Site
15330    site = handle(memento->GetAllocationSite());
15331  }
15332  AllocationSite::DigestTransitionFeedback(site, to_kind);
15333}
15334
15335
15336void JSObject::TransitionElementsKind(Handle<JSObject> object,
15337                                      ElementsKind to_kind) {
15338  ElementsKind from_kind = object->GetElementsKind();
15339
15340  if (IsFastHoleyElementsKind(from_kind)) {
15341    to_kind = GetHoleyElementsKind(to_kind);
15342  }
15343
15344  if (from_kind == to_kind) return;
15345
15346  // This method should never be called for any other case.
15347  DCHECK(IsFastElementsKind(from_kind));
15348  DCHECK(IsFastElementsKind(to_kind));
15349  DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
15350
15351  UpdateAllocationSite(object, to_kind);
15352  if (object->elements() == object->GetHeap()->empty_fixed_array() ||
15353      IsFastDoubleElementsKind(from_kind) ==
15354          IsFastDoubleElementsKind(to_kind)) {
15355    // No change is needed to the elements() buffer, the transition
15356    // only requires a map change.
15357    Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
15358    MigrateToMap(object, new_map);
15359    if (FLAG_trace_elements_transitions) {
15360      Handle<FixedArrayBase> elms(object->elements());
15361      PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
15362    }
15363  } else {
15364    DCHECK((IsFastSmiElementsKind(from_kind) &&
15365            IsFastDoubleElementsKind(to_kind)) ||
15366           (IsFastDoubleElementsKind(from_kind) &&
15367            IsFastObjectElementsKind(to_kind)));
15368    uint32_t c = static_cast<uint32_t>(object->elements()->length());
15369    ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
15370  }
15371}
15372
15373
15374// static
15375bool Map::IsValidElementsTransition(ElementsKind from_kind,
15376                                    ElementsKind to_kind) {
15377  // Transitions can't go backwards.
15378  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
15379    return false;
15380  }
15381
15382  // Transitions from HOLEY -> PACKED are not allowed.
15383  return !IsFastHoleyElementsKind(from_kind) ||
15384      IsFastHoleyElementsKind(to_kind);
15385}
15386
15387
15388bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
15389  Map* map = array->map();
15390  // Fast path: "length" is the first fast property of arrays. Since it's not
15391  // configurable, it's guaranteed to be the first in the descriptor array.
15392  if (!map->is_dictionary_map()) {
15393    DCHECK(map->instance_descriptors()->GetKey(0) ==
15394           array->GetHeap()->length_string());
15395    return map->instance_descriptors()->GetDetails(0).IsReadOnly();
15396  }
15397
15398  Isolate* isolate = array->GetIsolate();
15399  LookupIterator it(array, isolate->factory()->length_string(), array,
15400                    LookupIterator::OWN_SKIP_INTERCEPTOR);
15401  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
15402  return it.IsReadOnly();
15403}
15404
15405
15406bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
15407                                        uint32_t index) {
15408  uint32_t length = 0;
15409  CHECK(array->length()->ToArrayLength(&length));
15410  if (length <= index) return HasReadOnlyLength(array);
15411  return false;
15412}
15413
15414
15415template <typename BackingStore>
15416static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
15417  int limit = object->IsJSArray()
15418                  ? Smi::cast(JSArray::cast(object)->length())->value()
15419                  : store->length();
15420  int used = 0;
15421  for (int i = 0; i < limit; ++i) {
15422    if (!store->is_the_hole(i)) ++used;
15423  }
15424  return used;
15425}
15426
15427
15428int JSObject::GetFastElementsUsage() {
15429  FixedArrayBase* store = elements();
15430  switch (GetElementsKind()) {
15431    case FAST_SMI_ELEMENTS:
15432    case FAST_DOUBLE_ELEMENTS:
15433    case FAST_ELEMENTS:
15434      return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
15435                         : store->length();
15436    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
15437      store = FixedArray::cast(FixedArray::cast(store)->get(1));
15438    // Fall through.
15439    case FAST_HOLEY_SMI_ELEMENTS:
15440    case FAST_HOLEY_ELEMENTS:
15441    case FAST_STRING_WRAPPER_ELEMENTS:
15442      return FastHoleyElementsUsage(this, FixedArray::cast(store));
15443    case FAST_HOLEY_DOUBLE_ELEMENTS:
15444      if (elements()->length() == 0) return 0;
15445      return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
15446
15447    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
15448    case SLOW_STRING_WRAPPER_ELEMENTS:
15449    case DICTIONARY_ELEMENTS:
15450    case NO_ELEMENTS:
15451#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
15452    case TYPE##_ELEMENTS:                                                    \
15453
15454    TYPED_ARRAYS(TYPED_ARRAY_CASE)
15455#undef TYPED_ARRAY_CASE
15456    UNREACHABLE();
15457  }
15458  return 0;
15459}
15460
15461
15462// Certain compilers request function template instantiation when they
15463// see the definition of the other template functions in the
15464// class. This requires us to have the template functions put
15465// together, so even though this function belongs in objects-debug.cc,
15466// we keep it here instead to satisfy certain compilers.
15467#ifdef OBJECT_PRINT
15468template <typename Derived, typename Shape, typename Key>
15469void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
15470  Isolate* isolate = this->GetIsolate();
15471  int capacity = this->Capacity();
15472  for (int i = 0; i < capacity; i++) {
15473    Object* k = this->KeyAt(i);
15474    if (this->IsKey(isolate, k)) {
15475      os << "\n   ";
15476      if (k->IsString()) {
15477        String::cast(k)->StringPrint(os);
15478      } else {
15479        os << Brief(k);
15480      }
15481      os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i);
15482    }
15483  }
15484}
15485template <typename Derived, typename Shape, typename Key>
15486void Dictionary<Derived, Shape, Key>::Print() {
15487  OFStream os(stdout);
15488  Print(os);
15489}
15490#endif
15491
15492
15493template<typename Derived, typename Shape, typename Key>
15494void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
15495  Isolate* isolate = this->GetIsolate();
15496  int pos = 0;
15497  int capacity = this->Capacity();
15498  DisallowHeapAllocation no_gc;
15499  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
15500  for (int i = 0; i < capacity; i++) {
15501    Object* k = this->KeyAt(i);
15502    if (this->IsKey(isolate, k)) {
15503      elements->set(pos++, this->ValueAt(i), mode);
15504    }
15505  }
15506  DCHECK(pos == elements->length());
15507}
15508
15509
15510MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
15511                                                         bool* done) {
15512  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
15513  return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
15514}
15515
15516Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
15517                                           Handle<Name> name) {
15518  LookupIterator it = LookupIterator::PropertyOrElement(
15519      name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
15520  return HasProperty(&it);
15521}
15522
15523
15524Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
15525                                             uint32_t index) {
15526  Isolate* isolate = object->GetIsolate();
15527  LookupIterator it(isolate, object, index, object,
15528                    LookupIterator::OWN_SKIP_INTERCEPTOR);
15529  return HasProperty(&it);
15530}
15531
15532
15533Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
15534                                                   Handle<Name> name) {
15535  LookupIterator it = LookupIterator::PropertyOrElement(
15536      name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
15537  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
15538  return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
15539                               : Nothing<bool>();
15540}
15541
15542
15543void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
15544  Object* temp = get(i);
15545  set(i, get(j));
15546  set(j, temp);
15547  if (this != numbers) {
15548    temp = numbers->get(i);
15549    numbers->set(i, Smi::cast(numbers->get(j)));
15550    numbers->set(j, Smi::cast(temp));
15551  }
15552}
15553
15554
15555static void InsertionSortPairs(FixedArray* content,
15556                               FixedArray* numbers,
15557                               int len) {
15558  for (int i = 1; i < len; i++) {
15559    int j = i;
15560    while (j > 0 &&
15561           (NumberToUint32(numbers->get(j - 1)) >
15562            NumberToUint32(numbers->get(j)))) {
15563      content->SwapPairs(numbers, j - 1, j);
15564      j--;
15565    }
15566  }
15567}
15568
15569
15570void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
15571  // In-place heap sort.
15572  DCHECK(content->length() == numbers->length());
15573
15574  // Bottom-up max-heap construction.
15575  for (int i = 1; i < len; ++i) {
15576    int child_index = i;
15577    while (child_index > 0) {
15578      int parent_index = ((child_index + 1) >> 1) - 1;
15579      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
15580      uint32_t child_value = NumberToUint32(numbers->get(child_index));
15581      if (parent_value < child_value) {
15582        content->SwapPairs(numbers, parent_index, child_index);
15583      } else {
15584        break;
15585      }
15586      child_index = parent_index;
15587    }
15588  }
15589
15590  // Extract elements and create sorted array.
15591  for (int i = len - 1; i > 0; --i) {
15592    // Put max element at the back of the array.
15593    content->SwapPairs(numbers, 0, i);
15594    // Sift down the new top element.
15595    int parent_index = 0;
15596    while (true) {
15597      int child_index = ((parent_index + 1) << 1) - 1;
15598      if (child_index >= i) break;
15599      uint32_t child1_value = NumberToUint32(numbers->get(child_index));
15600      uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
15601      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
15602      if (child_index + 1 >= i || child1_value > child2_value) {
15603        if (parent_value > child1_value) break;
15604        content->SwapPairs(numbers, parent_index, child_index);
15605        parent_index = child_index;
15606      } else {
15607        if (parent_value > child2_value) break;
15608        content->SwapPairs(numbers, parent_index, child_index + 1);
15609        parent_index = child_index + 1;
15610      }
15611    }
15612  }
15613}
15614
15615
15616// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
15617void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
15618  DCHECK(this->length() == numbers->length());
15619  // For small arrays, simply use insertion sort.
15620  if (len <= 10) {
15621    InsertionSortPairs(this, numbers, len);
15622    return;
15623  }
15624  // Check the range of indices.
15625  uint32_t min_index = NumberToUint32(numbers->get(0));
15626  uint32_t max_index = min_index;
15627  uint32_t i;
15628  for (i = 1; i < len; i++) {
15629    if (NumberToUint32(numbers->get(i)) < min_index) {
15630      min_index = NumberToUint32(numbers->get(i));
15631    } else if (NumberToUint32(numbers->get(i)) > max_index) {
15632      max_index = NumberToUint32(numbers->get(i));
15633    }
15634  }
15635  if (max_index - min_index + 1 == len) {
15636    // Indices form a contiguous range, unless there are duplicates.
15637    // Do an in-place linear time sort assuming distinct numbers, but
15638    // avoid hanging in case they are not.
15639    for (i = 0; i < len; i++) {
15640      uint32_t p;
15641      uint32_t j = 0;
15642      // While the current element at i is not at its correct position p,
15643      // swap the elements at these two positions.
15644      while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
15645             j++ < len) {
15646        SwapPairs(numbers, i, p);
15647      }
15648    }
15649  } else {
15650    HeapSortPairs(this, numbers, len);
15651    return;
15652  }
15653}
15654
15655bool JSObject::WasConstructedFromApiFunction() {
15656  auto instance_type = map()->instance_type();
15657  bool is_api_object = instance_type == JS_API_OBJECT_TYPE ||
15658                       instance_type == JS_SPECIAL_API_OBJECT_TYPE;
15659#ifdef ENABLE_SLOW_DCHECKS
15660  if (FLAG_enable_slow_asserts) {
15661    Object* maybe_constructor = map()->GetConstructor();
15662    if (!maybe_constructor->IsJSFunction()) return false;
15663    JSFunction* constructor = JSFunction::cast(maybe_constructor);
15664    if (constructor->shared()->IsApiFunction()) {
15665      DCHECK(is_api_object);
15666    } else {
15667      DCHECK(!is_api_object);
15668    }
15669  }
15670#endif
15671  return is_api_object;
15672}
15673
15674MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
15675                                                Handle<Object> object) {
15676  if (*object == isolate->heap()->undefined_value()) {
15677    return isolate->factory()->undefined_to_string();
15678  }
15679  if (*object == isolate->heap()->null_value()) {
15680    return isolate->factory()->null_to_string();
15681  }
15682
15683  Handle<JSReceiver> receiver =
15684      Object::ToObject(isolate, object).ToHandleChecked();
15685
15686  // For proxies, we must check IsArray() before get(toStringTag) to comply
15687  // with the specification
15688  Maybe<bool> is_array = Nothing<bool>();
15689  InstanceType instance_type = receiver->map()->instance_type();
15690  if (instance_type == JS_PROXY_TYPE) {
15691    is_array = Object::IsArray(receiver);
15692    MAYBE_RETURN(is_array, MaybeHandle<String>());
15693  }
15694
15695  Handle<String> tag;
15696  Handle<Object> to_string_tag;
15697  ASSIGN_RETURN_ON_EXCEPTION(
15698      isolate, to_string_tag,
15699      JSReceiver::GetProperty(receiver,
15700                              isolate->factory()->to_string_tag_symbol()),
15701      String);
15702  if (to_string_tag->IsString()) {
15703    tag = Handle<String>::cast(to_string_tag);
15704  } else {
15705    switch (instance_type) {
15706      case JS_API_OBJECT_TYPE:
15707      case JS_SPECIAL_API_OBJECT_TYPE:
15708        tag = handle(receiver->class_name(), isolate);
15709        break;
15710      case JS_ARGUMENTS_TYPE:
15711        return isolate->factory()->arguments_to_string();
15712      case JS_ARRAY_TYPE:
15713        return isolate->factory()->array_to_string();
15714      case JS_BOUND_FUNCTION_TYPE:
15715      case JS_FUNCTION_TYPE:
15716        return isolate->factory()->function_to_string();
15717      case JS_ERROR_TYPE:
15718        return isolate->factory()->error_to_string();
15719      case JS_DATE_TYPE:
15720        return isolate->factory()->date_to_string();
15721      case JS_REGEXP_TYPE:
15722        return isolate->factory()->regexp_to_string();
15723      case JS_PROXY_TYPE: {
15724        if (is_array.FromJust()) {
15725          return isolate->factory()->array_to_string();
15726        }
15727        if (receiver->IsCallable()) {
15728          return isolate->factory()->function_to_string();
15729        }
15730        return isolate->factory()->object_to_string();
15731      }
15732      case JS_VALUE_TYPE: {
15733        Object* value = JSValue::cast(*receiver)->value();
15734        if (value->IsString()) {
15735          return isolate->factory()->string_to_string();
15736        }
15737        if (value->IsNumber()) {
15738          return isolate->factory()->number_to_string();
15739        }
15740        if (value->IsBoolean()) {
15741          return isolate->factory()->boolean_to_string();
15742        }
15743        if (value->IsSymbol()) {
15744          return isolate->factory()->object_to_string();
15745        }
15746        UNREACHABLE();
15747        tag = handle(receiver->class_name(), isolate);
15748        break;
15749      }
15750      default:
15751        return isolate->factory()->object_to_string();
15752    }
15753  }
15754
15755  IncrementalStringBuilder builder(isolate);
15756  builder.AppendCString("[object ");
15757  builder.AppendString(tag);
15758  builder.AppendCharacter(']');
15759  return builder.Finish();
15760}
15761
15762const char* Symbol::PrivateSymbolToName() const {
15763  Heap* heap = GetIsolate()->heap();
15764#define SYMBOL_CHECK_AND_PRINT(name) \
15765  if (this == heap->name()) return #name;
15766  PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
15767#undef SYMBOL_CHECK_AND_PRINT
15768  return "UNKNOWN";
15769}
15770
15771
15772void Symbol::SymbolShortPrint(std::ostream& os) {
15773  os << "<Symbol:";
15774  if (!name()->IsUndefined(GetIsolate())) {
15775    os << " ";
15776    HeapStringAllocator allocator;
15777    StringStream accumulator(&allocator);
15778    String::cast(name())->StringShortPrint(&accumulator, false);
15779    os << accumulator.ToCString().get();
15780  } else {
15781    os << " (" << PrivateSymbolToName() << ")";
15782  }
15783  os << ">";
15784}
15785
15786
15787// StringSharedKeys are used as keys in the eval cache.
15788class StringSharedKey : public HashTableKey {
15789 public:
15790  StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
15791                  LanguageMode language_mode, int scope_position)
15792      : source_(source),
15793        shared_(shared),
15794        language_mode_(language_mode),
15795        scope_position_(scope_position) {}
15796
15797  bool IsMatch(Object* other) override {
15798    DisallowHeapAllocation no_allocation;
15799    if (!other->IsFixedArray()) {
15800      if (!other->IsNumber()) return false;
15801      uint32_t other_hash = static_cast<uint32_t>(other->Number());
15802      return Hash() == other_hash;
15803    }
15804    FixedArray* other_array = FixedArray::cast(other);
15805    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
15806    if (shared != *shared_) return false;
15807    int language_unchecked = Smi::cast(other_array->get(2))->value();
15808    DCHECK(is_valid_language_mode(language_unchecked));
15809    LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
15810    if (language_mode != language_mode_) return false;
15811    int scope_position = Smi::cast(other_array->get(3))->value();
15812    if (scope_position != scope_position_) return false;
15813    String* source = String::cast(other_array->get(1));
15814    return source->Equals(*source_);
15815  }
15816
15817  static uint32_t StringSharedHashHelper(String* source,
15818                                         SharedFunctionInfo* shared,
15819                                         LanguageMode language_mode,
15820                                         int scope_position) {
15821    uint32_t hash = source->Hash();
15822    if (shared->HasSourceCode()) {
15823      // Instead of using the SharedFunctionInfo pointer in the hash
15824      // code computation, we use a combination of the hash of the
15825      // script source code and the start position of the calling scope.
15826      // We do this to ensure that the cache entries can survive garbage
15827      // collection.
15828      Script* script(Script::cast(shared->script()));
15829      hash ^= String::cast(script->source())->Hash();
15830      STATIC_ASSERT(LANGUAGE_END == 3);
15831      if (is_strict(language_mode)) hash ^= 0x8000;
15832      hash += scope_position;
15833    }
15834    return hash;
15835  }
15836
15837  uint32_t Hash() override {
15838    return StringSharedHashHelper(*source_, *shared_, language_mode_,
15839                                  scope_position_);
15840  }
15841
15842  uint32_t HashForObject(Object* obj) override {
15843    DisallowHeapAllocation no_allocation;
15844    if (obj->IsNumber()) {
15845      return static_cast<uint32_t>(obj->Number());
15846    }
15847    FixedArray* other_array = FixedArray::cast(obj);
15848    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
15849    String* source = String::cast(other_array->get(1));
15850    int language_unchecked = Smi::cast(other_array->get(2))->value();
15851    DCHECK(is_valid_language_mode(language_unchecked));
15852    LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
15853    int scope_position = Smi::cast(other_array->get(3))->value();
15854    return StringSharedHashHelper(source, shared, language_mode,
15855                                  scope_position);
15856  }
15857
15858
15859  Handle<Object> AsHandle(Isolate* isolate) override {
15860    Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
15861    array->set(0, *shared_);
15862    array->set(1, *source_);
15863    array->set(2, Smi::FromInt(language_mode_));
15864    array->set(3, Smi::FromInt(scope_position_));
15865    return array;
15866  }
15867
15868 private:
15869  Handle<String> source_;
15870  Handle<SharedFunctionInfo> shared_;
15871  LanguageMode language_mode_;
15872  int scope_position_;
15873};
15874
15875
15876namespace {
15877
15878JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
15879  JSRegExp::Flags value = JSRegExp::kNone;
15880  int length = flags->length();
15881  // A longer flags string cannot be valid.
15882  if (length > 5) return JSRegExp::Flags(0);
15883  for (int i = 0; i < length; i++) {
15884    JSRegExp::Flag flag = JSRegExp::kNone;
15885    switch (flags->Get(i)) {
15886      case 'g':
15887        flag = JSRegExp::kGlobal;
15888        break;
15889      case 'i':
15890        flag = JSRegExp::kIgnoreCase;
15891        break;
15892      case 'm':
15893        flag = JSRegExp::kMultiline;
15894        break;
15895      case 'u':
15896        flag = JSRegExp::kUnicode;
15897        break;
15898      case 'y':
15899        flag = JSRegExp::kSticky;
15900        break;
15901      default:
15902        return JSRegExp::Flags(0);
15903    }
15904    // Duplicate flag.
15905    if (value & flag) return JSRegExp::Flags(0);
15906    value |= flag;
15907  }
15908  *success = true;
15909  return value;
15910}
15911
15912}  // namespace
15913
15914
15915// static
15916MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) {
15917  Isolate* isolate = pattern->GetIsolate();
15918  Handle<JSFunction> constructor = isolate->regexp_function();
15919  Handle<JSRegExp> regexp =
15920      Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
15921
15922  return JSRegExp::Initialize(regexp, pattern, flags);
15923}
15924
15925
15926// static
15927Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
15928  Isolate* const isolate = regexp->GetIsolate();
15929  return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
15930}
15931
15932
15933template <typename Char>
15934inline int CountRequiredEscapes(Handle<String> source) {
15935  DisallowHeapAllocation no_gc;
15936  int escapes = 0;
15937  Vector<const Char> src = source->GetCharVector<Char>();
15938  for (int i = 0; i < src.length(); i++) {
15939    if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++;
15940  }
15941  return escapes;
15942}
15943
15944
15945template <typename Char, typename StringType>
15946inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
15947                                                   Handle<StringType> result) {
15948  DisallowHeapAllocation no_gc;
15949  Vector<const Char> src = source->GetCharVector<Char>();
15950  Vector<Char> dst(result->GetChars(), result->length());
15951  int s = 0;
15952  int d = 0;
15953  while (s < src.length()) {
15954    if (src[s] == '/' && (s == 0 || src[s - 1] != '\\')) dst[d++] = '\\';
15955    dst[d++] = src[s++];
15956  }
15957  DCHECK_EQ(result->length(), d);
15958  return result;
15959}
15960
15961
15962MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
15963                                       Handle<String> source) {
15964  String::Flatten(source);
15965  if (source->length() == 0) return isolate->factory()->query_colon_string();
15966  bool one_byte = source->IsOneByteRepresentationUnderneath();
15967  int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
15968                         : CountRequiredEscapes<uc16>(source);
15969  if (escapes == 0) return source;
15970  int length = source->length() + escapes;
15971  if (one_byte) {
15972    Handle<SeqOneByteString> result;
15973    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
15974                               isolate->factory()->NewRawOneByteString(length),
15975                               String);
15976    return WriteEscapedRegExpSource<uint8_t>(source, result);
15977  } else {
15978    Handle<SeqTwoByteString> result;
15979    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
15980                               isolate->factory()->NewRawTwoByteString(length),
15981                               String);
15982    return WriteEscapedRegExpSource<uc16>(source, result);
15983  }
15984}
15985
15986
15987// static
15988MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
15989                                           Handle<String> source,
15990                                           Handle<String> flags_string) {
15991  Isolate* isolate = source->GetIsolate();
15992  bool success = false;
15993  Flags flags = RegExpFlagsFromString(flags_string, &success);
15994  if (!success) {
15995    THROW_NEW_ERROR(
15996        isolate,
15997        NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
15998        JSRegExp);
15999  }
16000  return Initialize(regexp, source, flags);
16001}
16002
16003
16004// static
16005MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16006                                           Handle<String> source, Flags flags) {
16007  Isolate* isolate = regexp->GetIsolate();
16008  Factory* factory = isolate->factory();
16009  // If source is the empty string we set it to "(?:)" instead as
16010  // suggested by ECMA-262, 5th, section 15.10.4.1.
16011  if (source->length() == 0) source = factory->query_colon_string();
16012
16013  Handle<String> escaped_source;
16014  ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
16015                             EscapeRegExpSource(isolate, source), JSRegExp);
16016
16017  RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
16018                      JSRegExp);
16019
16020  regexp->set_source(*escaped_source);
16021  regexp->set_flags(Smi::FromInt(flags));
16022
16023  Map* map = regexp->map();
16024  Object* constructor = map->GetConstructor();
16025  if (constructor->IsJSFunction() &&
16026      JSFunction::cast(constructor)->initial_map() == map) {
16027    // If we still have the original map, set in-object properties directly.
16028    regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
16029                                  Smi::FromInt(0), SKIP_WRITE_BARRIER);
16030  } else {
16031    // Map has changed, so use generic, but slower, method.
16032    PropertyAttributes writable =
16033        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
16034    JSObject::SetOwnPropertyIgnoreAttributes(
16035        regexp, factory->last_index_string(),
16036        Handle<Smi>(Smi::FromInt(0), isolate), writable)
16037        .Check();
16038  }
16039
16040  return regexp;
16041}
16042
16043
16044// RegExpKey carries the source and flags of a regular expression as key.
16045class RegExpKey : public HashTableKey {
16046 public:
16047  RegExpKey(Handle<String> string, JSRegExp::Flags flags)
16048      : string_(string), flags_(Smi::FromInt(flags)) {}
16049
16050  // Rather than storing the key in the hash table, a pointer to the
16051  // stored value is stored where the key should be.  IsMatch then
16052  // compares the search key to the found object, rather than comparing
16053  // a key to a key.
16054  bool IsMatch(Object* obj) override {
16055    FixedArray* val = FixedArray::cast(obj);
16056    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
16057        && (flags_ == val->get(JSRegExp::kFlagsIndex));
16058  }
16059
16060  uint32_t Hash() override { return RegExpHash(*string_, flags_); }
16061
16062  Handle<Object> AsHandle(Isolate* isolate) override {
16063    // Plain hash maps, which is where regexp keys are used, don't
16064    // use this function.
16065    UNREACHABLE();
16066    return MaybeHandle<Object>().ToHandleChecked();
16067  }
16068
16069  uint32_t HashForObject(Object* obj) override {
16070    FixedArray* val = FixedArray::cast(obj);
16071    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
16072                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
16073  }
16074
16075  static uint32_t RegExpHash(String* string, Smi* flags) {
16076    return string->Hash() + flags->value();
16077  }
16078
16079  Handle<String> string_;
16080  Smi* flags_;
16081};
16082
16083
16084Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
16085  if (hash_field_ == 0) Hash();
16086  return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
16087}
16088
16089
16090Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
16091  if (hash_field_ == 0) Hash();
16092  return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
16093}
16094
16095
16096Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
16097  if (hash_field_ == 0) Hash();
16098  return isolate->factory()->NewOneByteInternalizedSubString(
16099      string_, from_, length_, hash_field_);
16100}
16101
16102
16103bool SeqOneByteSubStringKey::IsMatch(Object* string) {
16104  Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
16105  return String::cast(string)->IsOneByteEqualTo(chars);
16106}
16107
16108
16109// InternalizedStringKey carries a string/internalized-string object as key.
16110class InternalizedStringKey : public HashTableKey {
16111 public:
16112  explicit InternalizedStringKey(Handle<String> string)
16113      : string_(String::Flatten(string)) {}
16114
16115  bool IsMatch(Object* string) override {
16116    return String::cast(string)->Equals(*string_);
16117  }
16118
16119  uint32_t Hash() override { return string_->Hash(); }
16120
16121  uint32_t HashForObject(Object* other) override {
16122    return String::cast(other)->Hash();
16123  }
16124
16125  Handle<Object> AsHandle(Isolate* isolate) override {
16126    // Internalize the string if possible.
16127    MaybeHandle<Map> maybe_map =
16128        isolate->factory()->InternalizedStringMapForString(string_);
16129    Handle<Map> map;
16130    if (maybe_map.ToHandle(&map)) {
16131      string_->set_map_no_write_barrier(*map);
16132      DCHECK(string_->IsInternalizedString());
16133      return string_;
16134    }
16135    // Otherwise allocate a new internalized string.
16136    return isolate->factory()->NewInternalizedStringImpl(
16137        string_, string_->length(), string_->hash_field());
16138  }
16139
16140  static uint32_t StringHash(Object* obj) {
16141    return String::cast(obj)->Hash();
16142  }
16143
16144  Handle<String> string_;
16145};
16146
16147
16148template<typename Derived, typename Shape, typename Key>
16149void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
16150  BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
16151}
16152
16153
16154template<typename Derived, typename Shape, typename Key>
16155void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
16156  BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
16157                                      kHeaderSize + length() * kPointerSize, v);
16158}
16159
16160
16161template<typename Derived, typename Shape, typename Key>
16162Handle<Derived> HashTable<Derived, Shape, Key>::New(
16163    Isolate* isolate,
16164    int at_least_space_for,
16165    MinimumCapacity capacity_option,
16166    PretenureFlag pretenure) {
16167  DCHECK(0 <= at_least_space_for);
16168  DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
16169
16170  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
16171                     ? at_least_space_for
16172                     : ComputeCapacity(at_least_space_for);
16173  if (capacity > HashTable::kMaxCapacity) {
16174    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
16175  }
16176
16177  Factory* factory = isolate->factory();
16178  int length = EntryToIndex(capacity);
16179  Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
16180  array->set_map_no_write_barrier(*factory->hash_table_map());
16181  Handle<Derived> table = Handle<Derived>::cast(array);
16182
16183  table->SetNumberOfElements(0);
16184  table->SetNumberOfDeletedElements(0);
16185  table->SetCapacity(capacity);
16186  return table;
16187}
16188
16189
16190// Find entry for key otherwise return kNotFound.
16191template <typename Derived, typename Shape>
16192int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
16193  if (!key->IsUniqueName()) {
16194    return DerivedDictionary::FindEntry(key);
16195  }
16196
16197  // Optimized for unique names. Knowledge of the key type allows:
16198  // 1. Move the check if the key is unique out of the loop.
16199  // 2. Avoid comparing hash codes in unique-to-unique comparison.
16200  // 3. Detect a case when a dictionary key is not unique but the key is.
16201  //    In case of positive result the dictionary key may be replaced by the
16202  //    internalized string with minimal performance penalty. It gives a chance
16203  //    to perform further lookups in code stubs (and significant performance
16204  //    boost a certain style of code).
16205
16206  // EnsureCapacity will guarantee the hash table is never full.
16207  uint32_t capacity = this->Capacity();
16208  uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
16209  uint32_t count = 1;
16210  Isolate* isolate = this->GetIsolate();
16211  while (true) {
16212    Object* element = this->KeyAt(entry);
16213    if (element->IsUndefined(isolate)) break;  // Empty entry.
16214    if (*key == element) return entry;
16215    DCHECK(element->IsTheHole(isolate) || element->IsUniqueName());
16216    entry = Derived::NextProbe(entry, count++, capacity);
16217  }
16218  return Derived::kNotFound;
16219}
16220
16221
16222template<typename Derived, typename Shape, typename Key>
16223void HashTable<Derived, Shape, Key>::Rehash(
16224    Handle<Derived> new_table,
16225    Key key) {
16226  DCHECK(NumberOfElements() < new_table->Capacity());
16227
16228  DisallowHeapAllocation no_gc;
16229  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
16230
16231  // Copy prefix to new array.
16232  for (int i = kPrefixStartIndex;
16233       i < kPrefixStartIndex + Shape::kPrefixSize;
16234       i++) {
16235    new_table->set(i, get(i), mode);
16236  }
16237
16238  // Rehash the elements.
16239  int capacity = this->Capacity();
16240  Heap* heap = new_table->GetHeap();
16241  Object* the_hole = heap->the_hole_value();
16242  Object* undefined = heap->undefined_value();
16243  for (int i = 0; i < capacity; i++) {
16244    uint32_t from_index = EntryToIndex(i);
16245    Object* k = this->get(from_index);
16246    if (k != the_hole && k != undefined) {
16247      uint32_t hash = this->HashForObject(key, k);
16248      uint32_t insertion_index =
16249          EntryToIndex(new_table->FindInsertionEntry(hash));
16250      for (int j = 0; j < Shape::kEntrySize; j++) {
16251        new_table->set(insertion_index + j, get(from_index + j), mode);
16252      }
16253    }
16254  }
16255  new_table->SetNumberOfElements(NumberOfElements());
16256  new_table->SetNumberOfDeletedElements(0);
16257}
16258
16259
16260template<typename Derived, typename Shape, typename Key>
16261uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
16262    Key key,
16263    Object* k,
16264    int probe,
16265    uint32_t expected) {
16266  uint32_t hash = this->HashForObject(key, k);
16267  uint32_t capacity = this->Capacity();
16268  uint32_t entry = FirstProbe(hash, capacity);
16269  for (int i = 1; i < probe; i++) {
16270    if (entry == expected) return expected;
16271    entry = NextProbe(entry, i, capacity);
16272  }
16273  return entry;
16274}
16275
16276
16277template<typename Derived, typename Shape, typename Key>
16278void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
16279                                          uint32_t entry2,
16280                                          WriteBarrierMode mode) {
16281  int index1 = EntryToIndex(entry1);
16282  int index2 = EntryToIndex(entry2);
16283  Object* temp[Shape::kEntrySize];
16284  for (int j = 0; j < Shape::kEntrySize; j++) {
16285    temp[j] = get(index1 + j);
16286  }
16287  for (int j = 0; j < Shape::kEntrySize; j++) {
16288    set(index1 + j, get(index2 + j), mode);
16289  }
16290  for (int j = 0; j < Shape::kEntrySize; j++) {
16291    set(index2 + j, temp[j], mode);
16292  }
16293}
16294
16295
16296template<typename Derived, typename Shape, typename Key>
16297void HashTable<Derived, Shape, Key>::Rehash(Key key) {
16298  DisallowHeapAllocation no_gc;
16299  WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
16300  Isolate* isolate = GetIsolate();
16301  uint32_t capacity = Capacity();
16302  bool done = false;
16303  for (int probe = 1; !done; probe++) {
16304    // All elements at entries given by one of the first _probe_ probes
16305    // are placed correctly. Other elements might need to be moved.
16306    done = true;
16307    for (uint32_t current = 0; current < capacity; current++) {
16308      Object* current_key = KeyAt(current);
16309      if (IsKey(isolate, current_key)) {
16310        uint32_t target = EntryForProbe(key, current_key, probe, current);
16311        if (current == target) continue;
16312        Object* target_key = KeyAt(target);
16313        if (!IsKey(target_key) ||
16314            EntryForProbe(key, target_key, probe, target) != target) {
16315          // Put the current element into the correct position.
16316          Swap(current, target, mode);
16317          // The other element will be processed on the next iteration.
16318          current--;
16319        } else {
16320          // The place for the current element is occupied. Leave the element
16321          // for the next probe.
16322          done = false;
16323        }
16324      }
16325    }
16326  }
16327  // Wipe deleted entries.
16328  Object* the_hole = isolate->heap()->the_hole_value();
16329  Object* undefined = isolate->heap()->undefined_value();
16330  for (uint32_t current = 0; current < capacity; current++) {
16331    if (KeyAt(current) == the_hole) {
16332      set(EntryToIndex(current) + Derived::kEntryKeyIndex, undefined);
16333    }
16334  }
16335  SetNumberOfDeletedElements(0);
16336}
16337
16338
16339template<typename Derived, typename Shape, typename Key>
16340Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
16341    Handle<Derived> table,
16342    int n,
16343    Key key,
16344    PretenureFlag pretenure) {
16345  Isolate* isolate = table->GetIsolate();
16346  int capacity = table->Capacity();
16347  int nof = table->NumberOfElements() + n;
16348
16349  if (table->HasSufficientCapacityToAdd(n)) return table;
16350
16351  const int kMinCapacityForPretenure = 256;
16352  bool should_pretenure = pretenure == TENURED ||
16353      ((capacity > kMinCapacityForPretenure) &&
16354          !isolate->heap()->InNewSpace(*table));
16355  Handle<Derived> new_table = HashTable::New(
16356      isolate,
16357      nof * 2,
16358      USE_DEFAULT_MINIMUM_CAPACITY,
16359      should_pretenure ? TENURED : NOT_TENURED);
16360
16361  table->Rehash(new_table, key);
16362  return new_table;
16363}
16364
16365template <typename Derived, typename Shape, typename Key>
16366bool HashTable<Derived, Shape, Key>::HasSufficientCapacityToAdd(
16367    int number_of_additional_elements) {
16368  int capacity = Capacity();
16369  int nof = NumberOfElements() + number_of_additional_elements;
16370  int nod = NumberOfDeletedElements();
16371  // Return true if:
16372  //   50% is still free after adding number_of_additional_elements elements and
16373  //   at most 50% of the free elements are deleted elements.
16374  if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
16375    int needed_free = nof >> 1;
16376    if (nof + needed_free <= capacity) return true;
16377  }
16378  return false;
16379}
16380
16381
16382template<typename Derived, typename Shape, typename Key>
16383Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
16384                                                       Key key) {
16385  int capacity = table->Capacity();
16386  int nof = table->NumberOfElements();
16387
16388  // Shrink to fit the number of elements if only a quarter of the
16389  // capacity is filled with elements.
16390  if (nof > (capacity >> 2)) return table;
16391  // Allocate a new dictionary with room for at least the current
16392  // number of elements. The allocation method will make sure that
16393  // there is extra room in the dictionary for additions. Don't go
16394  // lower than room for 16 elements.
16395  int at_least_room_for = nof;
16396  if (at_least_room_for < 16) return table;
16397
16398  Isolate* isolate = table->GetIsolate();
16399  const int kMinCapacityForPretenure = 256;
16400  bool pretenure =
16401      (at_least_room_for > kMinCapacityForPretenure) &&
16402      !isolate->heap()->InNewSpace(*table);
16403  Handle<Derived> new_table = HashTable::New(
16404      isolate,
16405      at_least_room_for,
16406      USE_DEFAULT_MINIMUM_CAPACITY,
16407      pretenure ? TENURED : NOT_TENURED);
16408
16409  table->Rehash(new_table, key);
16410  return new_table;
16411}
16412
16413
16414template<typename Derived, typename Shape, typename Key>
16415uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
16416  uint32_t capacity = Capacity();
16417  uint32_t entry = FirstProbe(hash, capacity);
16418  uint32_t count = 1;
16419  // EnsureCapacity will guarantee the hash table is never full.
16420  Isolate* isolate = GetIsolate();
16421  while (true) {
16422    Object* element = KeyAt(entry);
16423    if (!IsKey(isolate, element)) break;
16424    entry = NextProbe(entry, count++, capacity);
16425  }
16426  return entry;
16427}
16428
16429
16430// Force instantiation of template instances class.
16431// Please note this list is compiler dependent.
16432
16433template class HashTable<StringTable, StringTableShape, HashTableKey*>;
16434
16435template class HashTable<CompilationCacheTable,
16436                         CompilationCacheShape,
16437                         HashTableKey*>;
16438
16439template class HashTable<ObjectHashTable,
16440                         ObjectHashTableShape,
16441                         Handle<Object> >;
16442
16443template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
16444
16445template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
16446
16447template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
16448                          Handle<Name> >;
16449
16450template class Dictionary<SeededNumberDictionary,
16451                          SeededNumberDictionaryShape,
16452                          uint32_t>;
16453
16454template class Dictionary<UnseededNumberDictionary,
16455                          UnseededNumberDictionaryShape,
16456                          uint32_t>;
16457
16458template Handle<SeededNumberDictionary>
16459Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16460    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
16461
16462template Handle<UnseededNumberDictionary>
16463Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
16464    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
16465
16466template Handle<NameDictionary>
16467Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
16468    New(Isolate*, int n, PretenureFlag pretenure);
16469
16470template Handle<GlobalDictionary>
16471Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::New(
16472    Isolate*, int n, PretenureFlag pretenure);
16473
16474template Handle<SeededNumberDictionary>
16475Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16476    AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
16477
16478template Handle<UnseededNumberDictionary>
16479Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
16480    AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
16481
16482template Object*
16483Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16484    SlowReverseLookup(Object* value);
16485
16486template Object*
16487Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
16488    SlowReverseLookup(Object* value);
16489
16490template Handle<Object>
16491Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
16492    Handle<NameDictionary>, int);
16493
16494template Handle<Object>
16495Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
16496           uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
16497
16498template Handle<Object>
16499Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
16500           uint32_t>::DeleteProperty(Handle<UnseededNumberDictionary>, int);
16501
16502template Handle<NameDictionary>
16503HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
16504    New(Isolate*, int, MinimumCapacity, PretenureFlag);
16505
16506template Handle<NameDictionary>
16507HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
16508    Shrink(Handle<NameDictionary>, Handle<Name>);
16509
16510template Handle<SeededNumberDictionary>
16511HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16512    Shrink(Handle<SeededNumberDictionary>, uint32_t);
16513
16514template Handle<UnseededNumberDictionary>
16515    HashTable<UnseededNumberDictionary, UnseededNumberDictionaryShape,
16516              uint32_t>::Shrink(Handle<UnseededNumberDictionary>, uint32_t);
16517
16518template Handle<NameDictionary>
16519Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
16520    Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
16521
16522template Handle<GlobalDictionary>
16523    Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Add(
16524        Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
16525        PropertyDetails);
16526
16527template Handle<FixedArray> Dictionary<
16528    NameDictionary, NameDictionaryShape,
16529    Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
16530
16531template Handle<FixedArray> Dictionary<
16532    NameDictionary, NameDictionaryShape,
16533    Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
16534
16535template Handle<SeededNumberDictionary>
16536Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16537    Add(Handle<SeededNumberDictionary>,
16538        uint32_t,
16539        Handle<Object>,
16540        PropertyDetails);
16541
16542template Handle<UnseededNumberDictionary>
16543Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
16544    Add(Handle<UnseededNumberDictionary>,
16545        uint32_t,
16546        Handle<Object>,
16547        PropertyDetails);
16548
16549template Handle<SeededNumberDictionary>
16550Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
16551    EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
16552
16553template Handle<UnseededNumberDictionary>
16554Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
16555    EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
16556
16557template void Dictionary<NameDictionary, NameDictionaryShape,
16558                         Handle<Name> >::SetRequiresCopyOnCapacityChange();
16559
16560template Handle<NameDictionary>
16561Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
16562    EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
16563
16564template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
16565                       uint32_t>::FindEntry(uint32_t);
16566
16567template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
16568    Handle<Name>);
16569
16570template int Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
16571    NumberOfElementsFilterAttributes(PropertyFilter filter);
16572
16573template int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::
16574    NumberOfElementsFilterAttributes(PropertyFilter filter);
16575
16576template void Dictionary<GlobalDictionary, GlobalDictionaryShape,
16577                         Handle<Name>>::CopyEnumKeysTo(FixedArray* storage);
16578
16579template void Dictionary<NameDictionary, NameDictionaryShape,
16580                         Handle<Name>>::CopyEnumKeysTo(FixedArray* storage);
16581
16582template void
16583Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
16584    CollectKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
16585                                    Handle<Name>>>
16586                      dictionary,
16587                  KeyAccumulator* keys, PropertyFilter filter);
16588
16589template void
16590Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CollectKeysTo(
16591    Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
16592        dictionary,
16593    KeyAccumulator* keys, PropertyFilter filter);
16594
16595Handle<Object> JSObject::PrepareSlowElementsForSort(
16596    Handle<JSObject> object, uint32_t limit) {
16597  DCHECK(object->HasDictionaryElements());
16598  Isolate* isolate = object->GetIsolate();
16599  // Must stay in dictionary mode, either because of requires_slow_elements,
16600  // or because we are not going to sort (and therefore compact) all of the
16601  // elements.
16602  Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
16603  Handle<SeededNumberDictionary> new_dict =
16604      SeededNumberDictionary::New(isolate, dict->NumberOfElements());
16605
16606  uint32_t pos = 0;
16607  uint32_t undefs = 0;
16608  int capacity = dict->Capacity();
16609  Handle<Smi> bailout(Smi::FromInt(-1), isolate);
16610  // Entry to the new dictionary does not cause it to grow, as we have
16611  // allocated one that is large enough for all entries.
16612  DisallowHeapAllocation no_gc;
16613  for (int i = 0; i < capacity; i++) {
16614    Object* k = dict->KeyAt(i);
16615    if (!dict->IsKey(isolate, k)) continue;
16616
16617    DCHECK(k->IsNumber());
16618    DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
16619    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
16620    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
16621
16622    HandleScope scope(isolate);
16623    Handle<Object> value(dict->ValueAt(i), isolate);
16624    PropertyDetails details = dict->DetailsAt(i);
16625    if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
16626      // Bail out and do the sorting of undefineds and array holes in JS.
16627      // Also bail out if the element is not supposed to be moved.
16628      return bailout;
16629    }
16630
16631    uint32_t key = NumberToUint32(k);
16632    if (key < limit) {
16633      if (value->IsUndefined(isolate)) {
16634        undefs++;
16635      } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
16636        // Adding an entry with the key beyond smi-range requires
16637        // allocation. Bailout.
16638        return bailout;
16639      } else {
16640        Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
16641            new_dict, pos, value, details, object->map()->is_prototype_map());
16642        DCHECK(result.is_identical_to(new_dict));
16643        USE(result);
16644        pos++;
16645      }
16646    } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
16647      // Adding an entry with the key beyond smi-range requires
16648      // allocation. Bailout.
16649      return bailout;
16650    } else {
16651      Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
16652          new_dict, key, value, details, object->map()->is_prototype_map());
16653      DCHECK(result.is_identical_to(new_dict));
16654      USE(result);
16655    }
16656  }
16657
16658  uint32_t result = pos;
16659  PropertyDetails no_details = PropertyDetails::Empty();
16660  while (undefs > 0) {
16661    if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
16662      // Adding an entry with the key beyond smi-range requires
16663      // allocation. Bailout.
16664      return bailout;
16665    }
16666    HandleScope scope(isolate);
16667    Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
16668        new_dict, pos, isolate->factory()->undefined_value(), no_details,
16669        object->map()->is_prototype_map());
16670    DCHECK(result.is_identical_to(new_dict));
16671    USE(result);
16672    pos++;
16673    undefs--;
16674  }
16675
16676  object->set_elements(*new_dict);
16677
16678  AllowHeapAllocation allocate_return_value;
16679  return isolate->factory()->NewNumberFromUint(result);
16680}
16681
16682
16683// Collects all defined (non-hole) and non-undefined (array) elements at
16684// the start of the elements array.
16685// If the object is in dictionary mode, it is converted to fast elements
16686// mode.
16687Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
16688                                                uint32_t limit) {
16689  Isolate* isolate = object->GetIsolate();
16690  if (object->HasSloppyArgumentsElements()) {
16691    return handle(Smi::FromInt(-1), isolate);
16692  }
16693
16694  if (object->HasStringWrapperElements()) {
16695    int len = String::cast(Handle<JSValue>::cast(object)->value())->length();
16696    return handle(Smi::FromInt(len), isolate);
16697  }
16698
16699  if (object->HasDictionaryElements()) {
16700    // Convert to fast elements containing only the existing properties.
16701    // Ordering is irrelevant, since we are going to sort anyway.
16702    Handle<SeededNumberDictionary> dict(object->element_dictionary());
16703    if (object->IsJSArray() || dict->requires_slow_elements() ||
16704        dict->max_number_key() >= limit) {
16705      return JSObject::PrepareSlowElementsForSort(object, limit);
16706    }
16707    // Convert to fast elements.
16708
16709    Handle<Map> new_map =
16710        JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
16711
16712    PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
16713        NOT_TENURED: TENURED;
16714    Handle<FixedArray> fast_elements =
16715        isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
16716    dict->CopyValuesTo(*fast_elements);
16717    JSObject::ValidateElements(object);
16718
16719    JSObject::SetMapAndElements(object, new_map, fast_elements);
16720  } else if (object->HasFixedTypedArrayElements()) {
16721    // Typed arrays cannot have holes or undefined elements.
16722    return handle(Smi::FromInt(
16723        FixedArrayBase::cast(object->elements())->length()), isolate);
16724  } else if (!object->HasFastDoubleElements()) {
16725    EnsureWritableFastElements(object);
16726  }
16727  DCHECK(object->HasFastSmiOrObjectElements() ||
16728         object->HasFastDoubleElements());
16729
16730  // Collect holes at the end, undefined before that and the rest at the
16731  // start, and return the number of non-hole, non-undefined values.
16732
16733  Handle<FixedArrayBase> elements_base(object->elements());
16734  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
16735  if (limit > elements_length) {
16736    limit = elements_length;
16737  }
16738  if (limit == 0) {
16739    return handle(Smi::FromInt(0), isolate);
16740  }
16741
16742  uint32_t result = 0;
16743  if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
16744    FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
16745    // Split elements into defined and the_hole, in that order.
16746    unsigned int holes = limit;
16747    // Assume most arrays contain no holes and undefined values, so minimize the
16748    // number of stores of non-undefined, non-the-hole values.
16749    for (unsigned int i = 0; i < holes; i++) {
16750      if (elements->is_the_hole(i)) {
16751        holes--;
16752      } else {
16753        continue;
16754      }
16755      // Position i needs to be filled.
16756      while (holes > i) {
16757        if (elements->is_the_hole(holes)) {
16758          holes--;
16759        } else {
16760          elements->set(i, elements->get_scalar(holes));
16761          break;
16762        }
16763      }
16764    }
16765    result = holes;
16766    while (holes < limit) {
16767      elements->set_the_hole(holes);
16768      holes++;
16769    }
16770  } else {
16771    FixedArray* elements = FixedArray::cast(*elements_base);
16772    DisallowHeapAllocation no_gc;
16773
16774    // Split elements into defined, undefined and the_hole, in that order.  Only
16775    // count locations for undefined and the hole, and fill them afterwards.
16776    WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
16777    unsigned int undefs = limit;
16778    unsigned int holes = limit;
16779    // Assume most arrays contain no holes and undefined values, so minimize the
16780    // number of stores of non-undefined, non-the-hole values.
16781    for (unsigned int i = 0; i < undefs; i++) {
16782      Object* current = elements->get(i);
16783      if (current->IsTheHole(isolate)) {
16784        holes--;
16785        undefs--;
16786      } else if (current->IsUndefined(isolate)) {
16787        undefs--;
16788      } else {
16789        continue;
16790      }
16791      // Position i needs to be filled.
16792      while (undefs > i) {
16793        current = elements->get(undefs);
16794        if (current->IsTheHole(isolate)) {
16795          holes--;
16796          undefs--;
16797        } else if (current->IsUndefined(isolate)) {
16798          undefs--;
16799        } else {
16800          elements->set(i, current, write_barrier);
16801          break;
16802        }
16803      }
16804    }
16805    result = undefs;
16806    while (undefs < holes) {
16807      elements->set_undefined(undefs);
16808      undefs++;
16809    }
16810    while (holes < limit) {
16811      elements->set_the_hole(holes);
16812      holes++;
16813    }
16814  }
16815
16816  return isolate->factory()->NewNumberFromUint(result);
16817}
16818
16819
16820ExternalArrayType JSTypedArray::type() {
16821  switch (elements()->map()->instance_type()) {
16822#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
16823    case FIXED_##TYPE##_ARRAY_TYPE:                                           \
16824      return kExternal##Type##Array;
16825
16826    TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
16827#undef INSTANCE_TYPE_TO_ARRAY_TYPE
16828
16829    default:
16830      UNREACHABLE();
16831      return static_cast<ExternalArrayType>(-1);
16832  }
16833}
16834
16835
16836size_t JSTypedArray::element_size() {
16837  switch (elements()->map()->instance_type()) {
16838#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
16839  case FIXED_##TYPE##_ARRAY_TYPE:                                    \
16840    return size;
16841
16842    TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
16843#undef INSTANCE_TYPE_TO_ELEMENT_SIZE
16844
16845    default:
16846      UNREACHABLE();
16847      return 0;
16848  }
16849}
16850
16851
16852void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
16853                                            Handle<Name> name) {
16854  DCHECK(!global->HasFastProperties());
16855  auto dictionary = handle(global->global_dictionary());
16856  int entry = dictionary->FindEntry(name);
16857  if (entry == GlobalDictionary::kNotFound) return;
16858  PropertyCell::InvalidateEntry(dictionary, entry);
16859}
16860
16861
16862// TODO(ishell): rename to EnsureEmptyPropertyCell or something.
16863Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
16864    Handle<JSGlobalObject> global, Handle<Name> name) {
16865  Isolate* isolate = global->GetIsolate();
16866  DCHECK(!global->HasFastProperties());
16867  auto dictionary = handle(global->global_dictionary(), isolate);
16868  int entry = dictionary->FindEntry(name);
16869  Handle<PropertyCell> cell;
16870  if (entry != GlobalDictionary::kNotFound) {
16871    // This call should be idempotent.
16872    DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
16873    cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
16874    DCHECK(cell->property_details().cell_type() ==
16875               PropertyCellType::kUninitialized ||
16876           cell->property_details().cell_type() ==
16877               PropertyCellType::kInvalidated);
16878    DCHECK(cell->value()->IsTheHole(isolate));
16879    return cell;
16880  }
16881  cell = isolate->factory()->NewPropertyCell();
16882  PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
16883  dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
16884  global->set_properties(*dictionary);
16885  return cell;
16886}
16887
16888
16889// This class is used for looking up two character strings in the string table.
16890// If we don't have a hit we don't want to waste much time so we unroll the
16891// string hash calculation loop here for speed.  Doesn't work if the two
16892// characters form a decimal integer, since such strings have a different hash
16893// algorithm.
16894class TwoCharHashTableKey : public HashTableKey {
16895 public:
16896  TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
16897    : c1_(c1), c2_(c2) {
16898    // Char 1.
16899    uint32_t hash = seed;
16900    hash += c1;
16901    hash += hash << 10;
16902    hash ^= hash >> 6;
16903    // Char 2.
16904    hash += c2;
16905    hash += hash << 10;
16906    hash ^= hash >> 6;
16907    // GetHash.
16908    hash += hash << 3;
16909    hash ^= hash >> 11;
16910    hash += hash << 15;
16911    if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
16912    hash_ = hash;
16913#ifdef DEBUG
16914    // If this assert fails then we failed to reproduce the two-character
16915    // version of the string hashing algorithm above.  One reason could be
16916    // that we were passed two digits as characters, since the hash
16917    // algorithm is different in that case.
16918    uint16_t chars[2] = {c1, c2};
16919    uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
16920    hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
16921    DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
16922#endif
16923  }
16924
16925  bool IsMatch(Object* o) override {
16926    if (!o->IsString()) return false;
16927    String* other = String::cast(o);
16928    if (other->length() != 2) return false;
16929    if (other->Get(0) != c1_) return false;
16930    return other->Get(1) == c2_;
16931  }
16932
16933  uint32_t Hash() override { return hash_; }
16934  uint32_t HashForObject(Object* key) override {
16935    if (!key->IsString()) return 0;
16936    return String::cast(key)->Hash();
16937  }
16938
16939  Handle<Object> AsHandle(Isolate* isolate) override {
16940    // The TwoCharHashTableKey is only used for looking in the string
16941    // table, not for adding to it.
16942    UNREACHABLE();
16943    return MaybeHandle<Object>().ToHandleChecked();
16944  }
16945
16946 private:
16947  uint16_t c1_;
16948  uint16_t c2_;
16949  uint32_t hash_;
16950};
16951
16952
16953MaybeHandle<String> StringTable::InternalizeStringIfExists(
16954    Isolate* isolate,
16955    Handle<String> string) {
16956  if (string->IsInternalizedString()) {
16957    return string;
16958  }
16959  return LookupStringIfExists(isolate, string);
16960}
16961
16962
16963MaybeHandle<String> StringTable::LookupStringIfExists(
16964    Isolate* isolate,
16965    Handle<String> string) {
16966  Handle<StringTable> string_table = isolate->factory()->string_table();
16967  InternalizedStringKey key(string);
16968  int entry = string_table->FindEntry(&key);
16969  if (entry == kNotFound) {
16970    return MaybeHandle<String>();
16971  } else {
16972    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
16973    DCHECK(StringShape(*result).IsInternalized());
16974    return result;
16975  }
16976}
16977
16978
16979MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
16980    Isolate* isolate,
16981    uint16_t c1,
16982    uint16_t c2) {
16983  Handle<StringTable> string_table = isolate->factory()->string_table();
16984  TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
16985  int entry = string_table->FindEntry(&key);
16986  if (entry == kNotFound) {
16987    return MaybeHandle<String>();
16988  } else {
16989    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
16990    DCHECK(StringShape(*result).IsInternalized());
16991    return result;
16992  }
16993}
16994
16995
16996void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
16997                                                   int expected) {
16998  Handle<StringTable> table = isolate->factory()->string_table();
16999  // We need a key instance for the virtual hash function.
17000  InternalizedStringKey dummy_key(isolate->factory()->empty_string());
17001  table = StringTable::EnsureCapacity(table, expected, &dummy_key);
17002  isolate->heap()->SetRootStringTable(*table);
17003}
17004
17005
17006Handle<String> StringTable::LookupString(Isolate* isolate,
17007                                         Handle<String> string) {
17008  if (string->IsConsString() && string->IsFlat()) {
17009    string = String::Flatten(string);
17010    if (string->IsInternalizedString()) return string;
17011  }
17012
17013  InternalizedStringKey key(string);
17014  Handle<String> result = LookupKey(isolate, &key);
17015
17016  if (string->IsConsString()) {
17017    Handle<ConsString> cons = Handle<ConsString>::cast(string);
17018    cons->set_first(*result);
17019    cons->set_second(isolate->heap()->empty_string());
17020  } else if (string->IsSlicedString()) {
17021    STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
17022    DisallowHeapAllocation no_gc;
17023    bool one_byte = result->IsOneByteRepresentation();
17024    Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map()
17025                               : isolate->factory()->cons_string_map();
17026    string->set_map(*map);
17027    Handle<ConsString> cons = Handle<ConsString>::cast(string);
17028    cons->set_first(*result);
17029    cons->set_second(isolate->heap()->empty_string());
17030  }
17031  return result;
17032}
17033
17034
17035Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
17036  Handle<StringTable> table = isolate->factory()->string_table();
17037  int entry = table->FindEntry(key);
17038
17039  // String already in table.
17040  if (entry != kNotFound) {
17041    return handle(String::cast(table->KeyAt(entry)), isolate);
17042  }
17043
17044  // Adding new string. Grow table if needed.
17045  table = StringTable::EnsureCapacity(table, 1, key);
17046
17047  // Create string object.
17048  Handle<Object> string = key->AsHandle(isolate);
17049  // There must be no attempts to internalize strings that could throw
17050  // InvalidStringLength error.
17051  CHECK(!string.is_null());
17052
17053  // Add the new string and return it along with the string table.
17054  entry = table->FindInsertionEntry(key->Hash());
17055  table->set(EntryToIndex(entry), *string);
17056  table->ElementAdded();
17057
17058  isolate->heap()->SetRootStringTable(*table);
17059  return Handle<String>::cast(string);
17060}
17061
17062
17063String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
17064  Handle<StringTable> table = isolate->factory()->string_table();
17065  int entry = table->FindEntry(key);
17066  if (entry != kNotFound) return String::cast(table->KeyAt(entry));
17067  return NULL;
17068}
17069
17070Handle<StringSet> StringSet::New(Isolate* isolate) {
17071  return HashTable::New(isolate, 0);
17072}
17073
17074Handle<StringSet> StringSet::Add(Handle<StringSet> stringset,
17075                                 Handle<String> name) {
17076  if (!stringset->Has(name)) {
17077    stringset = EnsureCapacity(stringset, 1, *name);
17078    uint32_t hash = StringSetShape::Hash(*name);
17079    int entry = stringset->FindInsertionEntry(hash);
17080    stringset->set(EntryToIndex(entry), *name);
17081    stringset->ElementAdded();
17082  }
17083  return stringset;
17084}
17085
17086bool StringSet::Has(Handle<String> name) {
17087  return FindEntry(*name) != kNotFound;
17088}
17089
17090Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
17091                                             Handle<Context> context,
17092                                             LanguageMode language_mode) {
17093  Isolate* isolate = GetIsolate();
17094  Handle<SharedFunctionInfo> shared(context->closure()->shared());
17095  StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
17096  int entry = FindEntry(&key);
17097  if (entry == kNotFound) return isolate->factory()->undefined_value();
17098  int index = EntryToIndex(entry);
17099  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
17100  return Handle<Object>(get(index + 1), isolate);
17101}
17102
17103
17104Handle<Object> CompilationCacheTable::LookupEval(
17105    Handle<String> src, Handle<SharedFunctionInfo> outer_info,
17106    LanguageMode language_mode, int scope_position) {
17107  Isolate* isolate = GetIsolate();
17108  // Cache key is the tuple (source, outer shared function info, scope position)
17109  // to unambiguously identify the context chain the cached eval code assumes.
17110  StringSharedKey key(src, outer_info, language_mode, scope_position);
17111  int entry = FindEntry(&key);
17112  if (entry == kNotFound) return isolate->factory()->undefined_value();
17113  int index = EntryToIndex(entry);
17114  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
17115  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
17116}
17117
17118
17119Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
17120                                                   JSRegExp::Flags flags) {
17121  Isolate* isolate = GetIsolate();
17122  DisallowHeapAllocation no_allocation;
17123  RegExpKey key(src, flags);
17124  int entry = FindEntry(&key);
17125  if (entry == kNotFound) return isolate->factory()->undefined_value();
17126  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
17127}
17128
17129
17130Handle<CompilationCacheTable> CompilationCacheTable::Put(
17131    Handle<CompilationCacheTable> cache, Handle<String> src,
17132    Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
17133  Isolate* isolate = cache->GetIsolate();
17134  Handle<SharedFunctionInfo> shared(context->closure()->shared());
17135  StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
17136  Handle<Object> k = key.AsHandle(isolate);
17137  cache = EnsureCapacity(cache, 1, &key);
17138  int entry = cache->FindInsertionEntry(key.Hash());
17139  cache->set(EntryToIndex(entry), *k);
17140  cache->set(EntryToIndex(entry) + 1, *value);
17141  cache->ElementAdded();
17142  return cache;
17143}
17144
17145
17146Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
17147    Handle<CompilationCacheTable> cache, Handle<String> src,
17148    Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
17149    int scope_position) {
17150  Isolate* isolate = cache->GetIsolate();
17151  StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
17152  {
17153    Handle<Object> k = key.AsHandle(isolate);
17154    DisallowHeapAllocation no_allocation_scope;
17155    int entry = cache->FindEntry(&key);
17156    if (entry != kNotFound) {
17157      cache->set(EntryToIndex(entry), *k);
17158      cache->set(EntryToIndex(entry) + 1, *value);
17159      return cache;
17160    }
17161  }
17162
17163  cache = EnsureCapacity(cache, 1, &key);
17164  int entry = cache->FindInsertionEntry(key.Hash());
17165  Handle<Object> k =
17166      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
17167  cache->set(EntryToIndex(entry), *k);
17168  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
17169  cache->ElementAdded();
17170  return cache;
17171}
17172
17173
17174Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
17175      Handle<CompilationCacheTable> cache, Handle<String> src,
17176      JSRegExp::Flags flags, Handle<FixedArray> value) {
17177  RegExpKey key(src, flags);
17178  cache = EnsureCapacity(cache, 1, &key);
17179  int entry = cache->FindInsertionEntry(key.Hash());
17180  // We store the value in the key slot, and compare the search key
17181  // to the stored value with a custon IsMatch function during lookups.
17182  cache->set(EntryToIndex(entry), *value);
17183  cache->set(EntryToIndex(entry) + 1, *value);
17184  cache->ElementAdded();
17185  return cache;
17186}
17187
17188
17189void CompilationCacheTable::Age() {
17190  DisallowHeapAllocation no_allocation;
17191  Object* the_hole_value = GetHeap()->the_hole_value();
17192  uint32_t capacity = Capacity();
17193  for (int entry = 0, size = capacity; entry < size; entry++) {
17194    int entry_index = EntryToIndex(entry);
17195    int value_index = entry_index + 1;
17196
17197    if (get(entry_index)->IsNumber()) {
17198      Smi* count = Smi::cast(get(value_index));
17199      count = Smi::FromInt(count->value() - 1);
17200      if (count->value() == 0) {
17201        NoWriteBarrierSet(this, entry_index, the_hole_value);
17202        NoWriteBarrierSet(this, value_index, the_hole_value);
17203        ElementRemoved();
17204      } else {
17205        NoWriteBarrierSet(this, value_index, count);
17206      }
17207    } else if (get(entry_index)->IsFixedArray()) {
17208      SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
17209      if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
17210        NoWriteBarrierSet(this, entry_index, the_hole_value);
17211        NoWriteBarrierSet(this, value_index, the_hole_value);
17212        ElementRemoved();
17213      }
17214    }
17215  }
17216  // Wipe deleted entries.
17217  Heap* heap = GetHeap();
17218  Object* the_hole = heap->the_hole_value();
17219  Object* undefined = heap->undefined_value();
17220  for (uint32_t current = 0; current < capacity; current++) {
17221    if (get(EntryToIndex(current)) == the_hole) {
17222      set(EntryToIndex(current), undefined);
17223    }
17224  }
17225  SetNumberOfDeletedElements(0);
17226}
17227
17228
17229void CompilationCacheTable::Remove(Object* value) {
17230  DisallowHeapAllocation no_allocation;
17231  Object* the_hole_value = GetHeap()->the_hole_value();
17232  for (int entry = 0, size = Capacity(); entry < size; entry++) {
17233    int entry_index = EntryToIndex(entry);
17234    int value_index = entry_index + 1;
17235    if (get(value_index) == value) {
17236      NoWriteBarrierSet(this, entry_index, the_hole_value);
17237      NoWriteBarrierSet(this, value_index, the_hole_value);
17238      ElementRemoved();
17239    }
17240  }
17241  return;
17242}
17243
17244
17245template<typename Derived, typename Shape, typename Key>
17246Handle<Derived> Dictionary<Derived, Shape, Key>::New(
17247    Isolate* isolate,
17248    int at_least_space_for,
17249    PretenureFlag pretenure) {
17250  DCHECK(0 <= at_least_space_for);
17251  Handle<Derived> dict = DerivedHashTable::New(isolate,
17252                                               at_least_space_for,
17253                                               USE_DEFAULT_MINIMUM_CAPACITY,
17254                                               pretenure);
17255
17256  // Initialize the next enumeration index.
17257  dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
17258  return dict;
17259}
17260
17261
17262template <typename Derived, typename Shape, typename Key>
17263Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
17264    Handle<Derived> dictionary) {
17265  Isolate* isolate = dictionary->GetIsolate();
17266  Factory* factory = isolate->factory();
17267  int length = dictionary->NumberOfElements();
17268
17269  Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
17270  Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
17271
17272  // Fill both the iteration order array and the enumeration order array
17273  // with property details.
17274  int capacity = dictionary->Capacity();
17275  int pos = 0;
17276  for (int i = 0; i < capacity; i++) {
17277    if (dictionary->IsKey(isolate, dictionary->KeyAt(i))) {
17278      int index = dictionary->DetailsAt(i).dictionary_index();
17279      iteration_order->set(pos, Smi::FromInt(i));
17280      enumeration_order->set(pos, Smi::FromInt(index));
17281      pos++;
17282    }
17283  }
17284  DCHECK(pos == length);
17285
17286  // Sort the arrays wrt. enumeration order.
17287  iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
17288  return iteration_order;
17289}
17290
17291
17292template <typename Derived, typename Shape, typename Key>
17293Handle<FixedArray>
17294Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
17295    Handle<Derived> dictionary) {
17296  int length = dictionary->NumberOfElements();
17297
17298  Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
17299  DCHECK(iteration_order->length() == length);
17300
17301  // Iterate over the dictionary using the enumeration order and update
17302  // the dictionary with new enumeration indices.
17303  for (int i = 0; i < length; i++) {
17304    int index = Smi::cast(iteration_order->get(i))->value();
17305    DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
17306
17307    int enum_index = PropertyDetails::kInitialIndex + i;
17308
17309    PropertyDetails details = dictionary->DetailsAt(index);
17310    PropertyDetails new_details = details.set_index(enum_index);
17311    dictionary->DetailsAtPut(index, new_details);
17312  }
17313
17314  // Set the next enumeration index.
17315  dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
17316  return iteration_order;
17317}
17318
17319
17320template <typename Derived, typename Shape, typename Key>
17321void Dictionary<Derived, Shape, Key>::SetRequiresCopyOnCapacityChange() {
17322  DCHECK_EQ(0, DerivedHashTable::NumberOfElements());
17323  DCHECK_EQ(0, DerivedHashTable::NumberOfDeletedElements());
17324  // Make sure that HashTable::EnsureCapacity will create a copy.
17325  DerivedHashTable::SetNumberOfDeletedElements(DerivedHashTable::Capacity());
17326  DCHECK(!DerivedHashTable::HasSufficientCapacityToAdd(1));
17327}
17328
17329
17330template <typename Derived, typename Shape, typename Key>
17331Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
17332    Handle<Derived> dictionary, int n, Key key) {
17333  // Check whether there are enough enumeration indices to add n elements.
17334  if (Shape::kIsEnumerable &&
17335      !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
17336    // If not, we generate new indices for the properties.
17337    GenerateNewEnumerationIndices(dictionary);
17338  }
17339  return DerivedHashTable::EnsureCapacity(dictionary, n, key);
17340}
17341
17342
17343template <typename Derived, typename Shape, typename Key>
17344Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
17345    Handle<Derived> dictionary, int entry) {
17346  Factory* factory = dictionary->GetIsolate()->factory();
17347  PropertyDetails details = dictionary->DetailsAt(entry);
17348  if (!details.IsConfigurable()) return factory->false_value();
17349
17350  dictionary->SetEntry(
17351      entry, factory->the_hole_value(), factory->the_hole_value());
17352  dictionary->ElementRemoved();
17353  return factory->true_value();
17354}
17355
17356
17357template<typename Derived, typename Shape, typename Key>
17358Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
17359    Handle<Derived> dictionary, Key key, Handle<Object> value) {
17360  int entry = dictionary->FindEntry(key);
17361
17362  // If the entry is present set the value;
17363  if (entry != Dictionary::kNotFound) {
17364    dictionary->ValueAtPut(entry, *value);
17365    return dictionary;
17366  }
17367
17368  // Check whether the dictionary should be extended.
17369  dictionary = EnsureCapacity(dictionary, 1, key);
17370#ifdef DEBUG
17371  USE(Shape::AsHandle(dictionary->GetIsolate(), key));
17372#endif
17373  PropertyDetails details = PropertyDetails::Empty();
17374
17375  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
17376  return dictionary;
17377}
17378
17379
17380template<typename Derived, typename Shape, typename Key>
17381Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
17382    Handle<Derived> dictionary,
17383    Key key,
17384    Handle<Object> value,
17385    PropertyDetails details) {
17386  // Valdate key is absent.
17387  SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
17388  // Check whether the dictionary should be extended.
17389  dictionary = EnsureCapacity(dictionary, 1, key);
17390
17391  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
17392  return dictionary;
17393}
17394
17395
17396// Add a key, value pair to the dictionary.
17397template<typename Derived, typename Shape, typename Key>
17398void Dictionary<Derived, Shape, Key>::AddEntry(
17399    Handle<Derived> dictionary,
17400    Key key,
17401    Handle<Object> value,
17402    PropertyDetails details,
17403    uint32_t hash) {
17404  // Compute the key object.
17405  Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
17406
17407  uint32_t entry = dictionary->FindInsertionEntry(hash);
17408  // Insert element at empty or deleted entry
17409  if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
17410    // Assign an enumeration index to the property and update
17411    // SetNextEnumerationIndex.
17412    int index = dictionary->NextEnumerationIndex();
17413    details = details.set_index(index);
17414    dictionary->SetNextEnumerationIndex(index + 1);
17415  }
17416  dictionary->SetEntry(entry, k, value, details);
17417  DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
17418          dictionary->KeyAt(entry)->IsName()));
17419  dictionary->ElementAdded();
17420}
17421
17422bool SeededNumberDictionary::HasComplexElements() {
17423  if (!requires_slow_elements()) return false;
17424  Isolate* isolate = this->GetIsolate();
17425  int capacity = this->Capacity();
17426  for (int i = 0; i < capacity; i++) {
17427    Object* k = this->KeyAt(i);
17428    if (!this->IsKey(isolate, k)) continue;
17429    DCHECK(!IsDeleted(i));
17430    PropertyDetails details = this->DetailsAt(i);
17431    if (details.type() == ACCESSOR_CONSTANT) return true;
17432    PropertyAttributes attr = details.attributes();
17433    if (attr & ALL_ATTRIBUTES_MASK) return true;
17434  }
17435  return false;
17436}
17437
17438void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key,
17439                                                bool used_as_prototype) {
17440  DisallowHeapAllocation no_allocation;
17441  // If the dictionary requires slow elements an element has already
17442  // been added at a high index.
17443  if (requires_slow_elements()) return;
17444  // Check if this index is high enough that we should require slow
17445  // elements.
17446  if (key > kRequiresSlowElementsLimit) {
17447    if (used_as_prototype) {
17448      // TODO(verwaest): Remove this hack.
17449      TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
17450    }
17451    set_requires_slow_elements();
17452    return;
17453  }
17454  // Update max key value.
17455  Object* max_index_object = get(kMaxNumberKeyIndex);
17456  if (!max_index_object->IsSmi() || max_number_key() < key) {
17457    FixedArray::set(kMaxNumberKeyIndex,
17458                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
17459  }
17460}
17461
17462
17463Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
17464    Handle<SeededNumberDictionary> dictionary, uint32_t key,
17465    Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
17466  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
17467  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
17468  return Add(dictionary, key, value, details);
17469}
17470
17471
17472Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
17473    Handle<UnseededNumberDictionary> dictionary,
17474    uint32_t key,
17475    Handle<Object> value) {
17476  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
17477  return Add(dictionary, key, value, PropertyDetails::Empty());
17478}
17479
17480
17481Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
17482    Handle<SeededNumberDictionary> dictionary, uint32_t key,
17483    Handle<Object> value, bool used_as_prototype) {
17484  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
17485  return AtPut(dictionary, key, value);
17486}
17487
17488
17489Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
17490    Handle<UnseededNumberDictionary> dictionary,
17491    uint32_t key,
17492    Handle<Object> value) {
17493  return AtPut(dictionary, key, value);
17494}
17495
17496
17497Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
17498    Handle<SeededNumberDictionary> dictionary, uint32_t key,
17499    Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
17500  int entry = dictionary->FindEntry(key);
17501  if (entry == kNotFound) {
17502    return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
17503  }
17504  // Preserve enumeration index.
17505  details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
17506  Handle<Object> object_key =
17507      SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
17508  dictionary->SetEntry(entry, object_key, value, details);
17509  return dictionary;
17510}
17511
17512
17513Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
17514    Handle<UnseededNumberDictionary> dictionary,
17515    uint32_t key,
17516    Handle<Object> value) {
17517  int entry = dictionary->FindEntry(key);
17518  if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
17519  Handle<Object> object_key =
17520      UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
17521  dictionary->SetEntry(entry, object_key, value);
17522  return dictionary;
17523}
17524
17525
17526template <typename Derived, typename Shape, typename Key>
17527int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
17528    PropertyFilter filter) {
17529  Isolate* isolate = this->GetIsolate();
17530  int capacity = this->Capacity();
17531  int result = 0;
17532  for (int i = 0; i < capacity; i++) {
17533    Object* k = this->KeyAt(i);
17534    if (this->IsKey(isolate, k) && !k->FilterKey(filter)) {
17535      if (this->IsDeleted(i)) continue;
17536      PropertyDetails details = this->DetailsAt(i);
17537      PropertyAttributes attr = details.attributes();
17538      if ((attr & filter) == 0) result++;
17539    }
17540  }
17541  return result;
17542}
17543
17544
17545template <typename Dictionary>
17546struct EnumIndexComparator {
17547  explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
17548  bool operator() (Smi* a, Smi* b) {
17549    PropertyDetails da(dict->DetailsAt(a->value()));
17550    PropertyDetails db(dict->DetailsAt(b->value()));
17551    return da.dictionary_index() < db.dictionary_index();
17552  }
17553  Dictionary* dict;
17554};
17555
17556
17557template <typename Derived, typename Shape, typename Key>
17558void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
17559  Isolate* isolate = this->GetIsolate();
17560  int length = storage->length();
17561  int capacity = this->Capacity();
17562  int properties = 0;
17563  for (int i = 0; i < capacity; i++) {
17564    Object* k = this->KeyAt(i);
17565    if (this->IsKey(isolate, k) && !k->IsSymbol()) {
17566      PropertyDetails details = this->DetailsAt(i);
17567      if (details.IsDontEnum() || this->IsDeleted(i)) continue;
17568      storage->set(properties, Smi::FromInt(i));
17569      properties++;
17570      if (properties == length) break;
17571    }
17572  }
17573  CHECK_EQ(length, properties);
17574  EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
17575  Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
17576  std::sort(start, start + length, cmp);
17577  for (int i = 0; i < length; i++) {
17578    int index = Smi::cast(storage->get(i))->value();
17579    storage->set(i, this->KeyAt(index));
17580  }
17581}
17582
17583template <typename Derived, typename Shape, typename Key>
17584void Dictionary<Derived, Shape, Key>::CollectKeysTo(
17585    Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
17586    PropertyFilter filter) {
17587  Isolate* isolate = keys->isolate();
17588  int capacity = dictionary->Capacity();
17589  Handle<FixedArray> array =
17590      isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
17591  int array_size = 0;
17592
17593  {
17594    DisallowHeapAllocation no_gc;
17595    Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
17596    for (int i = 0; i < capacity; i++) {
17597      Object* k = raw_dict->KeyAt(i);
17598      if (!raw_dict->IsKey(isolate, k) || k->FilterKey(filter)) continue;
17599      if (raw_dict->IsDeleted(i)) continue;
17600      PropertyDetails details = raw_dict->DetailsAt(i);
17601      if ((details.attributes() & filter) != 0) continue;
17602      if (filter & ONLY_ALL_CAN_READ) {
17603        if (details.kind() != kAccessor) continue;
17604        Object* accessors = raw_dict->ValueAt(i);
17605        if (accessors->IsPropertyCell()) {
17606          accessors = PropertyCell::cast(accessors)->value();
17607        }
17608        if (!accessors->IsAccessorInfo()) continue;
17609        if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
17610      }
17611      array->set(array_size++, Smi::FromInt(i));
17612    }
17613
17614    EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
17615    Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
17616    std::sort(start, start + array_size, cmp);
17617  }
17618
17619  bool has_seen_symbol = false;
17620  for (int i = 0; i < array_size; i++) {
17621    int index = Smi::cast(array->get(i))->value();
17622    Object* key = dictionary->KeyAt(index);
17623    if (key->IsSymbol()) {
17624      has_seen_symbol = true;
17625      continue;
17626    }
17627    keys->AddKey(key, DO_NOT_CONVERT);
17628  }
17629  if (has_seen_symbol) {
17630    for (int i = 0; i < array_size; i++) {
17631      int index = Smi::cast(array->get(i))->value();
17632      Object* key = dictionary->KeyAt(index);
17633      if (!key->IsSymbol()) continue;
17634      keys->AddKey(key, DO_NOT_CONVERT);
17635    }
17636  }
17637}
17638
17639
17640// Backwards lookup (slow).
17641template<typename Derived, typename Shape, typename Key>
17642Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
17643  Isolate* isolate = this->GetIsolate();
17644  int capacity = this->Capacity();
17645  for (int i = 0; i < capacity; i++) {
17646    Object* k = this->KeyAt(i);
17647    if (!this->IsKey(isolate, k)) continue;
17648    Object* e = this->ValueAt(i);
17649    // TODO(dcarney): this should be templatized.
17650    if (e->IsPropertyCell()) {
17651      e = PropertyCell::cast(e)->value();
17652    }
17653    if (e == value) return k;
17654  }
17655  return isolate->heap()->undefined_value();
17656}
17657
17658
17659Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
17660                                int32_t hash) {
17661  DisallowHeapAllocation no_gc;
17662  DCHECK(IsKey(isolate, *key));
17663
17664  int entry = FindEntry(isolate, key, hash);
17665  if (entry == kNotFound) return isolate->heap()->the_hole_value();
17666  return get(EntryToIndex(entry) + 1);
17667}
17668
17669
17670Object* ObjectHashTable::Lookup(Handle<Object> key) {
17671  DisallowHeapAllocation no_gc;
17672
17673  Isolate* isolate = GetIsolate();
17674  DCHECK(IsKey(isolate, *key));
17675
17676  // If the object does not have an identity hash, it was never used as a key.
17677  Object* hash = key->GetHash();
17678  if (hash->IsUndefined(isolate)) {
17679    return isolate->heap()->the_hole_value();
17680  }
17681  return Lookup(isolate, key, Smi::cast(hash)->value());
17682}
17683
17684
17685Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
17686  return Lookup(GetIsolate(), key, hash);
17687}
17688
17689
17690Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
17691                                             Handle<Object> key,
17692                                             Handle<Object> value) {
17693  Isolate* isolate = table->GetIsolate();
17694  DCHECK(table->IsKey(isolate, *key));
17695  DCHECK(!value->IsTheHole(isolate));
17696
17697  // Make sure the key object has an identity hash code.
17698  int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
17699
17700  return Put(table, key, value, hash);
17701}
17702
17703
17704Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
17705                                             Handle<Object> key,
17706                                             Handle<Object> value,
17707                                             int32_t hash) {
17708  Isolate* isolate = table->GetIsolate();
17709  DCHECK(table->IsKey(isolate, *key));
17710  DCHECK(!value->IsTheHole(isolate));
17711
17712  int entry = table->FindEntry(isolate, key, hash);
17713
17714  // Key is already in table, just overwrite value.
17715  if (entry != kNotFound) {
17716    table->set(EntryToIndex(entry) + 1, *value);
17717    return table;
17718  }
17719
17720  // Rehash if more than 25% of the entries are deleted entries.
17721  // TODO(jochen): Consider to shrink the fixed array in place.
17722  if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
17723    table->Rehash(isolate->factory()->undefined_value());
17724  }
17725  // If we're out of luck, we didn't get a GC recently, and so rehashing
17726  // isn't enough to avoid a crash.
17727  if (!table->HasSufficientCapacityToAdd(1)) {
17728    int nof = table->NumberOfElements() + 1;
17729    int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
17730    if (capacity > ObjectHashTable::kMaxCapacity) {
17731      for (size_t i = 0; i < 2; ++i) {
17732        isolate->heap()->CollectAllGarbage(
17733            Heap::kFinalizeIncrementalMarkingMask, "full object hash table");
17734      }
17735      table->Rehash(isolate->factory()->undefined_value());
17736    }
17737  }
17738
17739  // Check whether the hash table should be extended.
17740  table = EnsureCapacity(table, 1, key);
17741  table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
17742  return table;
17743}
17744
17745
17746Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
17747                                                Handle<Object> key,
17748                                                bool* was_present) {
17749  DCHECK(table->IsKey(table->GetIsolate(), *key));
17750
17751  Object* hash = key->GetHash();
17752  if (hash->IsUndefined(table->GetIsolate())) {
17753    *was_present = false;
17754    return table;
17755  }
17756
17757  return Remove(table, key, was_present, Smi::cast(hash)->value());
17758}
17759
17760
17761Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
17762                                                Handle<Object> key,
17763                                                bool* was_present,
17764                                                int32_t hash) {
17765  Isolate* isolate = table->GetIsolate();
17766  DCHECK(table->IsKey(isolate, *key));
17767
17768  int entry = table->FindEntry(isolate, key, hash);
17769  if (entry == kNotFound) {
17770    *was_present = false;
17771    return table;
17772  }
17773
17774  *was_present = true;
17775  table->RemoveEntry(entry);
17776  return Shrink(table, key);
17777}
17778
17779
17780void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
17781  set(EntryToIndex(entry), key);
17782  set(EntryToIndex(entry) + 1, value);
17783  ElementAdded();
17784}
17785
17786
17787void ObjectHashTable::RemoveEntry(int entry) {
17788  set_the_hole(EntryToIndex(entry));
17789  set_the_hole(EntryToIndex(entry) + 1);
17790  ElementRemoved();
17791}
17792
17793
17794Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
17795  DisallowHeapAllocation no_gc;
17796  Isolate* isolate = GetIsolate();
17797  DCHECK(IsKey(isolate, *key));
17798  int entry = FindEntry(key);
17799  if (entry == kNotFound) return isolate->heap()->the_hole_value();
17800  return get(EntryToValueIndex(entry));
17801}
17802
17803
17804Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
17805                                         Handle<HeapObject> key,
17806                                         Handle<HeapObject> value) {
17807  Isolate* isolate = key->GetIsolate();
17808  DCHECK(table->IsKey(isolate, *key));
17809  int entry = table->FindEntry(key);
17810  // Key is already in table, just overwrite value.
17811  if (entry != kNotFound) {
17812    table->set(EntryToValueIndex(entry), *value);
17813    return table;
17814  }
17815
17816  Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
17817
17818  // Check whether the hash table should be extended.
17819  table = EnsureCapacity(table, 1, key, TENURED);
17820
17821  table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
17822  return table;
17823}
17824
17825
17826void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
17827                             Handle<HeapObject> value) {
17828  DisallowHeapAllocation no_allocation;
17829  set(EntryToIndex(entry), *key_cell);
17830  set(EntryToValueIndex(entry), *value);
17831  ElementAdded();
17832}
17833
17834
17835template<class Derived, class Iterator, int entrysize>
17836Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
17837    Isolate* isolate, int capacity, PretenureFlag pretenure) {
17838  // Capacity must be a power of two, since we depend on being able
17839  // to divide and multiple by 2 (kLoadFactor) to derive capacity
17840  // from number of buckets. If we decide to change kLoadFactor
17841  // to something other than 2, capacity should be stored as another
17842  // field of this object.
17843  capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
17844  if (capacity > kMaxCapacity) {
17845    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
17846  }
17847  int num_buckets = capacity / kLoadFactor;
17848  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
17849      kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
17850  backing_store->set_map_no_write_barrier(
17851      isolate->heap()->ordered_hash_table_map());
17852  Handle<Derived> table = Handle<Derived>::cast(backing_store);
17853  for (int i = 0; i < num_buckets; ++i) {
17854    table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
17855  }
17856  table->SetNumberOfBuckets(num_buckets);
17857  table->SetNumberOfElements(0);
17858  table->SetNumberOfDeletedElements(0);
17859  return table;
17860}
17861
17862
17863template<class Derived, class Iterator, int entrysize>
17864Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
17865    Handle<Derived> table) {
17866  DCHECK(!table->IsObsolete());
17867
17868  int nof = table->NumberOfElements();
17869  int nod = table->NumberOfDeletedElements();
17870  int capacity = table->Capacity();
17871  if ((nof + nod) < capacity) return table;
17872  // Don't need to grow if we can simply clear out deleted entries instead.
17873  // Note that we can't compact in place, though, so we always allocate
17874  // a new table.
17875  return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
17876}
17877
17878
17879template<class Derived, class Iterator, int entrysize>
17880Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
17881    Handle<Derived> table) {
17882  DCHECK(!table->IsObsolete());
17883
17884  int nof = table->NumberOfElements();
17885  int capacity = table->Capacity();
17886  if (nof >= (capacity >> 2)) return table;
17887  return Rehash(table, capacity / 2);
17888}
17889
17890
17891template<class Derived, class Iterator, int entrysize>
17892Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
17893    Handle<Derived> table) {
17894  DCHECK(!table->IsObsolete());
17895
17896  Handle<Derived> new_table =
17897      Allocate(table->GetIsolate(),
17898               kMinCapacity,
17899               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
17900
17901  table->SetNextTable(*new_table);
17902  table->SetNumberOfDeletedElements(kClearedTableSentinel);
17903
17904  return new_table;
17905}
17906
17907template <class Derived, class Iterator, int entrysize>
17908bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
17909    Handle<Derived> table, Handle<Object> key) {
17910  DisallowHeapAllocation no_gc;
17911  Isolate* isolate = table->GetIsolate();
17912  Object* raw_key = *key;
17913  int entry = table->KeyToFirstEntry(isolate, raw_key);
17914  // Walk the chain in the bucket to find the key.
17915  while (entry != kNotFound) {
17916    Object* candidate_key = table->KeyAt(entry);
17917    if (candidate_key->SameValueZero(raw_key)) return true;
17918    entry = table->NextChainEntry(entry);
17919  }
17920  return false;
17921}
17922
17923
17924Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
17925                                           Handle<Object> key) {
17926  int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
17927  int entry = table->HashToEntry(hash);
17928  // Walk the chain of the bucket and try finding the key.
17929  while (entry != kNotFound) {
17930    Object* candidate_key = table->KeyAt(entry);
17931    // Do not add if we have the key already
17932    if (candidate_key->SameValueZero(*key)) return table;
17933    entry = table->NextChainEntry(entry);
17934  }
17935
17936  table = OrderedHashSet::EnsureGrowable(table);
17937  // Read the existing bucket values.
17938  int bucket = table->HashToBucket(hash);
17939  int previous_entry = table->HashToEntry(hash);
17940  int nof = table->NumberOfElements();
17941  // Insert a new entry at the end,
17942  int new_entry = nof + table->NumberOfDeletedElements();
17943  int new_index = table->EntryToIndex(new_entry);
17944  table->set(new_index, *key);
17945  table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
17946  // and point the bucket to the new entry.
17947  table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
17948  table->SetNumberOfElements(nof + 1);
17949  return table;
17950}
17951
17952Handle<FixedArray> OrderedHashSet::ConvertToKeysArray(
17953    Handle<OrderedHashSet> table, GetKeysConversion convert) {
17954  Isolate* isolate = table->GetIsolate();
17955  int length = table->NumberOfElements();
17956  int nof_buckets = table->NumberOfBuckets();
17957  // Convert the dictionary to a linear list.
17958  Handle<FixedArray> result = Handle<FixedArray>::cast(table);
17959  // From this point on table is no longer a valid OrderedHashSet.
17960  result->set_map(isolate->heap()->fixed_array_map());
17961  for (int i = 0; i < length; i++) {
17962    int index = kHashTableStartIndex + nof_buckets + (i * kEntrySize);
17963    Object* key = table->get(index);
17964    if (convert == GetKeysConversion::kConvertToString && key->IsNumber()) {
17965      key = *isolate->factory()->NumberToString(handle(key, isolate));
17966    }
17967    result->set(i, key);
17968  }
17969  result->Shrink(length);
17970  return result;
17971}
17972
17973template<class Derived, class Iterator, int entrysize>
17974Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
17975    Handle<Derived> table, int new_capacity) {
17976  Isolate* isolate = table->GetIsolate();
17977  DCHECK(!table->IsObsolete());
17978
17979  Handle<Derived> new_table =
17980      Allocate(isolate, new_capacity,
17981               isolate->heap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
17982  int nof = table->NumberOfElements();
17983  int nod = table->NumberOfDeletedElements();
17984  int new_buckets = new_table->NumberOfBuckets();
17985  int new_entry = 0;
17986  int removed_holes_index = 0;
17987
17988  DisallowHeapAllocation no_gc;
17989  for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
17990    Object* key = table->KeyAt(old_entry);
17991    if (key->IsTheHole(isolate)) {
17992      table->SetRemovedIndexAt(removed_holes_index++, old_entry);
17993      continue;
17994    }
17995
17996    Object* hash = key->GetHash();
17997    int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
17998    Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
17999    new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
18000    int new_index = new_table->EntryToIndex(new_entry);
18001    int old_index = table->EntryToIndex(old_entry);
18002    for (int i = 0; i < entrysize; ++i) {
18003      Object* value = table->get(old_index + i);
18004      new_table->set(new_index + i, value);
18005    }
18006    new_table->set(new_index + kChainOffset, chain_entry);
18007    ++new_entry;
18008  }
18009
18010  DCHECK_EQ(nod, removed_holes_index);
18011
18012  new_table->SetNumberOfElements(nof);
18013  table->SetNextTable(*new_table);
18014
18015  return new_table;
18016}
18017
18018
18019template Handle<OrderedHashSet>
18020OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
18021    Isolate* isolate, int capacity, PretenureFlag pretenure);
18022
18023template Handle<OrderedHashSet>
18024OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
18025    Handle<OrderedHashSet> table);
18026
18027template Handle<OrderedHashSet>
18028OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
18029    Handle<OrderedHashSet> table);
18030
18031template Handle<OrderedHashSet>
18032OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
18033    Handle<OrderedHashSet> table);
18034
18035template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
18036    Handle<OrderedHashSet> table, Handle<Object> key);
18037
18038
18039template Handle<OrderedHashMap>
18040OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
18041    Isolate* isolate, int capacity, PretenureFlag pretenure);
18042
18043template Handle<OrderedHashMap>
18044OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
18045    Handle<OrderedHashMap> table);
18046
18047template Handle<OrderedHashMap>
18048OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
18049    Handle<OrderedHashMap> table);
18050
18051template Handle<OrderedHashMap>
18052OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
18053    Handle<OrderedHashMap> table);
18054
18055template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
18056    Handle<OrderedHashMap> table, Handle<Object> key);
18057
18058
18059template<class Derived, class TableType>
18060void OrderedHashTableIterator<Derived, TableType>::Transition() {
18061  DisallowHeapAllocation no_allocation;
18062  TableType* table = TableType::cast(this->table());
18063  if (!table->IsObsolete()) return;
18064
18065  int index = Smi::cast(this->index())->value();
18066  while (table->IsObsolete()) {
18067    TableType* next_table = table->NextTable();
18068
18069    if (index > 0) {
18070      int nod = table->NumberOfDeletedElements();
18071
18072      if (nod == TableType::kClearedTableSentinel) {
18073        index = 0;
18074      } else {
18075        int old_index = index;
18076        for (int i = 0; i < nod; ++i) {
18077          int removed_index = table->RemovedIndexAt(i);
18078          if (removed_index >= old_index) break;
18079          --index;
18080        }
18081      }
18082    }
18083
18084    table = next_table;
18085  }
18086
18087  set_table(table);
18088  set_index(Smi::FromInt(index));
18089}
18090
18091
18092template<class Derived, class TableType>
18093bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
18094  DisallowHeapAllocation no_allocation;
18095  Isolate* isolate = this->GetIsolate();
18096  if (this->table()->IsUndefined(isolate)) return false;
18097
18098  Transition();
18099
18100  TableType* table = TableType::cast(this->table());
18101  int index = Smi::cast(this->index())->value();
18102  int used_capacity = table->UsedCapacity();
18103
18104  while (index < used_capacity && table->KeyAt(index)->IsTheHole(isolate)) {
18105    index++;
18106  }
18107
18108  set_index(Smi::FromInt(index));
18109
18110  if (index < used_capacity) return true;
18111
18112  set_table(isolate->heap()->undefined_value());
18113  return false;
18114}
18115
18116
18117template<class Derived, class TableType>
18118Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
18119  DisallowHeapAllocation no_allocation;
18120  if (HasMore()) {
18121    FixedArray* array = FixedArray::cast(value_array->elements());
18122    static_cast<Derived*>(this)->PopulateValueArray(array);
18123    MoveNext();
18124    return Smi::cast(kind());
18125  }
18126  return Smi::FromInt(0);
18127}
18128
18129
18130template Smi*
18131OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
18132    JSArray* value_array);
18133
18134template bool
18135OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
18136
18137template void
18138OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
18139
18140template Object*
18141OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
18142
18143template void
18144OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
18145
18146
18147template Smi*
18148OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
18149    JSArray* value_array);
18150
18151template bool
18152OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
18153
18154template void
18155OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
18156
18157template Object*
18158OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
18159
18160template void
18161OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
18162
18163
18164void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
18165  Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
18166  set->set_table(*table);
18167}
18168
18169
18170void JSSet::Clear(Handle<JSSet> set) {
18171  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
18172  table = OrderedHashSet::Clear(table);
18173  set->set_table(*table);
18174}
18175
18176
18177void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
18178  Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
18179  map->set_table(*table);
18180}
18181
18182
18183void JSMap::Clear(Handle<JSMap> map) {
18184  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
18185  table = OrderedHashMap::Clear(table);
18186  map->set_table(*table);
18187}
18188
18189
18190void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
18191                                  Isolate* isolate) {
18192  Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
18193  weak_collection->set_table(*table);
18194}
18195
18196
18197void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
18198                           Handle<Object> key, Handle<Object> value,
18199                           int32_t hash) {
18200  DCHECK(key->IsJSReceiver() || key->IsSymbol());
18201  Handle<ObjectHashTable> table(
18202      ObjectHashTable::cast(weak_collection->table()));
18203  DCHECK(table->IsKey(*key));
18204  Handle<ObjectHashTable> new_table =
18205      ObjectHashTable::Put(table, key, value, hash);
18206  weak_collection->set_table(*new_table);
18207  if (*table != *new_table) {
18208    // Zap the old table since we didn't record slots for its elements.
18209    table->FillWithHoles(0, table->length());
18210  }
18211}
18212
18213
18214bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
18215                              Handle<Object> key, int32_t hash) {
18216  DCHECK(key->IsJSReceiver() || key->IsSymbol());
18217  Handle<ObjectHashTable> table(
18218      ObjectHashTable::cast(weak_collection->table()));
18219  DCHECK(table->IsKey(*key));
18220  bool was_present = false;
18221  Handle<ObjectHashTable> new_table =
18222      ObjectHashTable::Remove(table, key, &was_present, hash);
18223  weak_collection->set_table(*new_table);
18224  if (*table != *new_table) {
18225    // Zap the old table since we didn't record slots for its elements.
18226    table->FillWithHoles(0, table->length());
18227  }
18228  return was_present;
18229}
18230
18231// Check if there is a break point at this code offset.
18232bool DebugInfo::HasBreakPoint(int code_offset) {
18233  // Get the break point info object for this code offset.
18234  Object* break_point_info = GetBreakPointInfo(code_offset);
18235
18236  // If there is no break point info object or no break points in the break
18237  // point info object there is no break point at this code offset.
18238  if (break_point_info->IsUndefined(GetIsolate())) return false;
18239  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
18240}
18241
18242// Get the break point info object for this code offset.
18243Object* DebugInfo::GetBreakPointInfo(int code_offset) {
18244  // Find the index of the break point info object for this code offset.
18245  int index = GetBreakPointInfoIndex(code_offset);
18246
18247  // Return the break point info object if any.
18248  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
18249  return BreakPointInfo::cast(break_points()->get(index));
18250}
18251
18252// Clear a break point at the specified code offset.
18253void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, int code_offset,
18254                                Handle<Object> break_point_object) {
18255  Isolate* isolate = debug_info->GetIsolate();
18256  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_offset),
18257                                  isolate);
18258  if (break_point_info->IsUndefined(isolate)) return;
18259  BreakPointInfo::ClearBreakPoint(
18260      Handle<BreakPointInfo>::cast(break_point_info),
18261      break_point_object);
18262}
18263
18264void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int code_offset,
18265                              int source_position, int statement_position,
18266                              Handle<Object> break_point_object) {
18267  Isolate* isolate = debug_info->GetIsolate();
18268  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_offset),
18269                                  isolate);
18270  if (!break_point_info->IsUndefined(isolate)) {
18271    BreakPointInfo::SetBreakPoint(
18272        Handle<BreakPointInfo>::cast(break_point_info),
18273        break_point_object);
18274    return;
18275  }
18276
18277  // Adding a new break point for a code offset which did not have any
18278  // break points before. Try to find a free slot.
18279  int index = kNoBreakPointInfo;
18280  for (int i = 0; i < debug_info->break_points()->length(); i++) {
18281    if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
18282      index = i;
18283      break;
18284    }
18285  }
18286  if (index == kNoBreakPointInfo) {
18287    // No free slot - extend break point info array.
18288    Handle<FixedArray> old_break_points = Handle<FixedArray>(
18289        FixedArray::cast(debug_info->break_points()), isolate);
18290    Handle<FixedArray> new_break_points =
18291        isolate->factory()->NewFixedArray(
18292            old_break_points->length() +
18293            DebugInfo::kEstimatedNofBreakPointsInFunction);
18294
18295    debug_info->set_break_points(*new_break_points);
18296    for (int i = 0; i < old_break_points->length(); i++) {
18297      new_break_points->set(i, old_break_points->get(i));
18298    }
18299    index = old_break_points->length();
18300  }
18301  DCHECK(index != kNoBreakPointInfo);
18302
18303  // Allocate new BreakPointInfo object and set the break point.
18304  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
18305      isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
18306  new_break_point_info->set_code_offset(code_offset);
18307  new_break_point_info->set_source_position(source_position);
18308  new_break_point_info->set_statement_position(statement_position);
18309  new_break_point_info->set_break_point_objects(
18310      isolate->heap()->undefined_value());
18311  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
18312  debug_info->break_points()->set(index, *new_break_point_info);
18313}
18314
18315// Get the break point objects for a code offset.
18316Handle<Object> DebugInfo::GetBreakPointObjects(int code_offset) {
18317  Object* break_point_info = GetBreakPointInfo(code_offset);
18318  Isolate* isolate = GetIsolate();
18319  if (break_point_info->IsUndefined(isolate)) {
18320    return isolate->factory()->undefined_value();
18321  }
18322  return Handle<Object>(
18323      BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
18324}
18325
18326
18327// Get the total number of break points.
18328int DebugInfo::GetBreakPointCount() {
18329  Isolate* isolate = GetIsolate();
18330  if (break_points()->IsUndefined(isolate)) return 0;
18331  int count = 0;
18332  for (int i = 0; i < break_points()->length(); i++) {
18333    if (!break_points()->get(i)->IsUndefined(isolate)) {
18334      BreakPointInfo* break_point_info =
18335          BreakPointInfo::cast(break_points()->get(i));
18336      count += break_point_info->GetBreakPointCount();
18337    }
18338  }
18339  return count;
18340}
18341
18342
18343Handle<Object> DebugInfo::FindBreakPointInfo(
18344    Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
18345  Isolate* isolate = debug_info->GetIsolate();
18346  if (!debug_info->break_points()->IsUndefined(isolate)) {
18347    for (int i = 0; i < debug_info->break_points()->length(); i++) {
18348      if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
18349        Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
18350            BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
18351        if (BreakPointInfo::HasBreakPointObject(break_point_info,
18352                                                break_point_object)) {
18353          return break_point_info;
18354        }
18355      }
18356    }
18357  }
18358  return isolate->factory()->undefined_value();
18359}
18360
18361
18362// Find the index of the break point info object for the specified code
18363// position.
18364int DebugInfo::GetBreakPointInfoIndex(int code_offset) {
18365  Isolate* isolate = GetIsolate();
18366  if (break_points()->IsUndefined(isolate)) return kNoBreakPointInfo;
18367  for (int i = 0; i < break_points()->length(); i++) {
18368    if (!break_points()->get(i)->IsUndefined(isolate)) {
18369      BreakPointInfo* break_point_info =
18370          BreakPointInfo::cast(break_points()->get(i));
18371      if (break_point_info->code_offset() == code_offset) {
18372        return i;
18373      }
18374    }
18375  }
18376  return kNoBreakPointInfo;
18377}
18378
18379
18380// Remove the specified break point object.
18381void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
18382                                     Handle<Object> break_point_object) {
18383  Isolate* isolate = break_point_info->GetIsolate();
18384  // If there are no break points just ignore.
18385  if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
18386  // If there is a single break point clear it if it is the same.
18387  if (!break_point_info->break_point_objects()->IsFixedArray()) {
18388    if (break_point_info->break_point_objects() == *break_point_object) {
18389      break_point_info->set_break_point_objects(
18390          isolate->heap()->undefined_value());
18391    }
18392    return;
18393  }
18394  // If there are multiple break points shrink the array
18395  DCHECK(break_point_info->break_point_objects()->IsFixedArray());
18396  Handle<FixedArray> old_array =
18397      Handle<FixedArray>(
18398          FixedArray::cast(break_point_info->break_point_objects()));
18399  Handle<FixedArray> new_array =
18400      isolate->factory()->NewFixedArray(old_array->length() - 1);
18401  int found_count = 0;
18402  for (int i = 0; i < old_array->length(); i++) {
18403    if (old_array->get(i) == *break_point_object) {
18404      DCHECK(found_count == 0);
18405      found_count++;
18406    } else {
18407      new_array->set(i - found_count, old_array->get(i));
18408    }
18409  }
18410  // If the break point was found in the list change it.
18411  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
18412}
18413
18414
18415// Add the specified break point object.
18416void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
18417                                   Handle<Object> break_point_object) {
18418  Isolate* isolate = break_point_info->GetIsolate();
18419
18420  // If there was no break point objects before just set it.
18421  if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
18422    break_point_info->set_break_point_objects(*break_point_object);
18423    return;
18424  }
18425  // If the break point object is the same as before just ignore.
18426  if (break_point_info->break_point_objects() == *break_point_object) return;
18427  // If there was one break point object before replace with array.
18428  if (!break_point_info->break_point_objects()->IsFixedArray()) {
18429    Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
18430    array->set(0, break_point_info->break_point_objects());
18431    array->set(1, *break_point_object);
18432    break_point_info->set_break_point_objects(*array);
18433    return;
18434  }
18435  // If there was more than one break point before extend array.
18436  Handle<FixedArray> old_array =
18437      Handle<FixedArray>(
18438          FixedArray::cast(break_point_info->break_point_objects()));
18439  Handle<FixedArray> new_array =
18440      isolate->factory()->NewFixedArray(old_array->length() + 1);
18441  for (int i = 0; i < old_array->length(); i++) {
18442    // If the break point was there before just ignore.
18443    if (old_array->get(i) == *break_point_object) return;
18444    new_array->set(i, old_array->get(i));
18445  }
18446  // Add the new break point.
18447  new_array->set(old_array->length(), *break_point_object);
18448  break_point_info->set_break_point_objects(*new_array);
18449}
18450
18451
18452bool BreakPointInfo::HasBreakPointObject(
18453    Handle<BreakPointInfo> break_point_info,
18454    Handle<Object> break_point_object) {
18455  // No break point.
18456  Isolate* isolate = break_point_info->GetIsolate();
18457  if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
18458    return false;
18459  }
18460  // Single break point.
18461  if (!break_point_info->break_point_objects()->IsFixedArray()) {
18462    return break_point_info->break_point_objects() == *break_point_object;
18463  }
18464  // Multiple break points.
18465  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
18466  for (int i = 0; i < array->length(); i++) {
18467    if (array->get(i) == *break_point_object) {
18468      return true;
18469    }
18470  }
18471  return false;
18472}
18473
18474
18475// Get the number of break points.
18476int BreakPointInfo::GetBreakPointCount() {
18477  // No break point.
18478  if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
18479  // Single break point.
18480  if (!break_point_objects()->IsFixedArray()) return 1;
18481  // Multiple break points.
18482  return FixedArray::cast(break_point_objects())->length();
18483}
18484
18485
18486// static
18487MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
18488                                Handle<JSReceiver> new_target, double tv) {
18489  Isolate* const isolate = constructor->GetIsolate();
18490  Handle<JSObject> result;
18491  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
18492                             JSObject::New(constructor, new_target), JSDate);
18493  if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
18494    tv = DoubleToInteger(tv) + 0.0;
18495  } else {
18496    tv = std::numeric_limits<double>::quiet_NaN();
18497  }
18498  Handle<Object> value = isolate->factory()->NewNumber(tv);
18499  Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
18500  return Handle<JSDate>::cast(result);
18501}
18502
18503
18504// static
18505double JSDate::CurrentTimeValue(Isolate* isolate) {
18506  if (FLAG_log_timer_events || FLAG_prof_cpp) LOG(isolate, CurrentTimeEvent());
18507
18508  // According to ECMA-262, section 15.9.1, page 117, the precision of
18509  // the number in a Date object representing a particular instant in
18510  // time is milliseconds. Therefore, we floor the result of getting
18511  // the OS time.
18512  return Floor(FLAG_verify_predictable
18513                   ? isolate->heap()->MonotonicallyIncreasingTimeInMs()
18514                   : base::OS::TimeCurrentMillis());
18515}
18516
18517
18518// static
18519Object* JSDate::GetField(Object* object, Smi* index) {
18520  return JSDate::cast(object)->DoGetField(
18521      static_cast<FieldIndex>(index->value()));
18522}
18523
18524
18525Object* JSDate::DoGetField(FieldIndex index) {
18526  DCHECK(index != kDateValue);
18527
18528  DateCache* date_cache = GetIsolate()->date_cache();
18529
18530  if (index < kFirstUncachedField) {
18531    Object* stamp = cache_stamp();
18532    if (stamp != date_cache->stamp() && stamp->IsSmi()) {
18533      // Since the stamp is not NaN, the value is also not NaN.
18534      int64_t local_time_ms =
18535          date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
18536      SetCachedFields(local_time_ms, date_cache);
18537    }
18538    switch (index) {
18539      case kYear: return year();
18540      case kMonth: return month();
18541      case kDay: return day();
18542      case kWeekday: return weekday();
18543      case kHour: return hour();
18544      case kMinute: return min();
18545      case kSecond: return sec();
18546      default: UNREACHABLE();
18547    }
18548  }
18549
18550  if (index >= kFirstUTCField) {
18551    return GetUTCField(index, value()->Number(), date_cache);
18552  }
18553
18554  double time = value()->Number();
18555  if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
18556
18557  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
18558  int days = DateCache::DaysFromTime(local_time_ms);
18559
18560  if (index == kDays) return Smi::FromInt(days);
18561
18562  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18563  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
18564  DCHECK(index == kTimeInDay);
18565  return Smi::FromInt(time_in_day_ms);
18566}
18567
18568
18569Object* JSDate::GetUTCField(FieldIndex index,
18570                            double value,
18571                            DateCache* date_cache) {
18572  DCHECK(index >= kFirstUTCField);
18573
18574  if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
18575
18576  int64_t time_ms = static_cast<int64_t>(value);
18577
18578  if (index == kTimezoneOffset) {
18579    return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
18580  }
18581
18582  int days = DateCache::DaysFromTime(time_ms);
18583
18584  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
18585
18586  if (index <= kDayUTC) {
18587    int year, month, day;
18588    date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18589    if (index == kYearUTC) return Smi::FromInt(year);
18590    if (index == kMonthUTC) return Smi::FromInt(month);
18591    DCHECK(index == kDayUTC);
18592    return Smi::FromInt(day);
18593  }
18594
18595  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
18596  switch (index) {
18597    case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
18598    case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
18599    case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
18600    case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
18601    case kDaysUTC: return Smi::FromInt(days);
18602    case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
18603    default: UNREACHABLE();
18604  }
18605
18606  UNREACHABLE();
18607  return NULL;
18608}
18609
18610
18611// static
18612Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
18613  Isolate* const isolate = date->GetIsolate();
18614  Handle<Object> value = isolate->factory()->NewNumber(v);
18615  bool value_is_nan = std::isnan(v);
18616  date->SetValue(*value, value_is_nan);
18617  return value;
18618}
18619
18620
18621void JSDate::SetValue(Object* value, bool is_value_nan) {
18622  set_value(value);
18623  if (is_value_nan) {
18624    HeapNumber* nan = GetIsolate()->heap()->nan_value();
18625    set_cache_stamp(nan, SKIP_WRITE_BARRIER);
18626    set_year(nan, SKIP_WRITE_BARRIER);
18627    set_month(nan, SKIP_WRITE_BARRIER);
18628    set_day(nan, SKIP_WRITE_BARRIER);
18629    set_hour(nan, SKIP_WRITE_BARRIER);
18630    set_min(nan, SKIP_WRITE_BARRIER);
18631    set_sec(nan, SKIP_WRITE_BARRIER);
18632    set_weekday(nan, SKIP_WRITE_BARRIER);
18633  } else {
18634    set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
18635  }
18636}
18637
18638
18639// static
18640MaybeHandle<Object> JSDate::ToPrimitive(Handle<JSReceiver> receiver,
18641                                        Handle<Object> hint) {
18642  Isolate* const isolate = receiver->GetIsolate();
18643  if (hint->IsString()) {
18644    Handle<String> hint_string = Handle<String>::cast(hint);
18645    if (hint_string->Equals(isolate->heap()->number_string())) {
18646      return JSReceiver::OrdinaryToPrimitive(receiver,
18647                                             OrdinaryToPrimitiveHint::kNumber);
18648    }
18649    if (hint_string->Equals(isolate->heap()->default_string()) ||
18650        hint_string->Equals(isolate->heap()->string_string())) {
18651      return JSReceiver::OrdinaryToPrimitive(receiver,
18652                                             OrdinaryToPrimitiveHint::kString);
18653    }
18654  }
18655  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidHint, hint),
18656                  Object);
18657}
18658
18659
18660void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
18661  int days = DateCache::DaysFromTime(local_time_ms);
18662  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
18663  int year, month, day;
18664  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
18665  int weekday = date_cache->Weekday(days);
18666  int hour = time_in_day_ms / (60 * 60 * 1000);
18667  int min = (time_in_day_ms / (60 * 1000)) % 60;
18668  int sec = (time_in_day_ms / 1000) % 60;
18669  set_cache_stamp(date_cache->stamp());
18670  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
18671  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
18672  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
18673  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
18674  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
18675  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
18676  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
18677}
18678
18679
18680void JSArrayBuffer::Neuter() {
18681  CHECK(is_neuterable());
18682  CHECK(is_external());
18683  set_backing_store(NULL);
18684  set_byte_length(Smi::FromInt(0));
18685  set_was_neutered(true);
18686}
18687
18688
18689void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
18690                          bool is_external, void* data, size_t allocated_length,
18691                          SharedFlag shared) {
18692  DCHECK(array_buffer->GetInternalFieldCount() ==
18693         v8::ArrayBuffer::kInternalFieldCount);
18694  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
18695    array_buffer->SetInternalField(i, Smi::FromInt(0));
18696  }
18697  array_buffer->set_bit_field(0);
18698  array_buffer->set_is_external(is_external);
18699  array_buffer->set_is_neuterable(shared == SharedFlag::kNotShared);
18700  array_buffer->set_is_shared(shared == SharedFlag::kShared);
18701
18702  Handle<Object> byte_length =
18703      isolate->factory()->NewNumberFromSize(allocated_length);
18704  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
18705  array_buffer->set_byte_length(*byte_length);
18706  // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
18707  // are currently being constructed in the |ArrayBufferTracker|. The
18708  // registration method below handles the case of registering a buffer that has
18709  // already been promoted.
18710  array_buffer->set_backing_store(data);
18711
18712  if (data && !is_external) {
18713    isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
18714  }
18715}
18716
18717
18718bool JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer> array_buffer,
18719                                        Isolate* isolate,
18720                                        size_t allocated_length,
18721                                        bool initialize, SharedFlag shared) {
18722  void* data;
18723  CHECK(isolate->array_buffer_allocator() != NULL);
18724  // Prevent creating array buffers when serializing.
18725  DCHECK(!isolate->serializer_enabled());
18726  if (allocated_length != 0) {
18727    if (initialize) {
18728      data = isolate->array_buffer_allocator()->Allocate(allocated_length);
18729    } else {
18730      data = isolate->array_buffer_allocator()->AllocateUninitialized(
18731          allocated_length);
18732    }
18733    if (data == NULL) return false;
18734  } else {
18735    data = NULL;
18736  }
18737
18738  JSArrayBuffer::Setup(array_buffer, isolate, false, data, allocated_length,
18739                       shared);
18740  return true;
18741}
18742
18743
18744Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
18745    Handle<JSTypedArray> typed_array) {
18746
18747  Handle<Map> map(typed_array->map());
18748  Isolate* isolate = typed_array->GetIsolate();
18749
18750  DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
18751
18752  Handle<FixedTypedArrayBase> fixed_typed_array(
18753      FixedTypedArrayBase::cast(typed_array->elements()));
18754
18755  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
18756                               isolate);
18757  void* backing_store =
18758      isolate->array_buffer_allocator()->AllocateUninitialized(
18759          fixed_typed_array->DataSize());
18760  buffer->set_is_external(false);
18761  DCHECK(buffer->byte_length()->IsSmi() ||
18762         buffer->byte_length()->IsHeapNumber());
18763  DCHECK(NumberToInt32(buffer->byte_length()) == fixed_typed_array->DataSize());
18764  // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
18765  // are currently being constructed in the |ArrayBufferTracker|. The
18766  // registration method below handles the case of registering a buffer that has
18767  // already been promoted.
18768  buffer->set_backing_store(backing_store);
18769  isolate->heap()->RegisterNewArrayBuffer(*buffer);
18770  memcpy(buffer->backing_store(),
18771         fixed_typed_array->DataPtr(),
18772         fixed_typed_array->DataSize());
18773  Handle<FixedTypedArrayBase> new_elements =
18774      isolate->factory()->NewFixedTypedArrayWithExternalPointer(
18775          fixed_typed_array->length(), typed_array->type(),
18776          static_cast<uint8_t*>(buffer->backing_store()));
18777
18778  typed_array->set_elements(*new_elements);
18779
18780  return buffer;
18781}
18782
18783
18784Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
18785  Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
18786                                     GetIsolate());
18787  if (array_buffer->was_neutered() ||
18788      array_buffer->backing_store() != nullptr) {
18789    return array_buffer;
18790  }
18791  Handle<JSTypedArray> self(this);
18792  return MaterializeArrayBuffer(self);
18793}
18794
18795
18796Handle<PropertyCell> PropertyCell::InvalidateEntry(
18797    Handle<GlobalDictionary> dictionary, int entry) {
18798  Isolate* isolate = dictionary->GetIsolate();
18799  // Swap with a copy.
18800  DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
18801  Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
18802  auto new_cell = isolate->factory()->NewPropertyCell();
18803  new_cell->set_value(cell->value());
18804  dictionary->ValueAtPut(entry, *new_cell);
18805  bool is_the_hole = cell->value()->IsTheHole(isolate);
18806  // Cell is officially mutable henceforth.
18807  PropertyDetails details = cell->property_details();
18808  details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
18809                                              : PropertyCellType::kMutable);
18810  new_cell->set_property_details(details);
18811  // Old cell is ready for invalidation.
18812  if (is_the_hole) {
18813    cell->set_value(isolate->heap()->undefined_value());
18814  } else {
18815    cell->set_value(isolate->heap()->the_hole_value());
18816  }
18817  details = details.set_cell_type(PropertyCellType::kInvalidated);
18818  cell->set_property_details(details);
18819  cell->dependent_code()->DeoptimizeDependentCodeGroup(
18820      isolate, DependentCode::kPropertyCellChangedGroup);
18821  return new_cell;
18822}
18823
18824
18825PropertyCellConstantType PropertyCell::GetConstantType() {
18826  if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
18827  return PropertyCellConstantType::kStableMap;
18828}
18829
18830
18831static bool RemainsConstantType(Handle<PropertyCell> cell,
18832                                Handle<Object> value) {
18833  // TODO(dcarney): double->smi and smi->double transition from kConstant
18834  if (cell->value()->IsSmi() && value->IsSmi()) {
18835    return true;
18836  } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
18837    return HeapObject::cast(cell->value())->map() ==
18838               HeapObject::cast(*value)->map() &&
18839           HeapObject::cast(*value)->map()->is_stable();
18840  }
18841  return false;
18842}
18843
18844
18845PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
18846                                           Handle<Object> value,
18847                                           PropertyDetails details) {
18848  PropertyCellType type = details.cell_type();
18849  Isolate* isolate = cell->GetIsolate();
18850  DCHECK(!value->IsTheHole(isolate));
18851  if (cell->value()->IsTheHole(isolate)) {
18852    switch (type) {
18853      // Only allow a cell to transition once into constant state.
18854      case PropertyCellType::kUninitialized:
18855        if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
18856        return PropertyCellType::kConstant;
18857      case PropertyCellType::kInvalidated:
18858        return PropertyCellType::kMutable;
18859      default:
18860        UNREACHABLE();
18861        return PropertyCellType::kMutable;
18862    }
18863  }
18864  switch (type) {
18865    case PropertyCellType::kUndefined:
18866      return PropertyCellType::kConstant;
18867    case PropertyCellType::kConstant:
18868      if (*value == cell->value()) return PropertyCellType::kConstant;
18869    // Fall through.
18870    case PropertyCellType::kConstantType:
18871      if (RemainsConstantType(cell, value)) {
18872        return PropertyCellType::kConstantType;
18873      }
18874    // Fall through.
18875    case PropertyCellType::kMutable:
18876      return PropertyCellType::kMutable;
18877  }
18878  UNREACHABLE();
18879  return PropertyCellType::kMutable;
18880}
18881
18882
18883void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
18884                              Handle<Object> value, PropertyDetails details) {
18885  Isolate* isolate = dictionary->GetIsolate();
18886  DCHECK(!value->IsTheHole(isolate));
18887  DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
18888  Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
18889  const PropertyDetails original_details = cell->property_details();
18890  // Data accesses could be cached in ics or optimized code.
18891  bool invalidate =
18892      original_details.kind() == kData && details.kind() == kAccessor;
18893  int index = original_details.dictionary_index();
18894  PropertyCellType old_type = original_details.cell_type();
18895  // Preserve the enumeration index unless the property was deleted or never
18896  // initialized.
18897  if (cell->value()->IsTheHole(isolate)) {
18898    index = dictionary->NextEnumerationIndex();
18899    dictionary->SetNextEnumerationIndex(index + 1);
18900    // Negative lookup cells must be invalidated.
18901    invalidate = true;
18902  }
18903  DCHECK(index > 0);
18904  details = details.set_index(index);
18905
18906  PropertyCellType new_type = UpdatedType(cell, value, original_details);
18907  if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
18908
18909  // Install new property details and cell value.
18910  details = details.set_cell_type(new_type);
18911  cell->set_property_details(details);
18912  cell->set_value(*value);
18913
18914  // Deopt when transitioning from a constant type.
18915  if (!invalidate && (old_type != new_type ||
18916                      original_details.IsReadOnly() != details.IsReadOnly())) {
18917    cell->dependent_code()->DeoptimizeDependentCodeGroup(
18918        isolate, DependentCode::kPropertyCellChangedGroup);
18919  }
18920}
18921
18922
18923// static
18924void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
18925                                            Handle<Object> new_value) {
18926  if (cell->value() != *new_value) {
18927    cell->set_value(*new_value);
18928    Isolate* isolate = cell->GetIsolate();
18929    cell->dependent_code()->DeoptimizeDependentCodeGroup(
18930        isolate, DependentCode::kPropertyCellChangedGroup);
18931  }
18932}
18933
18934int JSGeneratorObject::source_position() const {
18935  CHECK(is_suspended());
18936  if (function()->shared()->HasBytecodeArray()) {
18937    // New-style generators.
18938    int offset = Smi::cast(input_or_debug_pos())->value();
18939    // The stored bytecode offset is relative to a different base than what
18940    // is used in the source position table, hence the subtraction.
18941    offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
18942    return function()->shared()->bytecode_array()->SourcePosition(offset);
18943  } else {
18944    // Old-style generators.
18945    int offset = continuation();
18946    CHECK(0 <= offset && offset < function()->code()->instruction_size());
18947    return function()->code()->SourcePosition(offset);
18948  }
18949}
18950
18951// static
18952AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
18953                                      Handle<JSObject> receiver) {
18954  DisallowHeapAllocation no_gc;
18955  DCHECK(receiver->map()->is_access_check_needed());
18956  Object* maybe_constructor = receiver->map()->GetConstructor();
18957  // Might happen for a detached context.
18958  if (!maybe_constructor->IsJSFunction()) return nullptr;
18959  JSFunction* constructor = JSFunction::cast(maybe_constructor);
18960  // Might happen for the debug context.
18961  if (!constructor->shared()->IsApiFunction()) return nullptr;
18962
18963  Object* data_obj =
18964      constructor->shared()->get_api_func_data()->access_check_info();
18965  if (data_obj->IsUndefined(isolate)) return nullptr;
18966
18967  return AccessCheckInfo::cast(data_obj);
18968}
18969
18970}  // namespace internal
18971}  // namespace v8
18972