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/accessors.h"
12#include "src/allocation-site-scopes.h"
13#include "src/api.h"
14#include "src/arguments.h"
15#include "src/base/bits.h"
16#include "src/base/utils/random-number-generator.h"
17#include "src/bootstrapper.h"
18#include "src/code-stubs.h"
19#include "src/codegen.h"
20#include "src/compilation-dependencies.h"
21#include "src/compiler.h"
22#include "src/date.h"
23#include "src/debug/debug.h"
24#include "src/deoptimizer.h"
25#include "src/elements.h"
26#include "src/execution.h"
27#include "src/field-index.h"
28#include "src/field-index-inl.h"
29#include "src/full-codegen/full-codegen.h"
30#include "src/ic/ic.h"
31#include "src/identity-map.h"
32#include "src/interpreter/bytecodes.h"
33#include "src/isolate-inl.h"
34#include "src/key-accumulator.h"
35#include "src/list.h"
36#include "src/log.h"
37#include "src/lookup.h"
38#include "src/macro-assembler.h"
39#include "src/messages.h"
40#include "src/objects-inl.h"
41#include "src/objects-body-descriptors-inl.h"
42#include "src/profiler/cpu-profiler.h"
43#include "src/property-descriptor.h"
44#include "src/prototype.h"
45#include "src/regexp/jsregexp.h"
46#include "src/safepoint-table.h"
47#include "src/string-builder.h"
48#include "src/string-search.h"
49#include "src/string-stream.h"
50#include "src/utils.h"
51#include "src/zone.h"
52
53#ifdef ENABLE_DISASSEMBLER
54#include "src/disasm.h"
55#include "src/disassembler.h"
56#endif
57
58namespace v8 {
59namespace internal {
60
61std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
62  switch (instance_type) {
63#define WRITE_TYPE(TYPE) \
64  case TYPE:             \
65    return os << #TYPE;
66    INSTANCE_TYPE_LIST(WRITE_TYPE)
67#undef WRITE_TYPE
68  }
69  UNREACHABLE();
70  return os << "UNKNOWN";  // Keep the compiler happy.
71}
72
73
74Handle<HeapType> Object::OptimalType(Isolate* isolate,
75                                     Representation representation) {
76  if (representation.IsNone()) return HeapType::None(isolate);
77  if (FLAG_track_field_types) {
78    if (representation.IsHeapObject() && IsHeapObject()) {
79      // We can track only JavaScript objects with stable maps.
80      Handle<Map> map(HeapObject::cast(this)->map(), isolate);
81      if (map->is_stable() && map->IsJSReceiverMap()) {
82        return HeapType::Class(map, isolate);
83      }
84    }
85  }
86  return HeapType::Any(isolate);
87}
88
89
90MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
91                                         Handle<Object> object,
92                                         Handle<Context> native_context) {
93  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
94  Handle<JSFunction> constructor;
95  if (object->IsSmi()) {
96    constructor = handle(native_context->number_function(), isolate);
97  } else {
98    int constructor_function_index =
99        Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
100    if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
101      return MaybeHandle<JSReceiver>();
102    }
103    constructor = handle(
104        JSFunction::cast(native_context->get(constructor_function_index)),
105        isolate);
106  }
107  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
108  Handle<JSValue>::cast(result)->set_value(*object);
109  return result;
110}
111
112
113// static
114MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
115  ASSIGN_RETURN_ON_EXCEPTION(
116      isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
117      Name);
118  if (input->IsName()) return Handle<Name>::cast(input);
119  return ToString(isolate, input);
120}
121
122
123// static
124MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
125  while (true) {
126    if (input->IsNumber()) {
127      return input;
128    }
129    if (input->IsString()) {
130      return String::ToNumber(Handle<String>::cast(input));
131    }
132    if (input->IsOddball()) {
133      return Oddball::ToNumber(Handle<Oddball>::cast(input));
134    }
135    Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
136    if (input->IsSymbol()) {
137      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
138                      Object);
139    }
140    if (input->IsSimd128Value()) {
141      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber),
142                      Object);
143    }
144    ASSIGN_RETURN_ON_EXCEPTION(
145        isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
146                                                ToPrimitiveHint::kNumber),
147        Object);
148  }
149}
150
151
152// static
153MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
154  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
155  return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
156}
157
158
159// static
160MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
161  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
162  return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
163}
164
165
166// static
167MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
168  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
169  return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
170}
171
172
173// static
174MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
175  while (true) {
176    if (input->IsString()) {
177      return Handle<String>::cast(input);
178    }
179    if (input->IsOddball()) {
180      return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
181    }
182    if (input->IsNumber()) {
183      return isolate->factory()->NumberToString(input);
184    }
185    if (input->IsSymbol()) {
186      THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
187                      String);
188    }
189    if (input->IsSimd128Value()) {
190      return Simd128Value::ToString(Handle<Simd128Value>::cast(input));
191    }
192    ASSIGN_RETURN_ON_EXCEPTION(
193        isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
194                                                ToPrimitiveHint::kString),
195        String);
196  }
197}
198
199
200// static
201MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
202  ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
203  double len = DoubleToInteger(input->Number());
204  if (len <= 0.0) {
205    len = 0.0;
206  } else if (len >= kMaxSafeInteger) {
207    len = kMaxSafeInteger;
208  }
209  return isolate->factory()->NewNumber(len);
210}
211
212
213bool Object::BooleanValue() {
214  if (IsBoolean()) return IsTrue();
215  if (IsSmi()) return Smi::cast(this)->value() != 0;
216  if (IsUndefined() || IsNull()) return false;
217  if (IsUndetectableObject()) return false;   // Undetectable object is false.
218  if (IsString()) return String::cast(this)->length() != 0;
219  if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
220  return true;
221}
222
223
224namespace {
225
226// TODO(bmeurer): Maybe we should introduce a marker interface Number,
227// where we put all these methods at some point?
228ComparisonResult NumberCompare(double x, double y) {
229  if (std::isnan(x) || std::isnan(y)) {
230    return ComparisonResult::kUndefined;
231  } else if (x < y) {
232    return ComparisonResult::kLessThan;
233  } else if (x > y) {
234    return ComparisonResult::kGreaterThan;
235  } else {
236    return ComparisonResult::kEqual;
237  }
238}
239
240
241bool NumberEquals(double x, double y) {
242  // Must check explicitly for NaN's on Windows, but -0 works fine.
243  if (std::isnan(x)) return false;
244  if (std::isnan(y)) return false;
245  return x == y;
246}
247
248
249bool NumberEquals(const Object* x, const Object* y) {
250  return NumberEquals(x->Number(), y->Number());
251}
252
253
254bool NumberEquals(Handle<Object> x, Handle<Object> y) {
255  return NumberEquals(*x, *y);
256}
257
258}  // namespace
259
260
261// static
262Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y,
263                                        Strength strength) {
264  if (!is_strong(strength)) {
265    // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
266    if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
267        !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
268      return Nothing<ComparisonResult>();
269    }
270  }
271  if (x->IsString() && y->IsString()) {
272    // ES6 section 7.2.11 Abstract Relational Comparison step 5.
273    return Just(
274        String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
275  }
276  // ES6 section 7.2.11 Abstract Relational Comparison step 6.
277  if (!is_strong(strength)) {
278    if (!Object::ToNumber(x).ToHandle(&x) ||
279        !Object::ToNumber(y).ToHandle(&y)) {
280      return Nothing<ComparisonResult>();
281    }
282  } else {
283    if (!x->IsNumber()) {
284      Isolate* const isolate = Handle<HeapObject>::cast(x)->GetIsolate();
285      isolate->Throw(*isolate->factory()->NewTypeError(
286          MessageTemplate::kStrongImplicitConversion));
287      return Nothing<ComparisonResult>();
288    } else if (!y->IsNumber()) {
289      Isolate* const isolate = Handle<HeapObject>::cast(y)->GetIsolate();
290      isolate->Throw(*isolate->factory()->NewTypeError(
291          MessageTemplate::kStrongImplicitConversion));
292      return Nothing<ComparisonResult>();
293    }
294  }
295  return Just(NumberCompare(x->Number(), y->Number()));
296}
297
298
299// static
300Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
301  while (true) {
302    if (x->IsNumber()) {
303      if (y->IsNumber()) {
304        return Just(NumberEquals(x, y));
305      } else if (y->IsBoolean()) {
306        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
307      } else if (y->IsString()) {
308        return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
309      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
310        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
311                 .ToHandle(&y)) {
312          return Nothing<bool>();
313        }
314      } else {
315        return Just(false);
316      }
317    } else if (x->IsString()) {
318      if (y->IsString()) {
319        return Just(
320            String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
321      } else if (y->IsNumber()) {
322        x = String::ToNumber(Handle<String>::cast(x));
323        return Just(NumberEquals(x, y));
324      } else if (y->IsBoolean()) {
325        x = String::ToNumber(Handle<String>::cast(x));
326        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
327      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
328        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
329                 .ToHandle(&y)) {
330          return Nothing<bool>();
331        }
332      } else {
333        return Just(false);
334      }
335    } else if (x->IsBoolean()) {
336      if (y->IsOddball()) {
337        return Just(x.is_identical_to(y));
338      } else if (y->IsNumber()) {
339        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
340      } else if (y->IsString()) {
341        y = String::ToNumber(Handle<String>::cast(y));
342        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
343      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
344        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
345                 .ToHandle(&y)) {
346          return Nothing<bool>();
347        }
348        x = Oddball::ToNumber(Handle<Oddball>::cast(x));
349      } else {
350        return Just(false);
351      }
352    } else if (x->IsSymbol()) {
353      if (y->IsSymbol()) {
354        return Just(x.is_identical_to(y));
355      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
356        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
357                 .ToHandle(&y)) {
358          return Nothing<bool>();
359        }
360      } else {
361        return Just(false);
362      }
363    } else if (x->IsSimd128Value()) {
364      if (y->IsSimd128Value()) {
365        return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
366                                         Handle<Simd128Value>::cast(y)));
367      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
368        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
369                 .ToHandle(&y)) {
370          return Nothing<bool>();
371        }
372      } else {
373        return Just(false);
374      }
375    } else if (x->IsJSReceiver() && !x->IsUndetectableObject()) {
376      if (y->IsJSReceiver()) {
377        return Just(x.is_identical_to(y));
378      } else if (y->IsNull() || y->IsUndefined()) {
379        return Just(false);
380      } else if (y->IsBoolean()) {
381        y = Oddball::ToNumber(Handle<Oddball>::cast(y));
382      } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
383                      .ToHandle(&x)) {
384        return Nothing<bool>();
385      }
386    } else {
387      return Just(
388          (x->IsNull() || x->IsUndefined() || x->IsUndetectableObject()) &&
389          (y->IsNull() || y->IsUndefined() || y->IsUndetectableObject()));
390    }
391  }
392}
393
394
395bool Object::StrictEquals(Object* that) {
396  if (this->IsNumber()) {
397    if (!that->IsNumber()) return false;
398    return NumberEquals(this, that);
399  } else if (this->IsString()) {
400    if (!that->IsString()) return false;
401    return String::cast(this)->Equals(String::cast(that));
402  } else if (this->IsSimd128Value()) {
403    if (!that->IsSimd128Value()) return false;
404    return Simd128Value::cast(this)->Equals(Simd128Value::cast(that));
405  }
406  return this == that;
407}
408
409
410// static
411Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
412  if (object->IsNumber()) return isolate->factory()->number_string();
413  if (object->IsUndefined() || object->IsUndetectableObject()) {
414    return isolate->factory()->undefined_string();
415  }
416  if (object->IsBoolean()) return isolate->factory()->boolean_string();
417  if (object->IsString()) return isolate->factory()->string_string();
418  if (object->IsSymbol()) return isolate->factory()->symbol_string();
419  if (object->IsString()) return isolate->factory()->string_string();
420#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
421  if (object->Is##Type()) return isolate->factory()->type##_string();
422  SIMD128_TYPES(SIMD128_TYPE)
423#undef SIMD128_TYPE
424  if (object->IsCallable()) return isolate->factory()->function_string();
425  return isolate->factory()->object_string();
426}
427
428
429// static
430MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
431                                     Handle<Object> rhs, Strength strength) {
432  if (!lhs->IsNumber() || !rhs->IsNumber()) {
433    if (is_strong(strength)) {
434      THROW_NEW_ERROR(isolate,
435                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
436                      Object);
437    }
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, Strength strength) {
448  if (!lhs->IsNumber() || !rhs->IsNumber()) {
449    if (is_strong(strength)) {
450      THROW_NEW_ERROR(isolate,
451                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
452                      Object);
453    }
454    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
455    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
456  }
457  return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
458}
459
460
461// static
462MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
463                                    Handle<Object> rhs, Strength strength) {
464  if (!lhs->IsNumber() || !rhs->IsNumber()) {
465    if (is_strong(strength)) {
466      THROW_NEW_ERROR(isolate,
467                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
468                      Object);
469    }
470    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
471    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
472  }
473  return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
474}
475
476
477// static
478MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
479                                Handle<Object> rhs, Strength strength) {
480  if (lhs->IsNumber() && rhs->IsNumber()) {
481    return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
482  } else if (lhs->IsString() && rhs->IsString()) {
483    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
484                                             Handle<String>::cast(rhs));
485  } else if (is_strong(strength)) {
486    THROW_NEW_ERROR(isolate,
487                    NewTypeError(MessageTemplate::kStrongImplicitConversion),
488                    Object);
489  }
490  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
491  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
492  if (lhs->IsString() || rhs->IsString()) {
493    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
494                               Object);
495    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
496                               Object);
497    return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
498                                             Handle<String>::cast(rhs));
499  }
500  ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
501  ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
502  return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
503}
504
505
506// static
507MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
508                                     Handle<Object> rhs, Strength strength) {
509  if (!lhs->IsNumber() || !rhs->IsNumber()) {
510    if (is_strong(strength)) {
511      THROW_NEW_ERROR(isolate,
512                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
513                      Object);
514    }
515    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
516    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
517  }
518  return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
519}
520
521
522// static
523MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
524                                      Handle<Object> rhs, Strength strength) {
525  if (!lhs->IsNumber() || !rhs->IsNumber()) {
526    if (is_strong(strength)) {
527      THROW_NEW_ERROR(isolate,
528                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
529                      Object);
530    }
531    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
532    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
533  }
534  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
535                                              << (NumberToUint32(*rhs) & 0x1F));
536}
537
538
539// static
540MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
541                                       Handle<Object> rhs, Strength strength) {
542  if (!lhs->IsNumber() || !rhs->IsNumber()) {
543    if (is_strong(strength)) {
544      THROW_NEW_ERROR(isolate,
545                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
546                      Object);
547    }
548    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
549    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
550  }
551  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
552                                              (NumberToUint32(*rhs) & 0x1F));
553}
554
555
556// static
557MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
558                                              Handle<Object> lhs,
559                                              Handle<Object> rhs,
560                                              Strength strength) {
561  if (!lhs->IsNumber() || !rhs->IsNumber()) {
562    if (is_strong(strength)) {
563      THROW_NEW_ERROR(isolate,
564                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
565                      Object);
566    }
567    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
568    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
569  }
570  return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
571                                               (NumberToUint32(*rhs) & 0x1F));
572}
573
574
575// static
576MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
577                                       Handle<Object> rhs, Strength strength) {
578  if (!lhs->IsNumber() || !rhs->IsNumber()) {
579    if (is_strong(strength)) {
580      THROW_NEW_ERROR(isolate,
581                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
582                      Object);
583    }
584    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
585    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
586  }
587  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
588                                              NumberToInt32(*rhs));
589}
590
591
592// static
593MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
594                                      Handle<Object> rhs, Strength strength) {
595  if (!lhs->IsNumber() || !rhs->IsNumber()) {
596    if (is_strong(strength)) {
597      THROW_NEW_ERROR(isolate,
598                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
599                      Object);
600    }
601    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
602    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
603  }
604  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
605                                              NumberToInt32(*rhs));
606}
607
608
609// static
610MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
611                                       Handle<Object> rhs, Strength strength) {
612  if (!lhs->IsNumber() || !rhs->IsNumber()) {
613    if (is_strong(strength)) {
614      THROW_NEW_ERROR(isolate,
615                      NewTypeError(MessageTemplate::kStrongImplicitConversion),
616                      Object);
617    }
618    ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
619    ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
620  }
621  return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
622                                              NumberToInt32(*rhs));
623}
624
625
626Maybe<bool> Object::IsArray(Handle<Object> object) {
627  if (object->IsJSArray()) return Just(true);
628  if (object->IsJSProxy()) {
629    Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
630    Isolate* isolate = proxy->GetIsolate();
631    if (proxy->IsRevoked()) {
632      isolate->Throw(*isolate->factory()->NewTypeError(
633          MessageTemplate::kProxyRevoked,
634          isolate->factory()->NewStringFromAsciiChecked("IsArray")));
635      return Nothing<bool>();
636    }
637    return Object::IsArray(handle(proxy->target(), isolate));
638  }
639  return Just(false);
640}
641
642
643bool Object::IsPromise(Handle<Object> object) {
644  if (!object->IsJSObject()) return false;
645  auto js_object = Handle<JSObject>::cast(object);
646  // Promises can't have access checks.
647  if (js_object->map()->is_access_check_needed()) return false;
648  auto isolate = js_object->GetIsolate();
649  // TODO(dcarney): this should just be read from the symbol registry so as not
650  // to be context dependent.
651  auto key = isolate->factory()->promise_status_symbol();
652  // Shouldn't be possible to throw here.
653  return JSObject::HasRealNamedProperty(js_object, key).FromJust();
654}
655
656
657// static
658MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
659                                      Handle<Name> name) {
660  Handle<Object> func;
661  Isolate* isolate = receiver->GetIsolate();
662  ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
663                             JSReceiver::GetProperty(receiver, name), Object);
664  if (func->IsNull() || func->IsUndefined()) {
665    return isolate->factory()->undefined_value();
666  }
667  if (!func->IsCallable()) {
668    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
669                                          func, name, receiver),
670                    Object);
671  }
672  return func;
673}
674
675
676// static
677MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
678    Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
679  // 1. ReturnIfAbrupt(object).
680  // 2. (default elementTypes -- not applicable.)
681  // 3. If Type(obj) is not Object, throw a TypeError exception.
682  if (!object->IsJSReceiver()) {
683    THROW_NEW_ERROR(isolate,
684                    NewTypeError(MessageTemplate::kCalledOnNonObject,
685                                 isolate->factory()->NewStringFromAsciiChecked(
686                                     "CreateListFromArrayLike")),
687                    FixedArray);
688  }
689  // 4. Let len be ? ToLength(? Get(obj, "length")).
690  Handle<Object> raw_length_obj;
691  ASSIGN_RETURN_ON_EXCEPTION(
692      isolate, raw_length_obj,
693      JSReceiver::GetProperty(object, isolate->factory()->length_string()),
694      FixedArray);
695  Handle<Object> raw_length_number;
696  ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
697                             Object::ToLength(isolate, raw_length_obj),
698                             FixedArray);
699  uint32_t len;
700  if (!raw_length_number->ToUint32(&len) ||
701      len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
702    THROW_NEW_ERROR(isolate,
703                    NewRangeError(MessageTemplate::kInvalidArrayLength),
704                    FixedArray);
705  }
706  // 5. Let list be an empty List.
707  Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
708  // 6. Let index be 0.
709  // 7. Repeat while index < len:
710  for (uint32_t index = 0; index < len; ++index) {
711    // 7a. Let indexName be ToString(index).
712    // 7b. Let next be ? Get(obj, indexName).
713    Handle<Object> next;
714    ASSIGN_RETURN_ON_EXCEPTION(
715        isolate, next, Object::GetElement(isolate, object, index), FixedArray);
716    switch (element_types) {
717      case ElementTypes::kAll:
718        // Nothing to do.
719        break;
720      case ElementTypes::kStringAndSymbol: {
721        // 7c. If Type(next) is not an element of elementTypes, throw a
722        //     TypeError exception.
723        if (!next->IsName()) {
724          THROW_NEW_ERROR(isolate,
725                          NewTypeError(MessageTemplate::kNotPropertyName, next),
726                          FixedArray);
727        }
728        // 7d. Append next as the last element of list.
729        // Internalize on the fly so we can use pointer identity later.
730        next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
731        break;
732      }
733    }
734    list->set(index, *next);
735    // 7e. Set index to index + 1. (See loop header.)
736  }
737  // 8. Return list.
738  return list;
739}
740
741
742// static
743Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
744  for (; it->IsFound(); it->Next()) {
745    switch (it->state()) {
746      case LookupIterator::NOT_FOUND:
747      case LookupIterator::TRANSITION:
748        UNREACHABLE();
749      case LookupIterator::JSPROXY:
750        // Call the "has" trap on proxies.
751        return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
752                                    it->GetName());
753      case LookupIterator::INTERCEPTOR: {
754        Maybe<PropertyAttributes> result =
755            JSObject::GetPropertyAttributesWithInterceptor(it);
756        if (!result.IsJust()) return Nothing<bool>();
757        if (result.FromJust() != ABSENT) return Just(true);
758        break;
759      }
760      case LookupIterator::ACCESS_CHECK: {
761        if (it->HasAccess()) break;
762        Maybe<PropertyAttributes> result =
763            JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
764        if (!result.IsJust()) return Nothing<bool>();
765        return Just(result.FromJust() != ABSENT);
766      }
767      case LookupIterator::INTEGER_INDEXED_EXOTIC:
768        // TypedArray out-of-bounds access.
769        return Just(false);
770      case LookupIterator::ACCESSOR:
771      case LookupIterator::DATA:
772        return Just(true);
773    }
774  }
775  return Just(false);
776}
777
778
779// static
780MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
781                                        LanguageMode language_mode) {
782  for (; it->IsFound(); it->Next()) {
783    switch (it->state()) {
784      case LookupIterator::NOT_FOUND:
785      case LookupIterator::TRANSITION:
786        UNREACHABLE();
787      case LookupIterator::JSPROXY:
788        return JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
789                                    it->GetName(), it->GetReceiver(),
790                                    language_mode);
791      case LookupIterator::INTERCEPTOR: {
792        bool done;
793        Handle<Object> result;
794        ASSIGN_RETURN_ON_EXCEPTION(
795            it->isolate(), result,
796            JSObject::GetPropertyWithInterceptor(it, &done), Object);
797        if (done) return result;
798        break;
799      }
800      case LookupIterator::ACCESS_CHECK:
801        if (it->HasAccess()) break;
802        return JSObject::GetPropertyWithFailedAccessCheck(it);
803      case LookupIterator::ACCESSOR:
804        return GetPropertyWithAccessor(it, language_mode);
805      case LookupIterator::INTEGER_INDEXED_EXOTIC:
806        return ReadAbsentProperty(it, language_mode);
807      case LookupIterator::DATA:
808        return it->GetDataValue();
809    }
810  }
811  return ReadAbsentProperty(it, language_mode);
812}
813
814
815#define STACK_CHECK(result_value)                        \
816  do {                                                   \
817    StackLimitCheck stack_check(isolate);                \
818    if (stack_check.HasOverflowed()) {                   \
819      isolate->Throw(*isolate->factory()->NewRangeError( \
820          MessageTemplate::kStackOverflow));             \
821      return result_value;                               \
822    }                                                    \
823  } while (false)
824
825
826// static
827MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
828                                         Handle<JSProxy> proxy,
829                                         Handle<Name> name,
830                                         Handle<Object> receiver,
831                                         LanguageMode language_mode) {
832  if (receiver->IsJSGlobalObject()) {
833    THROW_NEW_ERROR(
834        isolate,
835        NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
836        Object);
837  }
838
839  DCHECK(!name->IsPrivate());
840  STACK_CHECK(MaybeHandle<Object>());
841  Handle<Name> trap_name = isolate->factory()->get_string();
842  // 1. Assert: IsPropertyKey(P) is true.
843  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
844  Handle<Object> handler(proxy->handler(), isolate);
845  // 3. If handler is null, throw a TypeError exception.
846  // 4. Assert: Type(handler) is Object.
847  if (proxy->IsRevoked()) {
848    THROW_NEW_ERROR(isolate,
849                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
850                    Object);
851  }
852  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
853  Handle<JSReceiver> target(proxy->target(), isolate);
854  // 6. Let trap be ? GetMethod(handler, "get").
855  Handle<Object> trap;
856  ASSIGN_RETURN_ON_EXCEPTION(
857      isolate, trap,
858      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
859  // 7. If trap is undefined, then
860  if (trap->IsUndefined()) {
861    // 7.a Return target.[[Get]](P, Receiver).
862    LookupIterator it =
863        LookupIterator::PropertyOrElement(isolate, receiver, name, target);
864    return Object::GetProperty(&it, language_mode);
865  }
866  // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
867  Handle<Object> trap_result;
868  Handle<Object> args[] = {target, name, receiver};
869  ASSIGN_RETURN_ON_EXCEPTION(
870      isolate, trap_result,
871      Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
872  // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
873  PropertyDescriptor target_desc;
874  Maybe<bool> target_found =
875      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
876  MAYBE_RETURN_NULL(target_found);
877  // 10. If targetDesc is not undefined, then
878  if (target_found.FromJust()) {
879    // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
880    //       false and targetDesc.[[Writable]] is false, then
881    // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
882    //        throw a TypeError exception.
883    bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
884                        !target_desc.configurable() &&
885                        !target_desc.writable() &&
886                        !trap_result->SameValue(*target_desc.value());
887    if (inconsistent) {
888      THROW_NEW_ERROR(
889          isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
890                                name, target_desc.value(), trap_result),
891          Object);
892    }
893    // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
894    //       is false and targetDesc.[[Get]] is undefined, then
895    // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
896    inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
897                   !target_desc.configurable() &&
898                   target_desc.get()->IsUndefined() &&
899                   !trap_result->IsUndefined();
900    if (inconsistent) {
901      THROW_NEW_ERROR(
902          isolate,
903          NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
904                       trap_result),
905          Object);
906    }
907  }
908  // 11. Return trap_result
909  return trap_result;
910}
911
912
913Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object,
914                                           Handle<Name> name) {
915  LookupIterator it(object, name,
916                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
917  return GetDataProperty(&it);
918}
919
920
921Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
922  for (; it->IsFound(); it->Next()) {
923    switch (it->state()) {
924      case LookupIterator::INTERCEPTOR:
925      case LookupIterator::NOT_FOUND:
926      case LookupIterator::TRANSITION:
927        UNREACHABLE();
928      case LookupIterator::ACCESS_CHECK:
929        // Support calling this method without an active context, but refuse
930        // access to access-checked objects in that case.
931        if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
932      // Fall through.
933      case LookupIterator::JSPROXY:
934        it->NotFound();
935        return it->isolate()->factory()->undefined_value();
936      case LookupIterator::ACCESSOR:
937        // TODO(verwaest): For now this doesn't call into
938        // ExecutableAccessorInfo, since clients don't need it. Update once
939        // relevant.
940        it->NotFound();
941        return it->isolate()->factory()->undefined_value();
942      case LookupIterator::INTEGER_INDEXED_EXOTIC:
943        return it->isolate()->factory()->undefined_value();
944      case LookupIterator::DATA:
945        return it->GetDataValue();
946    }
947  }
948  return it->isolate()->factory()->undefined_value();
949}
950
951
952bool Object::ToInt32(int32_t* value) {
953  if (IsSmi()) {
954    *value = Smi::cast(this)->value();
955    return true;
956  }
957  if (IsHeapNumber()) {
958    double num = HeapNumber::cast(this)->value();
959    if (FastI2D(FastD2I(num)) == num) {
960      *value = FastD2I(num);
961      return true;
962    }
963  }
964  return false;
965}
966
967
968bool Object::ToUint32(uint32_t* value) {
969  if (IsSmi()) {
970    int num = Smi::cast(this)->value();
971    if (num < 0) return false;
972    *value = static_cast<uint32_t>(num);
973    return true;
974  }
975  if (IsHeapNumber()) {
976    double num = HeapNumber::cast(this)->value();
977    if (num < 0) return false;
978    uint32_t uint_value = FastD2UI(num);
979    if (FastUI2D(uint_value) == num) {
980      *value = uint_value;
981      return true;
982    }
983  }
984  return false;
985}
986
987
988bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
989  if (!object->IsHeapObject()) return false;
990  return IsTemplateFor(HeapObject::cast(object)->map());
991}
992
993
994bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
995  // There is a constraint on the object; check.
996  if (!map->IsJSObjectMap()) return false;
997  // Fetch the constructor function of the object.
998  Object* cons_obj = map->GetConstructor();
999  if (!cons_obj->IsJSFunction()) return false;
1000  JSFunction* fun = JSFunction::cast(cons_obj);
1001  // Iterate through the chain of inheriting function templates to
1002  // see if the required one occurs.
1003  for (Object* type = fun->shared()->function_data();
1004       type->IsFunctionTemplateInfo();
1005       type = FunctionTemplateInfo::cast(type)->parent_template()) {
1006    if (type == this) return true;
1007  }
1008  // Didn't find the required type in the inheritance chain.
1009  return false;
1010}
1011
1012
1013// TODO(dcarney): CallOptimization duplicates this logic, merge.
1014Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
1015                                                    Object* receiver) {
1016  // API calls are only supported with JSObject receivers.
1017  if (!receiver->IsJSObject()) return isolate->heap()->null_value();
1018  Object* recv_type = this->signature();
1019  // No signature, return holder.
1020  if (recv_type->IsUndefined()) return receiver;
1021  FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
1022  // Check the receiver.
1023  for (PrototypeIterator iter(isolate, receiver,
1024                              PrototypeIterator::START_AT_RECEIVER);
1025       !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
1026    if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
1027  }
1028  return isolate->heap()->null_value();
1029}
1030
1031
1032// static
1033MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
1034                                    Handle<JSReceiver> new_target,
1035                                    Handle<AllocationSite> site) {
1036  // If called through new, new.target can be:
1037  // - a subclass of constructor,
1038  // - a proxy wrapper around constructor, or
1039  // - the constructor itself.
1040  // If called through Reflect.construct, it's guaranteed to be a constructor.
1041  Isolate* const isolate = constructor->GetIsolate();
1042  DCHECK(constructor->IsConstructor());
1043  DCHECK(new_target->IsConstructor());
1044  DCHECK(!constructor->has_initial_map() ||
1045         constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
1046
1047  Handle<Map> initial_map;
1048  ASSIGN_RETURN_ON_EXCEPTION(
1049      isolate, initial_map,
1050      JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
1051  Handle<JSObject> result =
1052      isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
1053  isolate->counters()->constructed_objects()->Increment();
1054  isolate->counters()->constructed_objects_runtime()->Increment();
1055  return result;
1056}
1057
1058
1059Handle<FixedArray> JSObject::EnsureWritableFastElements(
1060    Handle<JSObject> object) {
1061  DCHECK(object->HasFastSmiOrObjectElements());
1062  Isolate* isolate = object->GetIsolate();
1063  Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
1064  if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
1065  Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
1066      elems, isolate->factory()->fixed_array_map());
1067  object->set_elements(*writable_elems);
1068  isolate->counters()->cow_arrays_converted()->Increment();
1069  return writable_elems;
1070}
1071
1072
1073// ES6 9.5.1
1074// static
1075MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1076  Isolate* isolate = proxy->GetIsolate();
1077  Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1078
1079  STACK_CHECK(MaybeHandle<Object>());
1080
1081  // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1082  // 2. If handler is null, throw a TypeError exception.
1083  // 3. Assert: Type(handler) is Object.
1084  // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1085  if (proxy->IsRevoked()) {
1086    THROW_NEW_ERROR(isolate,
1087                    NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1088                    Object);
1089  }
1090  Handle<JSReceiver> target(proxy->target(), isolate);
1091  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1092
1093  // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1094  Handle<Object> trap;
1095  ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
1096                             Object);
1097  // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1098  if (trap->IsUndefined()) {
1099    return Object::GetPrototype(isolate, target);
1100  }
1101  // 7. Let handlerProto be ? Call(trap, handler, «target»).
1102  Handle<Object> argv[] = {target};
1103  Handle<Object> handler_proto;
1104  ASSIGN_RETURN_ON_EXCEPTION(
1105      isolate, handler_proto,
1106      Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
1107  // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1108  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) {
1109    THROW_NEW_ERROR(isolate,
1110                    NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1111                    Object);
1112  }
1113  // 9. Let extensibleTarget be ? IsExtensible(target).
1114  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1115  MAYBE_RETURN_NULL(is_extensible);
1116  // 10. If extensibleTarget is true, return handlerProto.
1117  if (is_extensible.FromJust()) return handler_proto;
1118  // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1119  Handle<Object> target_proto;
1120  ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1121                             Object::GetPrototype(isolate, target), Object);
1122  // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1123  if (!handler_proto->SameValue(*target_proto)) {
1124    THROW_NEW_ERROR(
1125        isolate,
1126        NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1127        Object);
1128  }
1129  // 13. Return handlerProto.
1130  return handler_proto;
1131}
1132
1133
1134MaybeHandle<Object> Object::GetPropertyWithAccessor(
1135    LookupIterator* it, LanguageMode language_mode) {
1136  Isolate* isolate = it->isolate();
1137  Handle<Object> structure = it->GetAccessors();
1138  Handle<Object> receiver = it->GetReceiver();
1139
1140  // We should never get here to initialize a const with the hole value since a
1141  // const declaration would conflict with the getter.
1142  DCHECK(!structure->IsForeign());
1143
1144  // API style callbacks.
1145  if (structure->IsAccessorInfo()) {
1146    Handle<JSObject> holder = it->GetHolder<JSObject>();
1147    Handle<Name> name = it->GetName();
1148    Handle<ExecutableAccessorInfo> info =
1149        Handle<ExecutableAccessorInfo>::cast(structure);
1150    if (!info->IsCompatibleReceiver(*receiver)) {
1151      THROW_NEW_ERROR(isolate,
1152                      NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1153                                   name, receiver),
1154                      Object);
1155    }
1156
1157    v8::AccessorNameGetterCallback call_fun =
1158        v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
1159    if (call_fun == nullptr) return isolate->factory()->undefined_value();
1160
1161    LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
1162    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
1163    v8::Local<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(name));
1164    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1165    if (result.IsEmpty()) {
1166      return ReadAbsentProperty(isolate, receiver, name, language_mode);
1167    }
1168    Handle<Object> return_value = v8::Utils::OpenHandle(*result);
1169    return_value->VerifyApiCallResultType();
1170    // Rebox handle before return.
1171    return handle(*return_value, isolate);
1172  }
1173
1174  // Regular accessor.
1175  Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1176  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(), language_mode);
1183}
1184
1185
1186bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
1187                                           Handle<AccessorInfo> info,
1188                                           Handle<Map> map) {
1189  if (!info->HasExpectedReceiverType()) return true;
1190  if (!map->IsJSObjectMap()) return false;
1191  return FunctionTemplateInfo::cast(info->expected_receiver_type())
1192      ->IsTemplateFor(*map);
1193}
1194
1195
1196Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
1197                                            Handle<Object> value,
1198                                            ShouldThrow should_throw) {
1199  Isolate* isolate = it->isolate();
1200  Handle<Object> structure = it->GetAccessors();
1201  Handle<Object> receiver = it->GetReceiver();
1202
1203  // We should never get here to initialize a const with the hole value since a
1204  // const declaration would conflict with the setter.
1205  DCHECK(!structure->IsForeign());
1206
1207  // API style callbacks.
1208  if (structure->IsExecutableAccessorInfo()) {
1209    Handle<JSObject> holder = it->GetHolder<JSObject>();
1210    Handle<Name> name = it->GetName();
1211    Handle<ExecutableAccessorInfo> info =
1212        Handle<ExecutableAccessorInfo>::cast(structure);
1213    if (!info->IsCompatibleReceiver(*receiver)) {
1214      isolate->Throw(*isolate->factory()->NewTypeError(
1215          MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1216      return Nothing<bool>();
1217    }
1218
1219    v8::AccessorNameSetterCallback call_fun =
1220        v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
1221    if (call_fun == nullptr) return Just(true);
1222    // TODO(verwaest): Shouldn't this case be unreachable (at least in the
1223    // long run?) Should we have ExecutableAccessorPairs with missing setter
1224    // that are "writable"? If they aren't writable, shouldn't we have bailed
1225    // out already earlier?
1226
1227    LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
1228    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
1229    args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
1230    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1231    return Just(true);
1232  }
1233
1234  // Regular accessor.
1235  Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1236  if (setter->IsCallable()) {
1237    // TODO(rossberg): nicer would be to cast to some JSCallable here...
1238    return SetPropertyWithDefinedSetter(
1239        receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
1240  }
1241
1242  RETURN_FAILURE(isolate, should_throw,
1243                 NewTypeError(MessageTemplate::kNoSetterInCallback,
1244                              it->GetName(), it->GetHolder<JSObject>()));
1245}
1246
1247
1248MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1249    Handle<Object> receiver,
1250    Handle<JSReceiver> getter) {
1251  Isolate* isolate = getter->GetIsolate();
1252
1253  // Platforms with simulators like arm/arm64 expose a funny issue. If the
1254  // simulator has a separate JS stack pointer from the C++ stack pointer, it
1255  // can miss C++ stack overflows in the stack guard at the start of JavaScript
1256  // functions. It would be very expensive to check the C++ stack pointer at
1257  // that location. The best solution seems to be to break the impasse by
1258  // adding checks at possible recursion points. What's more, we don't put
1259  // this stack check behind the USE_SIMULATOR define in order to keep
1260  // behavior the same between hardware and simulators.
1261  StackLimitCheck check(isolate);
1262  if (check.JsHasOverflowed()) {
1263    isolate->StackOverflow();
1264    return MaybeHandle<Object>();
1265  }
1266
1267  return Execution::Call(isolate, getter, receiver, 0, NULL);
1268}
1269
1270
1271Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
1272                                                 Handle<JSReceiver> setter,
1273                                                 Handle<Object> value,
1274                                                 ShouldThrow should_throw) {
1275  Isolate* isolate = setter->GetIsolate();
1276
1277  Handle<Object> argv[] = { value };
1278  RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1279                                                     arraysize(argv), argv),
1280                            Nothing<bool>());
1281  return Just(true);
1282}
1283
1284
1285// static
1286bool Object::IsErrorObject(Isolate* isolate, Handle<Object> object) {
1287  if (!object->IsJSObject()) return false;
1288  // Use stack_trace_symbol as proxy for [[ErrorData]].
1289  Handle<Name> symbol = isolate->factory()->stack_trace_symbol();
1290  Maybe<bool> has_stack_trace =
1291      JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol);
1292  DCHECK(!has_stack_trace.IsNothing());
1293  return has_stack_trace.FromJust();
1294}
1295
1296
1297// static
1298bool JSObject::AllCanRead(LookupIterator* it) {
1299  // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
1300  // which have already been checked.
1301  DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
1302         it->state() == LookupIterator::INTERCEPTOR);
1303  for (it->Next(); it->IsFound(); it->Next()) {
1304    if (it->state() == LookupIterator::ACCESSOR) {
1305      auto accessors = it->GetAccessors();
1306      if (accessors->IsAccessorInfo()) {
1307        if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
1308      }
1309    } else if (it->state() == LookupIterator::INTERCEPTOR) {
1310      if (it->GetInterceptor()->all_can_read()) return true;
1311    } else if (it->state() == LookupIterator::JSPROXY) {
1312      // Stop lookupiterating. And no, AllCanNotRead.
1313      return false;
1314    }
1315  }
1316  return false;
1317}
1318
1319
1320MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
1321    LookupIterator* it) {
1322  Handle<JSObject> checked = it->GetHolder<JSObject>();
1323  while (AllCanRead(it)) {
1324    if (it->state() == LookupIterator::ACCESSOR) {
1325      return GetPropertyWithAccessor(it, SLOPPY);
1326    }
1327    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
1328    bool done;
1329    Handle<Object> result;
1330    ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result,
1331                               GetPropertyWithInterceptor(it, &done), Object);
1332    if (done) return result;
1333  }
1334
1335  // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
1336  // undefined.
1337  Handle<Name> name = it->GetName();
1338  if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
1339    return it->factory()->undefined_value();
1340  }
1341
1342  it->isolate()->ReportFailedAccessCheck(checked);
1343  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
1344  return it->factory()->undefined_value();
1345}
1346
1347
1348Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
1349    LookupIterator* it) {
1350  Handle<JSObject> checked = it->GetHolder<JSObject>();
1351  while (AllCanRead(it)) {
1352    if (it->state() == LookupIterator::ACCESSOR) {
1353      return Just(it->property_details().attributes());
1354    }
1355    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
1356    auto result = GetPropertyAttributesWithInterceptor(it);
1357    if (it->isolate()->has_scheduled_exception()) break;
1358    if (result.IsJust() && result.FromJust() != ABSENT) return result;
1359  }
1360  it->isolate()->ReportFailedAccessCheck(checked);
1361  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
1362                                      Nothing<PropertyAttributes>());
1363  return Just(ABSENT);
1364}
1365
1366
1367// static
1368bool JSObject::AllCanWrite(LookupIterator* it) {
1369  for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
1370    if (it->state() == LookupIterator::ACCESSOR) {
1371      Handle<Object> accessors = it->GetAccessors();
1372      if (accessors->IsAccessorInfo()) {
1373        if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
1374      }
1375    }
1376  }
1377  return false;
1378}
1379
1380
1381Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
1382    LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
1383  Handle<JSObject> checked = it->GetHolder<JSObject>();
1384  if (AllCanWrite(it)) {
1385    return SetPropertyWithAccessor(it, value, should_throw);
1386  }
1387
1388  it->isolate()->ReportFailedAccessCheck(checked);
1389  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
1390  return Just(true);
1391}
1392
1393
1394void JSObject::SetNormalizedProperty(Handle<JSObject> object,
1395                                     Handle<Name> name,
1396                                     Handle<Object> value,
1397                                     PropertyDetails details) {
1398  DCHECK(!object->HasFastProperties());
1399  if (!name->IsUniqueName()) {
1400    name = object->GetIsolate()->factory()->InternalizeString(
1401        Handle<String>::cast(name));
1402  }
1403
1404  if (object->IsJSGlobalObject()) {
1405    Handle<GlobalDictionary> property_dictionary(object->global_dictionary());
1406
1407    int entry = property_dictionary->FindEntry(name);
1408    if (entry == GlobalDictionary::kNotFound) {
1409      auto cell = object->GetIsolate()->factory()->NewPropertyCell();
1410      cell->set_value(*value);
1411      auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
1412                                            : PropertyCellType::kConstant;
1413      details = details.set_cell_type(cell_type);
1414      value = cell;
1415      property_dictionary =
1416          GlobalDictionary::Add(property_dictionary, name, value, details);
1417      object->set_properties(*property_dictionary);
1418    } else {
1419      PropertyCell::UpdateCell(property_dictionary, entry, value, details);
1420    }
1421  } else {
1422    Handle<NameDictionary> property_dictionary(object->property_dictionary());
1423
1424    int entry = property_dictionary->FindEntry(name);
1425    if (entry == NameDictionary::kNotFound) {
1426      property_dictionary =
1427          NameDictionary::Add(property_dictionary, name, value, details);
1428      object->set_properties(*property_dictionary);
1429    } else {
1430      PropertyDetails original_details = property_dictionary->DetailsAt(entry);
1431      int enumeration_index = original_details.dictionary_index();
1432      DCHECK(enumeration_index > 0);
1433      details = details.set_index(enumeration_index);
1434      property_dictionary->SetEntry(entry, name, value, details);
1435    }
1436  }
1437}
1438
1439
1440Maybe<bool> Object::HasInPrototypeChain(Isolate* isolate, Handle<Object> object,
1441                                        Handle<Object> proto) {
1442  PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
1443  while (true) {
1444    if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
1445    if (iter.IsAtEnd()) return Just(false);
1446    if (iter.IsAtEnd(proto)) return Just(true);
1447  }
1448}
1449
1450
1451Map* Object::GetRootMap(Isolate* isolate) {
1452  DisallowHeapAllocation no_alloc;
1453  if (IsSmi()) {
1454    Context* native_context = isolate->context()->native_context();
1455    return native_context->number_function()->initial_map();
1456  }
1457
1458  // The object is either a number, a string, a symbol, a boolean, a SIMD value,
1459  // a real JS object, or a Harmony proxy.
1460  HeapObject* heap_object = HeapObject::cast(this);
1461  if (heap_object->IsJSReceiver()) {
1462    return heap_object->map();
1463  }
1464  int constructor_function_index =
1465      heap_object->map()->GetConstructorFunctionIndex();
1466  if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
1467    Context* native_context = isolate->context()->native_context();
1468    JSFunction* constructor_function =
1469        JSFunction::cast(native_context->get(constructor_function_index));
1470    return constructor_function->initial_map();
1471  }
1472  return isolate->heap()->null_value()->map();
1473}
1474
1475
1476Object* Object::GetHash() {
1477  Object* hash = GetSimpleHash();
1478  if (hash->IsSmi()) return hash;
1479
1480  DCHECK(IsJSReceiver());
1481  return JSReceiver::cast(this)->GetIdentityHash();
1482}
1483
1484
1485Object* Object::GetSimpleHash() {
1486  // The object is either a Smi, a HeapNumber, a name, an odd-ball,
1487  // a SIMD value type, a real JS object, or a Harmony proxy.
1488  if (IsSmi()) {
1489    uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed);
1490    return Smi::FromInt(hash & Smi::kMaxValue);
1491  }
1492  if (IsHeapNumber()) {
1493    double num = HeapNumber::cast(this)->value();
1494    if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
1495    if (i::IsMinusZero(num)) num = 0;
1496    if (IsSmiDouble(num)) {
1497      return Smi::FromInt(FastD2I(num))->GetHash();
1498    }
1499    uint32_t hash = ComputeLongHash(double_to_uint64(num));
1500    return Smi::FromInt(hash & Smi::kMaxValue);
1501  }
1502  if (IsName()) {
1503    uint32_t hash = Name::cast(this)->Hash();
1504    return Smi::FromInt(hash);
1505  }
1506  if (IsOddball()) {
1507    uint32_t hash = Oddball::cast(this)->to_string()->Hash();
1508    return Smi::FromInt(hash);
1509  }
1510  if (IsSimd128Value()) {
1511    uint32_t hash = Simd128Value::cast(this)->Hash();
1512    return Smi::FromInt(hash & Smi::kMaxValue);
1513  }
1514  DCHECK(IsJSReceiver());
1515  JSReceiver* receiver = JSReceiver::cast(this);
1516  return receiver->GetHeap()->undefined_value();
1517}
1518
1519
1520Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
1521  Handle<Object> hash(object->GetSimpleHash(), isolate);
1522  if (hash->IsSmi()) return Handle<Smi>::cast(hash);
1523
1524  DCHECK(object->IsJSReceiver());
1525  return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
1526}
1527
1528
1529bool Object::SameValue(Object* other) {
1530  if (other == this) return true;
1531
1532  // The object is either a number, a name, an odd-ball,
1533  // a real JS object, or a Harmony proxy.
1534  if (IsNumber() && other->IsNumber()) {
1535    double this_value = Number();
1536    double other_value = other->Number();
1537    // SameValue(NaN, NaN) is true.
1538    if (this_value != other_value) {
1539      return std::isnan(this_value) && std::isnan(other_value);
1540    }
1541    // SameValue(0.0, -0.0) is false.
1542    return (std::signbit(this_value) == std::signbit(other_value));
1543  }
1544  if (IsString() && other->IsString()) {
1545    return String::cast(this)->Equals(String::cast(other));
1546  }
1547  if (IsSimd128Value() && other->IsSimd128Value()) {
1548    if (IsFloat32x4() && other->IsFloat32x4()) {
1549      Float32x4* a = Float32x4::cast(this);
1550      Float32x4* b = Float32x4::cast(other);
1551      for (int i = 0; i < 4; i++) {
1552        float x = a->get_lane(i);
1553        float y = b->get_lane(i);
1554        // Implements the ES5 SameValue operation for floating point types.
1555        // http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
1556        if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
1557        if (std::signbit(x) != std::signbit(y)) return false;
1558      }
1559      return true;
1560    } else {
1561      Simd128Value* a = Simd128Value::cast(this);
1562      Simd128Value* b = Simd128Value::cast(other);
1563      return a->map()->instance_type() == b->map()->instance_type() &&
1564             a->BitwiseEquals(b);
1565    }
1566  }
1567  return false;
1568}
1569
1570
1571bool Object::SameValueZero(Object* other) {
1572  if (other == this) return true;
1573
1574  // The object is either a number, a name, an odd-ball,
1575  // a real JS object, or a Harmony proxy.
1576  if (IsNumber() && other->IsNumber()) {
1577    double this_value = Number();
1578    double other_value = other->Number();
1579    // +0 == -0 is true
1580    return this_value == other_value ||
1581           (std::isnan(this_value) && std::isnan(other_value));
1582  }
1583  if (IsString() && other->IsString()) {
1584    return String::cast(this)->Equals(String::cast(other));
1585  }
1586  if (IsSimd128Value() && other->IsSimd128Value()) {
1587    if (IsFloat32x4() && other->IsFloat32x4()) {
1588      Float32x4* a = Float32x4::cast(this);
1589      Float32x4* b = Float32x4::cast(other);
1590      for (int i = 0; i < 4; i++) {
1591        float x = a->get_lane(i);
1592        float y = b->get_lane(i);
1593        // Implements the ES6 SameValueZero operation for floating point types.
1594        // http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
1595        if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
1596        // SameValueZero doesn't distinguish between 0 and -0.
1597      }
1598      return true;
1599    } else {
1600      Simd128Value* a = Simd128Value::cast(this);
1601      Simd128Value* b = Simd128Value::cast(other);
1602      return a->map()->instance_type() == b->map()->instance_type() &&
1603             a->BitwiseEquals(b);
1604    }
1605  }
1606  return false;
1607}
1608
1609
1610MaybeHandle<Object> Object::ArraySpeciesConstructor(
1611    Isolate* isolate, Handle<Object> original_array) {
1612  Handle<Context> native_context = isolate->native_context();
1613  if (!FLAG_harmony_species) {
1614    return Handle<Object>(native_context->array_function(), isolate);
1615  }
1616  Handle<Object> constructor = isolate->factory()->undefined_value();
1617  Maybe<bool> is_array = Object::IsArray(original_array);
1618  MAYBE_RETURN_NULL(is_array);
1619  if (is_array.FromJust()) {
1620    ASSIGN_RETURN_ON_EXCEPTION(
1621        isolate, constructor,
1622        Object::GetProperty(original_array,
1623                            isolate->factory()->constructor_string()),
1624        Object);
1625    if (constructor->IsConstructor()) {
1626      Handle<Context> constructor_context;
1627      ASSIGN_RETURN_ON_EXCEPTION(
1628          isolate, constructor_context,
1629          JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
1630          Object);
1631      if (*constructor_context != *native_context &&
1632          *constructor == constructor_context->array_function()) {
1633        constructor = isolate->factory()->undefined_value();
1634      }
1635    }
1636    if (constructor->IsJSReceiver()) {
1637      ASSIGN_RETURN_ON_EXCEPTION(
1638          isolate, constructor,
1639          Object::GetProperty(constructor,
1640                              isolate->factory()->species_symbol()),
1641          Object);
1642      if (constructor->IsNull()) {
1643        constructor = isolate->factory()->undefined_value();
1644      }
1645    }
1646  }
1647  if (constructor->IsUndefined()) {
1648    return Handle<Object>(native_context->array_function(), isolate);
1649  } else {
1650    if (!constructor->IsConstructor()) {
1651      THROW_NEW_ERROR(isolate,
1652          NewTypeError(MessageTemplate::kSpeciesNotConstructor),
1653          Object);
1654    }
1655    return constructor;
1656  }
1657}
1658
1659
1660void Object::ShortPrint(FILE* out) {
1661  OFStream os(out);
1662  os << Brief(this);
1663}
1664
1665
1666void Object::ShortPrint(StringStream* accumulator) {
1667  std::ostringstream os;
1668  os << Brief(this);
1669  accumulator->Add(os.str().c_str());
1670}
1671
1672
1673void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
1674
1675
1676std::ostream& operator<<(std::ostream& os, const Brief& v) {
1677  if (v.value->IsSmi()) {
1678    Smi::cast(v.value)->SmiPrint(os);
1679  } else {
1680    // TODO(svenpanne) Const-correct HeapObjectShortPrint!
1681    HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
1682    obj->HeapObjectShortPrint(os);
1683  }
1684  return os;
1685}
1686
1687
1688void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
1689  os << value();
1690}
1691
1692
1693// Should a word be prefixed by 'a' or 'an' in order to read naturally in
1694// English?  Returns false for non-ASCII or words that don't start with
1695// a capital letter.  The a/an rule follows pronunciation in English.
1696// We don't use the BBC's overcorrect "an historic occasion" though if
1697// you speak a dialect you may well say "an 'istoric occasion".
1698static bool AnWord(String* str) {
1699  if (str->length() == 0) return false;  // A nothing.
1700  int c0 = str->Get(0);
1701  int c1 = str->length() > 1 ? str->Get(1) : 0;
1702  if (c0 == 'U') {
1703    if (c1 > 'Z') {
1704      return true;  // An Umpire, but a UTF8String, a U.
1705    }
1706  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
1707    return true;    // An Ape, an ABCBook.
1708  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
1709           (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
1710            c0 == 'S' || c0 == 'X')) {
1711    return true;    // An MP3File, an M.
1712  }
1713  return false;
1714}
1715
1716
1717Handle<String> String::SlowFlatten(Handle<ConsString> cons,
1718                                   PretenureFlag pretenure) {
1719  DCHECK(AllowHeapAllocation::IsAllowed());
1720  DCHECK(cons->second()->length() != 0);
1721  Isolate* isolate = cons->GetIsolate();
1722  int length = cons->length();
1723  PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
1724                                                            : TENURED;
1725  Handle<SeqString> result;
1726  if (cons->IsOneByteRepresentation()) {
1727    Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
1728        length, tenure).ToHandleChecked();
1729    DisallowHeapAllocation no_gc;
1730    WriteToFlat(*cons, flat->GetChars(), 0, length);
1731    result = flat;
1732  } else {
1733    Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
1734        length, tenure).ToHandleChecked();
1735    DisallowHeapAllocation no_gc;
1736    WriteToFlat(*cons, flat->GetChars(), 0, length);
1737    result = flat;
1738  }
1739  cons->set_first(*result);
1740  cons->set_second(isolate->heap()->empty_string());
1741  DCHECK(result->IsFlat());
1742  return result;
1743}
1744
1745
1746
1747bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1748  // Externalizing twice leaks the external resource, so it's
1749  // prohibited by the API.
1750  DCHECK(!this->IsExternalString());
1751  DCHECK(!resource->IsCompressible());
1752#ifdef ENABLE_SLOW_DCHECKS
1753  if (FLAG_enable_slow_asserts) {
1754    // Assert that the resource and the string are equivalent.
1755    DCHECK(static_cast<size_t>(this->length()) == resource->length());
1756    ScopedVector<uc16> smart_chars(this->length());
1757    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1758    DCHECK(memcmp(smart_chars.start(),
1759                  resource->data(),
1760                  resource->length() * sizeof(smart_chars[0])) == 0);
1761  }
1762#endif  // DEBUG
1763  int size = this->Size();  // Byte size of the original string.
1764  // Abort if size does not allow in-place conversion.
1765  if (size < ExternalString::kShortSize) return false;
1766  Heap* heap = GetHeap();
1767  bool is_one_byte = this->IsOneByteRepresentation();
1768  bool is_internalized = this->IsInternalizedString();
1769
1770  // Morph the string to an external string by replacing the map and
1771  // reinitializing the fields.  This won't work if the space the existing
1772  // string occupies is too small for a regular  external string.
1773  // Instead, we resort to a short external string instead, omitting
1774  // the field caching the address of the backing store.  When we encounter
1775  // short external strings in generated code, we need to bailout to runtime.
1776  Map* new_map;
1777  if (size < ExternalString::kSize) {
1778    new_map = is_internalized
1779        ? (is_one_byte
1780           ? heap->short_external_internalized_string_with_one_byte_data_map()
1781           : heap->short_external_internalized_string_map())
1782        : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
1783                       : heap->short_external_string_map());
1784  } else {
1785    new_map = is_internalized
1786        ? (is_one_byte
1787           ? heap->external_internalized_string_with_one_byte_data_map()
1788           : heap->external_internalized_string_map())
1789        : (is_one_byte ? heap->external_string_with_one_byte_data_map()
1790                       : heap->external_string_map());
1791  }
1792
1793  // Byte size of the external String object.
1794  int new_size = this->SizeFromMap(new_map);
1795  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1796
1797  // We are storing the new map using release store after creating a filler for
1798  // the left-over space to avoid races with the sweeper thread.
1799  this->synchronized_set_map(new_map);
1800
1801  ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1802  self->set_resource(resource);
1803  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1804
1805  heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
1806  return true;
1807}
1808
1809
1810bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
1811  // Externalizing twice leaks the external resource, so it's
1812  // prohibited by the API.
1813  DCHECK(!this->IsExternalString());
1814  DCHECK(!resource->IsCompressible());
1815#ifdef ENABLE_SLOW_DCHECKS
1816  if (FLAG_enable_slow_asserts) {
1817    // Assert that the resource and the string are equivalent.
1818    DCHECK(static_cast<size_t>(this->length()) == resource->length());
1819    if (this->IsTwoByteRepresentation()) {
1820      ScopedVector<uint16_t> smart_chars(this->length());
1821      String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1822      DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
1823    }
1824    ScopedVector<char> smart_chars(this->length());
1825    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1826    DCHECK(memcmp(smart_chars.start(),
1827                  resource->data(),
1828                  resource->length() * sizeof(smart_chars[0])) == 0);
1829  }
1830#endif  // DEBUG
1831  int size = this->Size();  // Byte size of the original string.
1832  // Abort if size does not allow in-place conversion.
1833  if (size < ExternalString::kShortSize) return false;
1834  Heap* heap = GetHeap();
1835  bool is_internalized = this->IsInternalizedString();
1836
1837  // Morph the string to an external string by replacing the map and
1838  // reinitializing the fields.  This won't work if the space the existing
1839  // string occupies is too small for a regular  external string.
1840  // Instead, we resort to a short external string instead, omitting
1841  // the field caching the address of the backing store.  When we encounter
1842  // short external strings in generated code, we need to bailout to runtime.
1843  Map* new_map;
1844  if (size < ExternalString::kSize) {
1845    new_map = is_internalized
1846                  ? heap->short_external_one_byte_internalized_string_map()
1847                  : heap->short_external_one_byte_string_map();
1848  } else {
1849    new_map = is_internalized
1850                  ? heap->external_one_byte_internalized_string_map()
1851                  : heap->external_one_byte_string_map();
1852  }
1853
1854  // Byte size of the external String object.
1855  int new_size = this->SizeFromMap(new_map);
1856  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1857
1858  // We are storing the new map using release store after creating a filler for
1859  // the left-over space to avoid races with the sweeper thread.
1860  this->synchronized_set_map(new_map);
1861
1862  ExternalOneByteString* self = ExternalOneByteString::cast(this);
1863  self->set_resource(resource);
1864  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1865
1866  heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
1867  return true;
1868}
1869
1870
1871void String::StringShortPrint(StringStream* accumulator) {
1872  int len = length();
1873  if (len > kMaxShortPrintLength) {
1874    accumulator->Add("<Very long string[%u]>", len);
1875    return;
1876  }
1877
1878  if (!LooksValid()) {
1879    accumulator->Add("<Invalid String>");
1880    return;
1881  }
1882
1883  StringCharacterStream stream(this);
1884
1885  bool truncated = false;
1886  if (len > kMaxShortPrintLength) {
1887    len = kMaxShortPrintLength;
1888    truncated = true;
1889  }
1890  bool one_byte = true;
1891  for (int i = 0; i < len; i++) {
1892    uint16_t c = stream.GetNext();
1893
1894    if (c < 32 || c >= 127) {
1895      one_byte = false;
1896    }
1897  }
1898  stream.Reset(this);
1899  if (one_byte) {
1900    accumulator->Add("<String[%u]: ", length());
1901    for (int i = 0; i < len; i++) {
1902      accumulator->Put(static_cast<char>(stream.GetNext()));
1903    }
1904    accumulator->Put('>');
1905  } else {
1906    // Backslash indicates that the string contains control
1907    // characters and that backslashes are therefore escaped.
1908    accumulator->Add("<String[%u]\\: ", length());
1909    for (int i = 0; i < len; i++) {
1910      uint16_t c = stream.GetNext();
1911      if (c == '\n') {
1912        accumulator->Add("\\n");
1913      } else if (c == '\r') {
1914        accumulator->Add("\\r");
1915      } else if (c == '\\') {
1916        accumulator->Add("\\\\");
1917      } else if (c < 32 || c > 126) {
1918        accumulator->Add("\\x%02x", c);
1919      } else {
1920        accumulator->Put(static_cast<char>(c));
1921      }
1922    }
1923    if (truncated) {
1924      accumulator->Put('.');
1925      accumulator->Put('.');
1926      accumulator->Put('.');
1927    }
1928    accumulator->Put('>');
1929  }
1930  return;
1931}
1932
1933
1934void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
1935  if (end < 0) end = length();
1936  StringCharacterStream stream(this, start);
1937  for (int i = start; i < end && stream.HasMore(); i++) {
1938    os << AsUC16(stream.GetNext());
1939  }
1940}
1941
1942
1943void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1944  switch (map()->instance_type()) {
1945    case JS_ARRAY_TYPE: {
1946      double length = JSArray::cast(this)->length()->IsUndefined()
1947          ? 0
1948          : JSArray::cast(this)->length()->Number();
1949      accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1950      break;
1951    }
1952    case JS_BOUND_FUNCTION_TYPE: {
1953      JSBoundFunction* bound_function = JSBoundFunction::cast(this);
1954      Object* name = bound_function->name();
1955      accumulator->Add("<JS BoundFunction");
1956      if (name->IsString()) {
1957        String* str = String::cast(name);
1958        if (str->length() > 0) {
1959          accumulator->Add(" ");
1960          accumulator->Put(str);
1961        }
1962      }
1963      accumulator->Add(
1964          " (BoundTargetFunction %p)>",
1965          reinterpret_cast<void*>(bound_function->bound_target_function()));
1966      break;
1967    }
1968    case JS_WEAK_MAP_TYPE: {
1969      accumulator->Add("<JS WeakMap>");
1970      break;
1971    }
1972    case JS_WEAK_SET_TYPE: {
1973      accumulator->Add("<JS WeakSet>");
1974      break;
1975    }
1976    case JS_REGEXP_TYPE: {
1977      accumulator->Add("<JS RegExp>");
1978      break;
1979    }
1980    case JS_FUNCTION_TYPE: {
1981      JSFunction* function = JSFunction::cast(this);
1982      Object* fun_name = function->shared()->DebugName();
1983      bool printed = false;
1984      if (fun_name->IsString()) {
1985        String* str = String::cast(fun_name);
1986        if (str->length() > 0) {
1987          accumulator->Add("<JS Function ");
1988          accumulator->Put(str);
1989          printed = true;
1990        }
1991      }
1992      if (!printed) {
1993        accumulator->Add("<JS Function");
1994      }
1995      accumulator->Add(" (SharedFunctionInfo %p)",
1996                       reinterpret_cast<void*>(function->shared()));
1997      accumulator->Put('>');
1998      break;
1999    }
2000    case JS_GENERATOR_OBJECT_TYPE: {
2001      accumulator->Add("<JS Generator>");
2002      break;
2003    }
2004    case JS_MODULE_TYPE: {
2005      accumulator->Add("<JS Module>");
2006      break;
2007    }
2008    // All other JSObjects are rather similar to each other (JSObject,
2009    // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
2010    default: {
2011      Map* map_of_this = map();
2012      Heap* heap = GetHeap();
2013      Object* constructor = map_of_this->GetConstructor();
2014      bool printed = false;
2015      if (constructor->IsHeapObject() &&
2016          !heap->Contains(HeapObject::cast(constructor))) {
2017        accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
2018      } else {
2019        bool global_object = IsJSGlobalProxy();
2020        if (constructor->IsJSFunction()) {
2021          if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
2022            accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
2023          } else {
2024            Object* constructor_name =
2025                JSFunction::cast(constructor)->shared()->name();
2026            if (constructor_name->IsString()) {
2027              String* str = String::cast(constructor_name);
2028              if (str->length() > 0) {
2029                bool vowel = AnWord(str);
2030                accumulator->Add("<%sa%s ",
2031                       global_object ? "Global Object: " : "",
2032                       vowel ? "n" : "");
2033                accumulator->Put(str);
2034                accumulator->Add(" with %smap %p",
2035                    map_of_this->is_deprecated() ? "deprecated " : "",
2036                    map_of_this);
2037                printed = true;
2038              }
2039            }
2040          }
2041        }
2042        if (!printed) {
2043          accumulator->Add("<JS %sObject", global_object ? "Global " : "");
2044        }
2045      }
2046      if (IsJSValue()) {
2047        accumulator->Add(" value = ");
2048        JSValue::cast(this)->value()->ShortPrint(accumulator);
2049      }
2050      accumulator->Put('>');
2051      break;
2052    }
2053  }
2054}
2055
2056
2057void JSObject::PrintElementsTransition(
2058    FILE* file, Handle<JSObject> object,
2059    ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
2060    ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
2061  if (from_kind != to_kind) {
2062    OFStream os(file);
2063    os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
2064       << ElementsKindToString(to_kind) << "] in ";
2065    JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
2066    PrintF(file, " for ");
2067    object->ShortPrint(file);
2068    PrintF(file, " from ");
2069    from_elements->ShortPrint(file);
2070    PrintF(file, " to ");
2071    to_elements->ShortPrint(file);
2072    PrintF(file, "\n");
2073  }
2074}
2075
2076
2077// static
2078MaybeHandle<JSFunction> Map::GetConstructorFunction(
2079    Handle<Map> map, Handle<Context> native_context) {
2080  if (map->IsPrimitiveMap()) {
2081    int const constructor_function_index = map->GetConstructorFunctionIndex();
2082    if (constructor_function_index != kNoConstructorFunctionIndex) {
2083      return handle(
2084          JSFunction::cast(native_context->get(constructor_function_index)));
2085    }
2086  }
2087  return MaybeHandle<JSFunction>();
2088}
2089
2090
2091void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
2092                               PropertyAttributes attributes) {
2093  OFStream os(file);
2094  os << "[reconfiguring]";
2095  Name* name = instance_descriptors()->GetKey(modify_index);
2096  if (name->IsString()) {
2097    String::cast(name)->PrintOn(file);
2098  } else {
2099    os << "{symbol " << static_cast<void*>(name) << "}";
2100  }
2101  os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
2102  os << attributes << " [";
2103  JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
2104  os << "]\n";
2105}
2106
2107
2108void Map::PrintGeneralization(FILE* file,
2109                              const char* reason,
2110                              int modify_index,
2111                              int split,
2112                              int descriptors,
2113                              bool constant_to_field,
2114                              Representation old_representation,
2115                              Representation new_representation,
2116                              HeapType* old_field_type,
2117                              HeapType* new_field_type) {
2118  OFStream os(file);
2119  os << "[generalizing]";
2120  Name* name = instance_descriptors()->GetKey(modify_index);
2121  if (name->IsString()) {
2122    String::cast(name)->PrintOn(file);
2123  } else {
2124    os << "{symbol " << static_cast<void*>(name) << "}";
2125  }
2126  os << ":";
2127  if (constant_to_field) {
2128    os << "c";
2129  } else {
2130    os << old_representation.Mnemonic() << "{";
2131    old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
2132    os << "}";
2133  }
2134  os << "->" << new_representation.Mnemonic() << "{";
2135  new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
2136  os << "} (";
2137  if (strlen(reason) > 0) {
2138    os << reason;
2139  } else {
2140    os << "+" << (descriptors - split) << " maps";
2141  }
2142  os << ") [";
2143  JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
2144  os << "]\n";
2145}
2146
2147
2148void JSObject::PrintInstanceMigration(FILE* file,
2149                                      Map* original_map,
2150                                      Map* new_map) {
2151  PrintF(file, "[migrating]");
2152  DescriptorArray* o = original_map->instance_descriptors();
2153  DescriptorArray* n = new_map->instance_descriptors();
2154  for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
2155    Representation o_r = o->GetDetails(i).representation();
2156    Representation n_r = n->GetDetails(i).representation();
2157    if (!o_r.Equals(n_r)) {
2158      String::cast(o->GetKey(i))->PrintOn(file);
2159      PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
2160    } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
2161               n->GetDetails(i).type() == DATA) {
2162      Name* name = o->GetKey(i);
2163      if (name->IsString()) {
2164        String::cast(name)->PrintOn(file);
2165      } else {
2166        PrintF(file, "{symbol %p}", static_cast<void*>(name));
2167      }
2168      PrintF(file, " ");
2169    }
2170  }
2171  PrintF(file, "\n");
2172}
2173
2174
2175void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
2176  Heap* heap = GetHeap();
2177  if (!heap->Contains(this)) {
2178    os << "!!!INVALID POINTER!!!";
2179    return;
2180  }
2181  if (!heap->Contains(map())) {
2182    os << "!!!INVALID MAP!!!";
2183    return;
2184  }
2185
2186  os << this << " ";
2187
2188  if (IsString()) {
2189    HeapStringAllocator allocator;
2190    StringStream accumulator(&allocator);
2191    String::cast(this)->StringShortPrint(&accumulator);
2192    os << accumulator.ToCString().get();
2193    return;
2194  }
2195  if (IsJSObject()) {
2196    HeapStringAllocator allocator;
2197    StringStream accumulator(&allocator);
2198    JSObject::cast(this)->JSObjectShortPrint(&accumulator);
2199    os << accumulator.ToCString().get();
2200    return;
2201  }
2202  switch (map()->instance_type()) {
2203    case MAP_TYPE:
2204      os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
2205         << ")>";
2206      break;
2207    case FIXED_ARRAY_TYPE:
2208      os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
2209      break;
2210    case FIXED_DOUBLE_ARRAY_TYPE:
2211      os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
2212         << "]>";
2213      break;
2214    case BYTE_ARRAY_TYPE:
2215      os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
2216      break;
2217    case BYTECODE_ARRAY_TYPE:
2218      os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
2219      break;
2220    case TRANSITION_ARRAY_TYPE:
2221      os << "<TransitionArray[" << TransitionArray::cast(this)->length()
2222         << "]>";
2223      break;
2224    case FREE_SPACE_TYPE:
2225      os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
2226      break;
2227#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
2228  case FIXED_##TYPE##_ARRAY_TYPE:                                             \
2229    os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
2230       << "]>";                                                               \
2231    break;
2232
2233    TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
2234#undef TYPED_ARRAY_SHORT_PRINT
2235
2236    case SHARED_FUNCTION_INFO_TYPE: {
2237      SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
2238      base::SmartArrayPointer<char> debug_name =
2239          shared->DebugName()->ToCString();
2240      if (debug_name[0] != 0) {
2241        os << "<SharedFunctionInfo " << debug_name.get() << ">";
2242      } else {
2243        os << "<SharedFunctionInfo>";
2244      }
2245      break;
2246    }
2247    case JS_MESSAGE_OBJECT_TYPE:
2248      os << "<JSMessageObject>";
2249      break;
2250#define MAKE_STRUCT_CASE(NAME, Name, name) \
2251  case NAME##_TYPE:                        \
2252    os << "<" #Name ">";                   \
2253    break;
2254  STRUCT_LIST(MAKE_STRUCT_CASE)
2255#undef MAKE_STRUCT_CASE
2256    case CODE_TYPE: {
2257      Code* code = Code::cast(this);
2258      os << "<Code: " << Code::Kind2String(code->kind()) << ">";
2259      break;
2260    }
2261    case ODDBALL_TYPE: {
2262      if (IsUndefined()) {
2263        os << "<undefined>";
2264      } else if (IsTheHole()) {
2265        os << "<the hole>";
2266      } else if (IsNull()) {
2267        os << "<null>";
2268      } else if (IsTrue()) {
2269        os << "<true>";
2270      } else if (IsFalse()) {
2271        os << "<false>";
2272      } else {
2273        os << "<Odd Oddball>";
2274      }
2275      break;
2276    }
2277    case SYMBOL_TYPE: {
2278      Symbol* symbol = Symbol::cast(this);
2279      symbol->SymbolShortPrint(os);
2280      break;
2281    }
2282    case HEAP_NUMBER_TYPE: {
2283      os << "<Number: ";
2284      HeapNumber::cast(this)->HeapNumberPrint(os);
2285      os << ">";
2286      break;
2287    }
2288    case MUTABLE_HEAP_NUMBER_TYPE: {
2289      os << "<MutableNumber: ";
2290      HeapNumber::cast(this)->HeapNumberPrint(os);
2291      os << '>';
2292      break;
2293    }
2294    case SIMD128_VALUE_TYPE: {
2295#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
2296  if (Is##Type()) {                                           \
2297    os << "<" #Type ">";                                      \
2298    break;                                                    \
2299  }
2300      SIMD128_TYPES(SIMD128_TYPE)
2301#undef SIMD128_TYPE
2302      UNREACHABLE();
2303      break;
2304    }
2305    case JS_PROXY_TYPE:
2306      os << "<JSProxy>";
2307      break;
2308    case FOREIGN_TYPE:
2309      os << "<Foreign>";
2310      break;
2311    case CELL_TYPE: {
2312      os << "Cell for ";
2313      HeapStringAllocator allocator;
2314      StringStream accumulator(&allocator);
2315      Cell::cast(this)->value()->ShortPrint(&accumulator);
2316      os << accumulator.ToCString().get();
2317      break;
2318    }
2319    case PROPERTY_CELL_TYPE: {
2320      os << "PropertyCell for ";
2321      HeapStringAllocator allocator;
2322      StringStream accumulator(&allocator);
2323      PropertyCell* cell = PropertyCell::cast(this);
2324      cell->value()->ShortPrint(&accumulator);
2325      os << accumulator.ToCString().get();
2326      break;
2327    }
2328    case WEAK_CELL_TYPE: {
2329      os << "WeakCell for ";
2330      HeapStringAllocator allocator;
2331      StringStream accumulator(&allocator);
2332      WeakCell::cast(this)->value()->ShortPrint(&accumulator);
2333      os << accumulator.ToCString().get();
2334      break;
2335    }
2336    default:
2337      os << "<Other heap object (" << map()->instance_type() << ")>";
2338      break;
2339  }
2340}
2341
2342
2343void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
2344
2345
2346void HeapObject::IterateBody(ObjectVisitor* v) {
2347  Map* m = map();
2348  IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
2349}
2350
2351
2352void HeapObject::IterateBody(InstanceType type, int object_size,
2353                             ObjectVisitor* v) {
2354  IterateBodyFast<ObjectVisitor>(type, object_size, v);
2355}
2356
2357
2358struct CallIsValidSlot {
2359  template <typename BodyDescriptor>
2360  static bool apply(HeapObject* obj, int offset, int) {
2361    return BodyDescriptor::IsValidSlot(obj, offset);
2362  }
2363};
2364
2365
2366bool HeapObject::IsValidSlot(int offset) {
2367  DCHECK_NE(0, offset);
2368  return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
2369                                                    this, offset, 0);
2370}
2371
2372
2373bool HeapNumber::HeapNumberBooleanValue() {
2374  return DoubleToBoolean(value());
2375}
2376
2377
2378void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
2379  os << value();
2380}
2381
2382
2383#define FIELD_ADDR_CONST(p, offset) \
2384  (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
2385
2386#define READ_INT32_FIELD(p, offset) \
2387  (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
2388
2389#define READ_INT64_FIELD(p, offset) \
2390  (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
2391
2392#define READ_BYTE_FIELD(p, offset) \
2393  (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
2394
2395
2396// static
2397Handle<String> Simd128Value::ToString(Handle<Simd128Value> input) {
2398#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
2399  if (input->Is##Type()) return Type::ToString(Handle<Type>::cast(input));
2400  SIMD128_TYPES(SIMD128_TYPE)
2401#undef SIMD128_TYPE
2402  UNREACHABLE();
2403  return Handle<String>::null();
2404}
2405
2406
2407// static
2408Handle<String> Float32x4::ToString(Handle<Float32x4> input) {
2409  Isolate* const isolate = input->GetIsolate();
2410  char arr[100];
2411  Vector<char> buffer(arr, arraysize(arr));
2412  std::ostringstream os;
2413  os << "SIMD.Float32x4("
2414     << std::string(DoubleToCString(input->get_lane(0), buffer)) << ", "
2415     << std::string(DoubleToCString(input->get_lane(1), buffer)) << ", "
2416     << std::string(DoubleToCString(input->get_lane(2), buffer)) << ", "
2417     << std::string(DoubleToCString(input->get_lane(3), buffer)) << ")";
2418  return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str());
2419}
2420
2421
2422#define SIMD128_BOOL_TO_STRING(Type, lane_count)                            \
2423  Handle<String> Type::ToString(Handle<Type> input) {                       \
2424    Isolate* const isolate = input->GetIsolate();                           \
2425    std::ostringstream os;                                                  \
2426    os << "SIMD." #Type "(";                                                \
2427    os << (input->get_lane(0) ? "true" : "false");                          \
2428    for (int i = 1; i < lane_count; i++) {                                  \
2429      os << ", " << (input->get_lane(i) ? "true" : "false");                \
2430    }                                                                       \
2431    os << ")";                                                              \
2432    return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
2433  }
2434SIMD128_BOOL_TO_STRING(Bool32x4, 4)
2435SIMD128_BOOL_TO_STRING(Bool16x8, 8)
2436SIMD128_BOOL_TO_STRING(Bool8x16, 16)
2437#undef SIMD128_BOOL_TO_STRING
2438
2439
2440#define SIMD128_INT_TO_STRING(Type, lane_count)                             \
2441  Handle<String> Type::ToString(Handle<Type> input) {                       \
2442    Isolate* const isolate = input->GetIsolate();                           \
2443    char arr[100];                                                          \
2444    Vector<char> buffer(arr, arraysize(arr));                               \
2445    std::ostringstream os;                                                  \
2446    os << "SIMD." #Type "(";                                                \
2447    os << IntToCString(input->get_lane(0), buffer);                         \
2448    for (int i = 1; i < lane_count; i++) {                                  \
2449      os << ", " << IntToCString(input->get_lane(i), buffer);               \
2450    }                                                                       \
2451    os << ")";                                                              \
2452    return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
2453  }
2454SIMD128_INT_TO_STRING(Int32x4, 4)
2455SIMD128_INT_TO_STRING(Uint32x4, 4)
2456SIMD128_INT_TO_STRING(Int16x8, 8)
2457SIMD128_INT_TO_STRING(Uint16x8, 8)
2458SIMD128_INT_TO_STRING(Int8x16, 16)
2459SIMD128_INT_TO_STRING(Uint8x16, 16)
2460#undef SIMD128_INT_TO_STRING
2461
2462
2463bool Simd128Value::BitwiseEquals(const Simd128Value* other) const {
2464  return READ_INT64_FIELD(this, kValueOffset) ==
2465             READ_INT64_FIELD(other, kValueOffset) &&
2466         READ_INT64_FIELD(this, kValueOffset + kInt64Size) ==
2467             READ_INT64_FIELD(other, kValueOffset + kInt64Size);
2468}
2469
2470
2471uint32_t Simd128Value::Hash() const {
2472  uint32_t seed = v8::internal::kZeroHashSeed;
2473  uint32_t hash;
2474  hash = ComputeIntegerHash(READ_INT32_FIELD(this, kValueOffset), seed);
2475  hash = ComputeIntegerHash(
2476      READ_INT32_FIELD(this, kValueOffset + 1 * kInt32Size), hash * 31);
2477  hash = ComputeIntegerHash(
2478      READ_INT32_FIELD(this, kValueOffset + 2 * kInt32Size), hash * 31);
2479  hash = ComputeIntegerHash(
2480      READ_INT32_FIELD(this, kValueOffset + 3 * kInt32Size), hash * 31);
2481  return hash;
2482}
2483
2484
2485void Simd128Value::CopyBits(void* destination) const {
2486  memcpy(destination, &READ_BYTE_FIELD(this, kValueOffset), kSimd128Size);
2487}
2488
2489
2490String* JSReceiver::class_name() {
2491  if (IsFunction()) {
2492    return GetHeap()->Function_string();
2493  }
2494  Object* maybe_constructor = map()->GetConstructor();
2495  if (maybe_constructor->IsJSFunction()) {
2496    JSFunction* constructor = JSFunction::cast(maybe_constructor);
2497    return String::cast(constructor->shared()->instance_class_name());
2498  }
2499  // If the constructor is not present, return "Object".
2500  return GetHeap()->Object_string();
2501}
2502
2503
2504MaybeHandle<String> JSReceiver::BuiltinStringTag(Handle<JSReceiver> object) {
2505  Maybe<bool> is_array = Object::IsArray(object);
2506  MAYBE_RETURN(is_array, MaybeHandle<String>());
2507  Isolate* const isolate = object->GetIsolate();
2508  if (is_array.FromJust()) {
2509    return isolate->factory()->Array_string();
2510  }
2511  // TODO(adamk): According to ES2015, we should return "Function" when
2512  // object has a [[Call]] internal method (corresponds to IsCallable).
2513  // But this is well cemented in layout tests and might cause webbreakage.
2514  // if (object->IsCallable()) {
2515  //   return isolate->factory()->Function_string();
2516  // }
2517  // TODO(adamk): class_name() is expensive, replace with instance type
2518  // checks where possible.
2519  return handle(object->class_name(), isolate);
2520}
2521
2522
2523// static
2524Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
2525  Isolate* isolate = receiver->GetIsolate();
2526
2527  // If the object was instantiated simply with base == new.target, the
2528  // constructor on the map provides the most accurate name.
2529  // Don't provide the info for prototypes, since their constructors are
2530  // reclaimed and replaced by Object in OptimizeAsPrototype.
2531  if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
2532      !receiver->map()->is_prototype_map()) {
2533    Object* maybe_constructor = receiver->map()->GetConstructor();
2534    if (maybe_constructor->IsJSFunction()) {
2535      JSFunction* constructor = JSFunction::cast(maybe_constructor);
2536      String* name = String::cast(constructor->shared()->name());
2537      if (name->length() == 0) name = constructor->shared()->inferred_name();
2538      if (name->length() != 0 &&
2539          !name->Equals(isolate->heap()->Object_string())) {
2540        return handle(name, isolate);
2541      }
2542    }
2543  }
2544
2545  if (FLAG_harmony_tostring) {
2546    Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
2547        receiver, isolate->factory()->to_string_tag_symbol());
2548    if (maybe_tag->IsString()) return Handle<String>::cast(maybe_tag);
2549  }
2550
2551  PrototypeIterator iter(isolate, receiver);
2552  if (iter.IsAtEnd()) return handle(receiver->class_name());
2553  Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
2554  LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
2555                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
2556  Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
2557  Handle<String> result = isolate->factory()->Object_string();
2558  if (maybe_constructor->IsJSFunction()) {
2559    JSFunction* constructor = JSFunction::cast(*maybe_constructor);
2560    String* name = String::cast(constructor->shared()->name());
2561    if (name->length() == 0) name = constructor->shared()->inferred_name();
2562    if (name->length() > 0) result = handle(name, isolate);
2563  }
2564
2565  return result.is_identical_to(isolate->factory()->Object_string())
2566             ? handle(receiver->class_name())
2567             : result;
2568}
2569
2570
2571Context* JSReceiver::GetCreationContext() {
2572  if (IsJSBoundFunction()) {
2573    return JSBoundFunction::cast(this)->creation_context();
2574  }
2575  Object* constructor = map()->GetConstructor();
2576  JSFunction* function;
2577  if (constructor->IsJSFunction()) {
2578    function = JSFunction::cast(constructor);
2579  } else {
2580    // Functions have null as a constructor,
2581    // but any JSFunction knows its context immediately.
2582    CHECK(IsJSFunction());
2583    function = JSFunction::cast(this);
2584  }
2585
2586  return function->context()->native_context();
2587}
2588
2589
2590static Handle<Object> WrapType(Handle<HeapType> type) {
2591  if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
2592  return type;
2593}
2594
2595
2596MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
2597                                    Handle<Name> name,
2598                                    Handle<HeapType> type,
2599                                    PropertyAttributes attributes,
2600                                    Representation representation,
2601                                    TransitionFlag flag) {
2602  DCHECK(DescriptorArray::kNotFound ==
2603         map->instance_descriptors()->Search(
2604             *name, map->NumberOfOwnDescriptors()));
2605
2606  // Ensure the descriptor array does not get too big.
2607  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
2608    return MaybeHandle<Map>();
2609  }
2610
2611  Isolate* isolate = map->GetIsolate();
2612
2613  // Compute the new index for new field.
2614  int index = map->NextFreePropertyIndex();
2615
2616  if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
2617    representation = Representation::Tagged();
2618    type = HeapType::Any(isolate);
2619  }
2620
2621  Handle<Object> wrapped_type(WrapType(type));
2622
2623  DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
2624                                representation);
2625  Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
2626  int unused_property_fields = new_map->unused_property_fields() - 1;
2627  if (unused_property_fields < 0) {
2628    unused_property_fields += JSObject::kFieldsAdded;
2629  }
2630  new_map->set_unused_property_fields(unused_property_fields);
2631  return new_map;
2632}
2633
2634
2635MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
2636                                       Handle<Name> name,
2637                                       Handle<Object> constant,
2638                                       PropertyAttributes attributes,
2639                                       TransitionFlag flag) {
2640  // Ensure the descriptor array does not get too big.
2641  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
2642    return MaybeHandle<Map>();
2643  }
2644
2645  // Allocate new instance descriptors with (name, constant) added.
2646  DataConstantDescriptor new_constant_desc(name, constant, attributes);
2647  return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
2648}
2649
2650
2651void JSObject::AddSlowProperty(Handle<JSObject> object,
2652                               Handle<Name> name,
2653                               Handle<Object> value,
2654                               PropertyAttributes attributes) {
2655  DCHECK(!object->HasFastProperties());
2656  Isolate* isolate = object->GetIsolate();
2657  if (object->IsJSGlobalObject()) {
2658    Handle<GlobalDictionary> dict(object->global_dictionary());
2659    PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
2660    int entry = dict->FindEntry(name);
2661    // If there's a cell there, just invalidate and set the property.
2662    if (entry != GlobalDictionary::kNotFound) {
2663      PropertyCell::UpdateCell(dict, entry, value, details);
2664      // TODO(ishell): move this to UpdateCell.
2665      // Need to adjust the details.
2666      int index = dict->NextEnumerationIndex();
2667      dict->SetNextEnumerationIndex(index + 1);
2668      PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
2669      details = cell->property_details().set_index(index);
2670      cell->set_property_details(details);
2671
2672    } else {
2673      auto cell = isolate->factory()->NewPropertyCell();
2674      cell->set_value(*value);
2675      auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
2676                                            : PropertyCellType::kConstant;
2677      details = details.set_cell_type(cell_type);
2678      value = cell;
2679
2680      Handle<GlobalDictionary> result =
2681          GlobalDictionary::Add(dict, name, value, details);
2682      if (*dict != *result) object->set_properties(*result);
2683    }
2684  } else {
2685    Handle<NameDictionary> dict(object->property_dictionary());
2686    PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
2687    Handle<NameDictionary> result =
2688        NameDictionary::Add(dict, name, value, details);
2689    if (*dict != *result) object->set_properties(*result);
2690  }
2691}
2692
2693
2694MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2695                                                  const char* type_str,
2696                                                  Handle<Name> name,
2697                                                  Handle<Object> old_value) {
2698  DCHECK(!object->IsJSGlobalProxy());
2699  DCHECK(!object->IsJSGlobalObject());
2700  Isolate* isolate = object->GetIsolate();
2701  HandleScope scope(isolate);
2702  Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2703  Handle<Object> args[] = { type, object, name, old_value };
2704  int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2705
2706  return Execution::Call(isolate,
2707                         Handle<JSFunction>(isolate->observers_notify_change()),
2708                         isolate->factory()->undefined_value(), argc, args);
2709}
2710
2711
2712const char* Representation::Mnemonic() const {
2713  switch (kind_) {
2714    case kNone: return "v";
2715    case kTagged: return "t";
2716    case kSmi: return "s";
2717    case kDouble: return "d";
2718    case kInteger32: return "i";
2719    case kHeapObject: return "h";
2720    case kExternal: return "x";
2721    default:
2722      UNREACHABLE();
2723      return NULL;
2724  }
2725}
2726
2727
2728bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
2729                                 int target_inobject, int target_unused,
2730                                 int* old_number_of_fields) {
2731  // If fields were added (or removed), rewrite the instance.
2732  *old_number_of_fields = NumberOfFields();
2733  DCHECK(target_number_of_fields >= *old_number_of_fields);
2734  if (target_number_of_fields != *old_number_of_fields) return true;
2735
2736  // If smi descriptors were replaced by double descriptors, rewrite.
2737  DescriptorArray* old_desc = instance_descriptors();
2738  DescriptorArray* new_desc = target->instance_descriptors();
2739  int limit = NumberOfOwnDescriptors();
2740  for (int i = 0; i < limit; i++) {
2741    if (new_desc->GetDetails(i).representation().IsDouble() !=
2742        old_desc->GetDetails(i).representation().IsDouble()) {
2743      return true;
2744    }
2745  }
2746
2747  // If no fields were added, and no inobject properties were removed, setting
2748  // the map is sufficient.
2749  if (target_inobject == GetInObjectProperties()) return false;
2750  // In-object slack tracking may have reduced the object size of the new map.
2751  // In that case, succeed if all existing fields were inobject, and they still
2752  // fit within the new inobject size.
2753  DCHECK(target_inobject < GetInObjectProperties());
2754  if (target_number_of_fields <= target_inobject) {
2755    DCHECK(target_number_of_fields + target_unused == target_inobject);
2756    return false;
2757  }
2758  // Otherwise, properties will need to be moved to the backing store.
2759  return true;
2760}
2761
2762
2763// static
2764void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
2765                                               Handle<Map> new_map,
2766                                               Isolate* isolate) {
2767  if (!FLAG_track_prototype_users) return;
2768  if (!old_map->is_prototype_map()) return;
2769  DCHECK(new_map->is_prototype_map());
2770  bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
2771  new_map->set_prototype_info(old_map->prototype_info());
2772  old_map->set_prototype_info(Smi::FromInt(0));
2773  if (FLAG_trace_prototype_users) {
2774    PrintF("Moving prototype_info %p from map %p to map %p.\n",
2775           reinterpret_cast<void*>(new_map->prototype_info()),
2776           reinterpret_cast<void*>(*old_map),
2777           reinterpret_cast<void*>(*new_map));
2778  }
2779  if (was_registered) {
2780    if (new_map->prototype_info()->IsPrototypeInfo()) {
2781      // The new map isn't registered with its prototype yet; reflect this fact
2782      // in the PrototypeInfo it just inherited from the old map.
2783      PrototypeInfo::cast(new_map->prototype_info())
2784          ->set_registry_slot(PrototypeInfo::UNREGISTERED);
2785    }
2786    JSObject::LazyRegisterPrototypeUser(new_map, isolate);
2787  }
2788}
2789
2790
2791void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
2792                            int expected_additional_properties) {
2793  if (object->map() == *new_map) return;
2794  // If this object is a prototype (the callee will check), invalidate any
2795  // prototype chains involving it.
2796  InvalidatePrototypeChains(object->map());
2797  Handle<Map> old_map(object->map());
2798
2799  // If the map was registered with its prototype before, ensure that it
2800  // registers with its new prototype now. This preserves the invariant that
2801  // when a map on a prototype chain is registered with its prototype, then
2802  // all prototypes further up the chain are also registered with their
2803  // respective prototypes.
2804  UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate());
2805
2806  if (object->HasFastProperties()) {
2807    if (!new_map->is_dictionary_map()) {
2808      MigrateFastToFast(object, new_map);
2809      if (old_map->is_prototype_map()) {
2810        DCHECK(!old_map->is_stable());
2811        DCHECK(new_map->is_stable());
2812        // Clear out the old descriptor array to avoid problems to sharing
2813        // the descriptor array without using an explicit.
2814        old_map->InitializeDescriptors(
2815            old_map->GetHeap()->empty_descriptor_array(),
2816            LayoutDescriptor::FastPointerLayout());
2817        // Ensure that no transition was inserted for prototype migrations.
2818        DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
2819                         old_map->raw_transitions()));
2820        DCHECK(new_map->GetBackPointer()->IsUndefined());
2821      }
2822    } else {
2823      MigrateFastToSlow(object, new_map, expected_additional_properties);
2824    }
2825  } else {
2826    // For slow-to-fast migrations JSObject::MigrateSlowToFast()
2827    // must be used instead.
2828    CHECK(new_map->is_dictionary_map());
2829
2830    // Slow-to-slow migration is trivial.
2831    object->set_map(*new_map);
2832  }
2833
2834  // Careful: Don't allocate here!
2835  // For some callers of this method, |object| might be in an inconsistent
2836  // state now: the new map might have a new elements_kind, but the object's
2837  // elements pointer hasn't been updated yet. Callers will fix this, but in
2838  // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
2839  // When adding code here, add a DisallowHeapAllocation too.
2840}
2841
2842
2843// To migrate a fast instance to a fast map:
2844// - First check whether the instance needs to be rewritten. If not, simply
2845//   change the map.
2846// - Otherwise, allocate a fixed array large enough to hold all fields, in
2847//   addition to unused space.
2848// - Copy all existing properties in, in the following order: backing store
2849//   properties, unused fields, inobject properties.
2850// - If all allocation succeeded, commit the state atomically:
2851//   * Copy inobject properties from the backing store back into the object.
2852//   * Trim the difference in instance size of the object. This also cleanly
2853//     frees inobject properties that moved to the backing store.
2854//   * If there are properties left in the backing store, trim of the space used
2855//     to temporarily store the inobject properties.
2856//   * If there are properties left in the backing store, install the backing
2857//     store.
2858void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
2859  Isolate* isolate = object->GetIsolate();
2860  Handle<Map> old_map(object->map());
2861  int old_number_of_fields;
2862  int number_of_fields = new_map->NumberOfFields();
2863  int inobject = new_map->GetInObjectProperties();
2864  int unused = new_map->unused_property_fields();
2865
2866  // Nothing to do if no functions were converted to fields and no smis were
2867  // converted to doubles.
2868  if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
2869                                       unused, &old_number_of_fields)) {
2870    object->synchronized_set_map(*new_map);
2871    return;
2872  }
2873
2874  int total_size = number_of_fields + unused;
2875  int external = total_size - inobject;
2876
2877  if (number_of_fields != old_number_of_fields &&
2878      new_map->GetBackPointer() == *old_map) {
2879    PropertyDetails details = new_map->GetLastDescriptorDetails();
2880
2881    if (old_map->unused_property_fields() > 0) {
2882      if (details.representation().IsDouble()) {
2883        FieldIndex index =
2884            FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
2885        if (new_map->IsUnboxedDoubleField(index)) {
2886          object->RawFastDoublePropertyAtPut(index, 0);
2887        } else {
2888          Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2889          object->RawFastPropertyAtPut(index, *value);
2890        }
2891      }
2892      object->synchronized_set_map(*new_map);
2893      return;
2894    }
2895
2896    DCHECK(number_of_fields == old_number_of_fields + 1);
2897    // This migration is a transition from a map that has run out of property
2898    // space. Therefore it could be done by extending the backing store.
2899    int grow_by = external - object->properties()->length();
2900    Handle<FixedArray> old_storage = handle(object->properties(), isolate);
2901    Handle<FixedArray> new_storage =
2902        isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
2903
2904    // Properly initialize newly added property.
2905    Handle<Object> value;
2906    if (details.representation().IsDouble()) {
2907      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2908    } else {
2909      value = isolate->factory()->uninitialized_value();
2910    }
2911    DCHECK(details.type() == DATA);
2912    int target_index = details.field_index() - inobject;
2913    DCHECK(target_index >= 0);  // Must be a backing store index.
2914    new_storage->set(target_index, *value);
2915
2916    // From here on we cannot fail and we shouldn't GC anymore.
2917    DisallowHeapAllocation no_allocation;
2918
2919    // Set the new property value and do the map transition.
2920    object->set_properties(*new_storage);
2921    object->synchronized_set_map(*new_map);
2922    return;
2923  }
2924  Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2925
2926  Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2927  Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2928  int old_nof = old_map->NumberOfOwnDescriptors();
2929  int new_nof = new_map->NumberOfOwnDescriptors();
2930
2931  // This method only supports generalizing instances to at least the same
2932  // number of properties.
2933  DCHECK(old_nof <= new_nof);
2934
2935  for (int i = 0; i < old_nof; i++) {
2936    PropertyDetails details = new_descriptors->GetDetails(i);
2937    if (details.type() != DATA) continue;
2938    PropertyDetails old_details = old_descriptors->GetDetails(i);
2939    Representation old_representation = old_details.representation();
2940    Representation representation = details.representation();
2941    Handle<Object> value;
2942    if (old_details.type() == ACCESSOR_CONSTANT) {
2943      // In case of kAccessor -> kData property reconfiguration, the property
2944      // must already be prepared for data or certain type.
2945      DCHECK(!details.representation().IsNone());
2946      if (details.representation().IsDouble()) {
2947        value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2948      } else {
2949        value = isolate->factory()->uninitialized_value();
2950      }
2951    } else if (old_details.type() == DATA_CONSTANT) {
2952      value = handle(old_descriptors->GetValue(i), isolate);
2953      DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
2954    } else {
2955      FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
2956      if (object->IsUnboxedDoubleField(index)) {
2957        double old = object->RawFastDoublePropertyAt(index);
2958        value = isolate->factory()->NewHeapNumber(
2959            old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
2960
2961      } else {
2962        value = handle(object->RawFastPropertyAt(index), isolate);
2963        if (!old_representation.IsDouble() && representation.IsDouble()) {
2964          if (old_representation.IsNone()) {
2965            value = handle(Smi::FromInt(0), isolate);
2966          }
2967          value = Object::NewStorageFor(isolate, value, representation);
2968        } else if (old_representation.IsDouble() &&
2969                   !representation.IsDouble()) {
2970          value = Object::WrapForRead(isolate, value, old_representation);
2971        }
2972      }
2973    }
2974    DCHECK(!(representation.IsDouble() && value->IsSmi()));
2975    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2976    if (target_index < 0) target_index += total_size;
2977    array->set(target_index, *value);
2978  }
2979
2980  for (int i = old_nof; i < new_nof; i++) {
2981    PropertyDetails details = new_descriptors->GetDetails(i);
2982    if (details.type() != DATA) continue;
2983    Handle<Object> value;
2984    if (details.representation().IsDouble()) {
2985      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2986    } else {
2987      value = isolate->factory()->uninitialized_value();
2988    }
2989    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2990    if (target_index < 0) target_index += total_size;
2991    array->set(target_index, *value);
2992  }
2993
2994  // From here on we cannot fail and we shouldn't GC anymore.
2995  DisallowHeapAllocation no_allocation;
2996
2997  // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2998  // avoid overwriting |one_pointer_filler_map|.
2999  int limit = Min(inobject, number_of_fields);
3000  for (int i = 0; i < limit; i++) {
3001    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
3002    Object* value = array->get(external + i);
3003    // Can't use JSObject::FastPropertyAtPut() because proper map was not set
3004    // yet.
3005    if (new_map->IsUnboxedDoubleField(index)) {
3006      DCHECK(value->IsMutableHeapNumber());
3007      object->RawFastDoublePropertyAtPut(index,
3008                                         HeapNumber::cast(value)->value());
3009    } else {
3010      object->RawFastPropertyAtPut(index, value);
3011    }
3012  }
3013
3014  Heap* heap = isolate->heap();
3015
3016  // If there are properties in the new backing store, trim it to the correct
3017  // size and install the backing store into the object.
3018  if (external > 0) {
3019    heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
3020    object->set_properties(*array);
3021  }
3022
3023  // Create filler object past the new instance size.
3024  int new_instance_size = new_map->instance_size();
3025  int instance_size_delta = old_map->instance_size() - new_instance_size;
3026  DCHECK(instance_size_delta >= 0);
3027
3028  if (instance_size_delta > 0) {
3029    Address address = object->address();
3030    heap->CreateFillerObjectAt(
3031        address + new_instance_size, instance_size_delta);
3032    heap->AdjustLiveBytes(*object, -instance_size_delta,
3033                          Heap::CONCURRENT_TO_SWEEPER);
3034  }
3035
3036  // We are storing the new map using release store after creating a filler for
3037  // the left-over space to avoid races with the sweeper thread.
3038  object->synchronized_set_map(*new_map);
3039}
3040
3041
3042int Map::NumberOfFields() {
3043  DescriptorArray* descriptors = instance_descriptors();
3044  int result = 0;
3045  for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
3046    if (descriptors->GetDetails(i).location() == kField) result++;
3047  }
3048  return result;
3049}
3050
3051
3052Handle<Map> Map::CopyGeneralizeAllRepresentations(
3053    Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
3054    PropertyAttributes attributes, const char* reason) {
3055  Isolate* isolate = map->GetIsolate();
3056  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3057  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
3058  Handle<DescriptorArray> descriptors =
3059      DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
3060
3061  for (int i = 0; i < number_of_own_descriptors; i++) {
3062    descriptors->SetRepresentation(i, Representation::Tagged());
3063    if (descriptors->GetDetails(i).type() == DATA) {
3064      descriptors->SetValue(i, HeapType::Any());
3065    }
3066  }
3067
3068  Handle<LayoutDescriptor> new_layout_descriptor(
3069      LayoutDescriptor::FastPointerLayout(), isolate);
3070  Handle<Map> new_map = CopyReplaceDescriptors(
3071      map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
3072      MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
3073
3074  // Unless the instance is being migrated, ensure that modify_index is a field.
3075  if (modify_index >= 0) {
3076    PropertyDetails details = descriptors->GetDetails(modify_index);
3077    if (store_mode == FORCE_FIELD &&
3078        (details.type() != DATA || details.attributes() != attributes)) {
3079      int field_index = details.type() == DATA ? details.field_index()
3080                                               : new_map->NumberOfFields();
3081      DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
3082                       field_index, attributes, Representation::Tagged());
3083      descriptors->Replace(modify_index, &d);
3084      if (details.type() != DATA) {
3085        int unused_property_fields = new_map->unused_property_fields() - 1;
3086        if (unused_property_fields < 0) {
3087          unused_property_fields += JSObject::kFieldsAdded;
3088        }
3089        new_map->set_unused_property_fields(unused_property_fields);
3090      }
3091    } else {
3092      DCHECK(details.attributes() == attributes);
3093    }
3094
3095    if (FLAG_trace_generalization) {
3096      HeapType* field_type =
3097          (details.type() == DATA)
3098              ? map->instance_descriptors()->GetFieldType(modify_index)
3099              : NULL;
3100      map->PrintGeneralization(
3101          stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
3102          new_map->NumberOfOwnDescriptors(),
3103          details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
3104          details.representation(), Representation::Tagged(), field_type,
3105          HeapType::Any());
3106    }
3107  }
3108  return new_map;
3109}
3110
3111
3112void Map::DeprecateTransitionTree() {
3113  if (is_deprecated()) return;
3114  Object* transitions = raw_transitions();
3115  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3116  for (int i = 0; i < num_transitions; ++i) {
3117    TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
3118  }
3119  deprecate();
3120  dependent_code()->DeoptimizeDependentCodeGroup(
3121      GetIsolate(), DependentCode::kTransitionGroup);
3122  NotifyLeafMapLayoutChange();
3123}
3124
3125
3126static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
3127  if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
3128  // TODO(ishell): compare AccessorPairs.
3129  return false;
3130}
3131
3132
3133// Installs |new_descriptors| over the current instance_descriptors to ensure
3134// proper sharing of descriptor arrays.
3135void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
3136                             LayoutDescriptor* new_layout_descriptor) {
3137  // Don't overwrite the empty descriptor array or initial map's descriptors.
3138  if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) {
3139    return;
3140  }
3141
3142  DescriptorArray* to_replace = instance_descriptors();
3143  GetHeap()->incremental_marking()->RecordWrites(to_replace);
3144  Map* current = this;
3145  while (current->instance_descriptors() == to_replace) {
3146    Object* next = current->GetBackPointer();
3147    if (next->IsUndefined()) break;  // Stop overwriting at initial map.
3148    current->SetEnumLength(kInvalidEnumCacheSentinel);
3149    current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
3150    current = Map::cast(next);
3151  }
3152  set_owns_descriptors(false);
3153}
3154
3155
3156Map* Map::FindRootMap() {
3157  Map* result = this;
3158  while (true) {
3159    Object* back = result->GetBackPointer();
3160    if (back->IsUndefined()) {
3161      // Initial map always owns descriptors and doesn't have unused entries
3162      // in the descriptor array.
3163      DCHECK(result->owns_descriptors());
3164      DCHECK_EQ(result->NumberOfOwnDescriptors(),
3165                result->instance_descriptors()->number_of_descriptors());
3166      return result;
3167    }
3168    result = Map::cast(back);
3169  }
3170}
3171
3172
3173Map* Map::FindLastMatchMap(int verbatim,
3174                           int length,
3175                           DescriptorArray* descriptors) {
3176  DisallowHeapAllocation no_allocation;
3177
3178  // This can only be called on roots of transition trees.
3179  DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
3180
3181  Map* current = this;
3182
3183  for (int i = verbatim; i < length; i++) {
3184    Name* name = descriptors->GetKey(i);
3185    PropertyDetails details = descriptors->GetDetails(i);
3186    Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
3187                                                  details.attributes());
3188    if (next == NULL) break;
3189    DescriptorArray* next_descriptors = next->instance_descriptors();
3190
3191    PropertyDetails next_details = next_descriptors->GetDetails(i);
3192    DCHECK_EQ(details.kind(), next_details.kind());
3193    DCHECK_EQ(details.attributes(), next_details.attributes());
3194    if (details.location() != next_details.location()) break;
3195    if (!details.representation().Equals(next_details.representation())) break;
3196
3197    if (next_details.location() == kField) {
3198      HeapType* next_field_type = next_descriptors->GetFieldType(i);
3199      if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
3200        break;
3201      }
3202    } else {
3203      if (!EqualImmutableValues(descriptors->GetValue(i),
3204                                next_descriptors->GetValue(i))) {
3205        break;
3206      }
3207    }
3208    current = next;
3209  }
3210  return current;
3211}
3212
3213
3214Map* Map::FindFieldOwner(int descriptor) {
3215  DisallowHeapAllocation no_allocation;
3216  DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
3217  Map* result = this;
3218  while (true) {
3219    Object* back = result->GetBackPointer();
3220    if (back->IsUndefined()) break;
3221    Map* parent = Map::cast(back);
3222    if (parent->NumberOfOwnDescriptors() <= descriptor) break;
3223    result = parent;
3224  }
3225  return result;
3226}
3227
3228
3229void Map::UpdateFieldType(int descriptor, Handle<Name> name,
3230                          Representation new_representation,
3231                          Handle<Object> new_wrapped_type) {
3232  DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
3233  DisallowHeapAllocation no_allocation;
3234  PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
3235  if (details.type() != DATA) return;
3236  Object* transitions = raw_transitions();
3237  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
3238  for (int i = 0; i < num_transitions; ++i) {
3239    Map* target = TransitionArray::GetTarget(transitions, i);
3240    target->UpdateFieldType(descriptor, name, new_representation,
3241                            new_wrapped_type);
3242  }
3243  // It is allowed to change representation here only from None to something.
3244  DCHECK(details.representation().Equals(new_representation) ||
3245         details.representation().IsNone());
3246
3247  // Skip if already updated the shared descriptor.
3248  if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return;
3249  DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
3250                   new_wrapped_type, details.attributes(), new_representation);
3251  instance_descriptors()->Replace(descriptor, &d);
3252}
3253
3254
3255bool FieldTypeIsCleared(Representation rep, HeapType* type) {
3256  return type->Is(HeapType::None()) && rep.IsHeapObject();
3257}
3258
3259
3260// static
3261Handle<HeapType> Map::GeneralizeFieldType(Representation rep1,
3262                                          Handle<HeapType> type1,
3263                                          Representation rep2,
3264                                          Handle<HeapType> type2,
3265                                          Isolate* isolate) {
3266  // Cleared field types need special treatment. They represent lost knowledge,
3267  // so we must be conservative, so their generalization with any other type
3268  // is "Any".
3269  if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
3270    return HeapType::Any(isolate);
3271  }
3272  if (type1->NowIs(type2)) return type2;
3273  if (type2->NowIs(type1)) return type1;
3274  return HeapType::Any(isolate);
3275}
3276
3277
3278// static
3279void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
3280                              Representation new_representation,
3281                              Handle<HeapType> new_field_type) {
3282  Isolate* isolate = map->GetIsolate();
3283
3284  // Check if we actually need to generalize the field type at all.
3285  Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
3286  Representation old_representation =
3287      old_descriptors->GetDetails(modify_index).representation();
3288  Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
3289                                  isolate);
3290
3291  if (old_representation.Equals(new_representation) &&
3292      !FieldTypeIsCleared(new_representation, *new_field_type) &&
3293      // Checking old_field_type for being cleared is not necessary because
3294      // the NowIs check below would fail anyway in that case.
3295      new_field_type->NowIs(old_field_type)) {
3296    DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type,
3297                                    new_representation, new_field_type, isolate)
3298               ->NowIs(old_field_type));
3299    return;
3300  }
3301
3302  // Determine the field owner.
3303  Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
3304  Handle<DescriptorArray> descriptors(
3305      field_owner->instance_descriptors(), isolate);
3306  DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
3307
3308  new_field_type =
3309      Map::GeneralizeFieldType(old_representation, old_field_type,
3310                               new_representation, new_field_type, isolate);
3311
3312  PropertyDetails details = descriptors->GetDetails(modify_index);
3313  Handle<Name> name(descriptors->GetKey(modify_index));
3314
3315  Handle<Object> wrapped_type(WrapType(new_field_type));
3316  field_owner->UpdateFieldType(modify_index, name, new_representation,
3317                               wrapped_type);
3318  field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
3319      isolate, DependentCode::kFieldTypeGroup);
3320
3321  if (FLAG_trace_generalization) {
3322    map->PrintGeneralization(
3323        stdout, "field type generalization",
3324        modify_index, map->NumberOfOwnDescriptors(),
3325        map->NumberOfOwnDescriptors(), false,
3326        details.representation(), details.representation(),
3327        *old_field_type, *new_field_type);
3328  }
3329}
3330
3331
3332static inline Handle<HeapType> GetFieldType(Isolate* isolate,
3333                                            Handle<DescriptorArray> descriptors,
3334                                            int descriptor,
3335                                            PropertyLocation location,
3336                                            Representation representation) {
3337#ifdef DEBUG
3338  PropertyDetails details = descriptors->GetDetails(descriptor);
3339  DCHECK_EQ(kData, details.kind());
3340  DCHECK_EQ(details.location(), location);
3341#endif
3342  if (location == kField) {
3343    return handle(descriptors->GetFieldType(descriptor), isolate);
3344  } else {
3345    return descriptors->GetValue(descriptor)
3346        ->OptimalType(isolate, representation);
3347  }
3348}
3349
3350
3351// Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
3352// |store_mode| and/or |new_representation|/|new_field_type|.
3353// If |modify_index| is negative then no properties are reconfigured but the
3354// map is migrated to the up-to-date non-deprecated state.
3355//
3356// This method rewrites or completes the transition tree to reflect the new
3357// change. To avoid high degrees over polymorphism, and to stabilize quickly,
3358// on every rewrite the new type is deduced by merging the current type with
3359// any potential new (partial) version of the type in the transition tree.
3360// To do this, on each rewrite:
3361// - Search the root of the transition tree using FindRootMap.
3362// - Find |target_map|, the newest matching version of this map using the
3363//   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
3364//   |modify_index| is considered to be of |new_kind| and having
3365//   |new_attributes|) to walk the transition tree.
3366// - Merge/generalize the "enhanced" descriptor array of the |old_map| and
3367//   descriptor array of the |target_map|.
3368// - Generalize the |modify_index| descriptor using |new_representation| and
3369//   |new_field_type|.
3370// - Walk the tree again starting from the root towards |target_map|. Stop at
3371//   |split_map|, the first map who's descriptor array does not match the merged
3372//   descriptor array.
3373// - If |target_map| == |split_map|, |target_map| is in the expected state.
3374//   Return it.
3375// - Otherwise, invalidate the outdated transition target from |target_map|, and
3376//   replace its transition tree with a new branch for the updated descriptors.
3377Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
3378                                     PropertyKind new_kind,
3379                                     PropertyAttributes new_attributes,
3380                                     Representation new_representation,
3381                                     Handle<HeapType> new_field_type,
3382                                     StoreMode store_mode) {
3383  DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
3384  DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
3385  Isolate* isolate = old_map->GetIsolate();
3386
3387  Handle<DescriptorArray> old_descriptors(
3388      old_map->instance_descriptors(), isolate);
3389  int old_nof = old_map->NumberOfOwnDescriptors();
3390
3391  // If it's just a representation generalization case (i.e. property kind and
3392  // attributes stays unchanged) it's fine to transition from None to anything
3393  // but double without any modification to the object, because the default
3394  // uninitialized value for representation None can be overwritten by both
3395  // smi and tagged values. Doubles, however, would require a box allocation.
3396  if (modify_index >= 0 && !new_representation.IsNone() &&
3397      !new_representation.IsDouble()) {
3398    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3399    Representation old_representation = old_details.representation();
3400
3401    if (old_representation.IsNone()) {
3402      DCHECK_EQ(new_kind, old_details.kind());
3403      DCHECK_EQ(new_attributes, old_details.attributes());
3404      DCHECK_EQ(DATA, old_details.type());
3405      if (FLAG_trace_generalization) {
3406        old_map->PrintGeneralization(
3407            stdout, "uninitialized field", modify_index,
3408            old_map->NumberOfOwnDescriptors(),
3409            old_map->NumberOfOwnDescriptors(), false, old_representation,
3410            new_representation, old_descriptors->GetFieldType(modify_index),
3411            *new_field_type);
3412      }
3413      Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
3414
3415      GeneralizeFieldType(field_owner, modify_index, new_representation,
3416                          new_field_type);
3417      DCHECK(old_descriptors->GetDetails(modify_index)
3418                 .representation()
3419                 .Equals(new_representation));
3420      DCHECK(
3421          old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
3422      return old_map;
3423    }
3424  }
3425
3426  // Check the state of the root map.
3427  Handle<Map> root_map(old_map->FindRootMap(), isolate);
3428  if (!old_map->EquivalentToForTransition(*root_map)) {
3429    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3430                                            new_kind, new_attributes,
3431                                            "GenAll_NotEquivalent");
3432  }
3433
3434  ElementsKind from_kind = root_map->elements_kind();
3435  ElementsKind to_kind = old_map->elements_kind();
3436  // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
3437  if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
3438      to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
3439      !(IsTransitionableFastElementsKind(from_kind) &&
3440        IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
3441    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3442                                            new_kind, new_attributes,
3443                                            "GenAll_InvalidElementsTransition");
3444  }
3445  int root_nof = root_map->NumberOfOwnDescriptors();
3446  if (modify_index >= 0 && modify_index < root_nof) {
3447    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3448    if (old_details.kind() != new_kind ||
3449        old_details.attributes() != new_attributes) {
3450      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3451                                              new_kind, new_attributes,
3452                                              "GenAll_RootModification1");
3453    }
3454    if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
3455        (old_details.type() == DATA &&
3456         (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
3457          !new_representation.fits_into(old_details.representation())))) {
3458      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3459                                              new_kind, new_attributes,
3460                                              "GenAll_RootModification2");
3461    }
3462  }
3463
3464  // From here on, use the map with correct elements kind as root map.
3465  if (from_kind != to_kind) {
3466    root_map = Map::AsElementsKind(root_map, to_kind);
3467  }
3468
3469  Handle<Map> target_map = root_map;
3470  for (int i = root_nof; i < old_nof; ++i) {
3471    PropertyDetails old_details = old_descriptors->GetDetails(i);
3472    PropertyKind next_kind;
3473    PropertyLocation next_location;
3474    PropertyAttributes next_attributes;
3475    Representation next_representation;
3476    bool property_kind_reconfiguration = false;
3477
3478    if (modify_index == i) {
3479      DCHECK_EQ(FORCE_FIELD, store_mode);
3480      property_kind_reconfiguration = old_details.kind() != new_kind;
3481
3482      next_kind = new_kind;
3483      next_location = kField;
3484      next_attributes = new_attributes;
3485      // If property kind is not reconfigured merge the result with
3486      // representation/field type from the old descriptor.
3487      next_representation = new_representation;
3488      if (!property_kind_reconfiguration) {
3489        next_representation =
3490            next_representation.generalize(old_details.representation());
3491      }
3492
3493    } else {
3494      next_kind = old_details.kind();
3495      next_location = old_details.location();
3496      next_attributes = old_details.attributes();
3497      next_representation = old_details.representation();
3498    }
3499    Map* transition = TransitionArray::SearchTransition(
3500        *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
3501    if (transition == NULL) break;
3502    Handle<Map> tmp_map(transition, isolate);
3503
3504    Handle<DescriptorArray> tmp_descriptors = handle(
3505        tmp_map->instance_descriptors(), isolate);
3506
3507    // Check if target map is incompatible.
3508    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3509    DCHECK_EQ(next_kind, tmp_details.kind());
3510    DCHECK_EQ(next_attributes, tmp_details.attributes());
3511    if (next_kind == kAccessor &&
3512        !EqualImmutableValues(old_descriptors->GetValue(i),
3513                              tmp_descriptors->GetValue(i))) {
3514      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3515                                              new_kind, new_attributes,
3516                                              "GenAll_Incompatible");
3517    }
3518    if (next_location == kField && tmp_details.location() == kDescriptor) break;
3519
3520    Representation tmp_representation = tmp_details.representation();
3521    if (!next_representation.fits_into(tmp_representation)) break;
3522
3523    PropertyLocation old_location = old_details.location();
3524    PropertyLocation tmp_location = tmp_details.location();
3525    if (tmp_location == kField) {
3526      if (next_kind == kData) {
3527        Handle<HeapType> next_field_type;
3528        if (modify_index == i) {
3529          next_field_type = new_field_type;
3530          if (!property_kind_reconfiguration) {
3531            Handle<HeapType> old_field_type =
3532                GetFieldType(isolate, old_descriptors, i,
3533                             old_details.location(), tmp_representation);
3534            Representation old_representation = old_details.representation();
3535            next_field_type = GeneralizeFieldType(
3536                old_representation, old_field_type, new_representation,
3537                next_field_type, isolate);
3538          }
3539        } else {
3540          Handle<HeapType> old_field_type =
3541              GetFieldType(isolate, old_descriptors, i, old_details.location(),
3542                           tmp_representation);
3543          next_field_type = old_field_type;
3544        }
3545        GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
3546      }
3547    } else if (old_location == kField ||
3548               !EqualImmutableValues(old_descriptors->GetValue(i),
3549                                     tmp_descriptors->GetValue(i))) {
3550      break;
3551    }
3552    DCHECK(!tmp_map->is_deprecated());
3553    target_map = tmp_map;
3554  }
3555
3556  // Directly change the map if the target map is more general.
3557  Handle<DescriptorArray> target_descriptors(
3558      target_map->instance_descriptors(), isolate);
3559  int target_nof = target_map->NumberOfOwnDescriptors();
3560  if (target_nof == old_nof &&
3561      (store_mode != FORCE_FIELD ||
3562       (modify_index >= 0 &&
3563        target_descriptors->GetDetails(modify_index).location() == kField))) {
3564#ifdef DEBUG
3565    if (modify_index >= 0) {
3566      PropertyDetails details = target_descriptors->GetDetails(modify_index);
3567      DCHECK_EQ(new_kind, details.kind());
3568      DCHECK_EQ(new_attributes, details.attributes());
3569      DCHECK(new_representation.fits_into(details.representation()));
3570      DCHECK(details.location() != kField ||
3571             new_field_type->NowIs(
3572                 target_descriptors->GetFieldType(modify_index)));
3573    }
3574#endif
3575    if (*target_map != *old_map) {
3576      old_map->NotifyLeafMapLayoutChange();
3577    }
3578    return target_map;
3579  }
3580
3581  // Find the last compatible target map in the transition tree.
3582  for (int i = target_nof; i < old_nof; ++i) {
3583    PropertyDetails old_details = old_descriptors->GetDetails(i);
3584    PropertyKind next_kind;
3585    PropertyAttributes next_attributes;
3586    if (modify_index == i) {
3587      next_kind = new_kind;
3588      next_attributes = new_attributes;
3589    } else {
3590      next_kind = old_details.kind();
3591      next_attributes = old_details.attributes();
3592    }
3593    Map* transition = TransitionArray::SearchTransition(
3594        *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
3595    if (transition == NULL) break;
3596    Handle<Map> tmp_map(transition, isolate);
3597    Handle<DescriptorArray> tmp_descriptors(
3598        tmp_map->instance_descriptors(), isolate);
3599
3600    // Check if target map is compatible.
3601#ifdef DEBUG
3602    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
3603    DCHECK_EQ(next_kind, tmp_details.kind());
3604    DCHECK_EQ(next_attributes, tmp_details.attributes());
3605#endif
3606    if (next_kind == kAccessor &&
3607        !EqualImmutableValues(old_descriptors->GetValue(i),
3608                              tmp_descriptors->GetValue(i))) {
3609      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3610                                              new_kind, new_attributes,
3611                                              "GenAll_Incompatible");
3612    }
3613    DCHECK(!tmp_map->is_deprecated());
3614    target_map = tmp_map;
3615  }
3616  target_nof = target_map->NumberOfOwnDescriptors();
3617  target_descriptors = handle(target_map->instance_descriptors(), isolate);
3618
3619  // Allocate a new descriptor array large enough to hold the required
3620  // descriptors, with minimally the exact same size as the old descriptor
3621  // array.
3622  int new_slack = Max(
3623      old_nof, old_descriptors->number_of_descriptors()) - old_nof;
3624  Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
3625      isolate, old_nof, new_slack);
3626  DCHECK(new_descriptors->length() > target_descriptors->length() ||
3627         new_descriptors->NumberOfSlackDescriptors() > 0 ||
3628         new_descriptors->number_of_descriptors() ==
3629         old_descriptors->number_of_descriptors());
3630  DCHECK(new_descriptors->number_of_descriptors() == old_nof);
3631
3632  // 0 -> |root_nof|
3633  int current_offset = 0;
3634  for (int i = 0; i < root_nof; ++i) {
3635    PropertyDetails old_details = old_descriptors->GetDetails(i);
3636    if (old_details.location() == kField) {
3637      current_offset += old_details.field_width_in_words();
3638    }
3639    Descriptor d(handle(old_descriptors->GetKey(i), isolate),
3640                 handle(old_descriptors->GetValue(i), isolate),
3641                 old_details);
3642    new_descriptors->Set(i, &d);
3643  }
3644
3645  // |root_nof| -> |target_nof|
3646  for (int i = root_nof; i < target_nof; ++i) {
3647    Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
3648    PropertyDetails old_details = old_descriptors->GetDetails(i);
3649    PropertyDetails target_details = target_descriptors->GetDetails(i);
3650
3651    PropertyKind next_kind;
3652    PropertyAttributes next_attributes;
3653    PropertyLocation next_location;
3654    Representation next_representation;
3655    bool property_kind_reconfiguration = false;
3656
3657    if (modify_index == i) {
3658      DCHECK_EQ(FORCE_FIELD, store_mode);
3659      property_kind_reconfiguration = old_details.kind() != new_kind;
3660
3661      next_kind = new_kind;
3662      next_attributes = new_attributes;
3663      next_location = kField;
3664
3665      // Merge new representation/field type with ones from the target
3666      // descriptor. If property kind is not reconfigured merge the result with
3667      // representation/field type from the old descriptor.
3668      next_representation =
3669          new_representation.generalize(target_details.representation());
3670      if (!property_kind_reconfiguration) {
3671        next_representation =
3672            next_representation.generalize(old_details.representation());
3673      }
3674    } else {
3675      // Merge old_descriptor and target_descriptor entries.
3676      DCHECK_EQ(target_details.kind(), old_details.kind());
3677      next_kind = target_details.kind();
3678      next_attributes = target_details.attributes();
3679      next_location =
3680          old_details.location() == kField ||
3681                  target_details.location() == kField ||
3682                  !EqualImmutableValues(target_descriptors->GetValue(i),
3683                                        old_descriptors->GetValue(i))
3684              ? kField
3685              : kDescriptor;
3686
3687      next_representation = old_details.representation().generalize(
3688          target_details.representation());
3689    }
3690    DCHECK_EQ(next_kind, target_details.kind());
3691    DCHECK_EQ(next_attributes, target_details.attributes());
3692
3693    if (next_location == kField) {
3694      if (next_kind == kData) {
3695        Handle<HeapType> target_field_type =
3696            GetFieldType(isolate, target_descriptors, i,
3697                         target_details.location(), next_representation);
3698
3699        Handle<HeapType> next_field_type;
3700        if (modify_index == i) {
3701          next_field_type = GeneralizeFieldType(
3702              target_details.representation(), target_field_type,
3703              new_representation, new_field_type, isolate);
3704          if (!property_kind_reconfiguration) {
3705            Handle<HeapType> old_field_type =
3706                GetFieldType(isolate, old_descriptors, i,
3707                             old_details.location(), next_representation);
3708            next_field_type = GeneralizeFieldType(
3709                old_details.representation(), old_field_type,
3710                next_representation, next_field_type, isolate);
3711          }
3712        } else {
3713          Handle<HeapType> old_field_type =
3714              GetFieldType(isolate, old_descriptors, i, old_details.location(),
3715                           next_representation);
3716          next_field_type = GeneralizeFieldType(
3717              old_details.representation(), old_field_type, next_representation,
3718              target_field_type, isolate);
3719        }
3720        Handle<Object> wrapped_type(WrapType(next_field_type));
3721        DataDescriptor d(target_key, current_offset, wrapped_type,
3722                         next_attributes, next_representation);
3723        current_offset += d.GetDetails().field_width_in_words();
3724        new_descriptors->Set(i, &d);
3725      } else {
3726        UNIMPLEMENTED();  // TODO(ishell): implement.
3727      }
3728    } else {
3729      PropertyDetails details(next_attributes, next_kind, next_location,
3730                              next_representation);
3731      Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
3732                   details);
3733      new_descriptors->Set(i, &d);
3734    }
3735  }
3736
3737  // |target_nof| -> |old_nof|
3738  for (int i = target_nof; i < old_nof; ++i) {
3739    PropertyDetails old_details = old_descriptors->GetDetails(i);
3740    Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
3741
3742    // Merge old_descriptor entry and modified details together.
3743    PropertyKind next_kind;
3744    PropertyAttributes next_attributes;
3745    PropertyLocation next_location;
3746    Representation next_representation;
3747    bool property_kind_reconfiguration = false;
3748
3749    if (modify_index == i) {
3750      DCHECK_EQ(FORCE_FIELD, store_mode);
3751      // In case of property kind reconfiguration it is not necessary to
3752      // take into account representation/field type of the old descriptor.
3753      property_kind_reconfiguration = old_details.kind() != new_kind;
3754
3755      next_kind = new_kind;
3756      next_attributes = new_attributes;
3757      next_location = kField;
3758      next_representation = new_representation;
3759      if (!property_kind_reconfiguration) {
3760        next_representation =
3761            next_representation.generalize(old_details.representation());
3762      }
3763    } else {
3764      next_kind = old_details.kind();
3765      next_attributes = old_details.attributes();
3766      next_location = old_details.location();
3767      next_representation = old_details.representation();
3768    }
3769
3770    if (next_location == kField) {
3771      if (next_kind == kData) {
3772        Handle<HeapType> next_field_type;
3773        if (modify_index == i) {
3774          next_field_type = new_field_type;
3775          if (!property_kind_reconfiguration) {
3776            Handle<HeapType> old_field_type =
3777                GetFieldType(isolate, old_descriptors, i,
3778                             old_details.location(), next_representation);
3779            next_field_type = GeneralizeFieldType(
3780                old_details.representation(), old_field_type,
3781                next_representation, next_field_type, isolate);
3782          }
3783        } else {
3784          Handle<HeapType> old_field_type =
3785              GetFieldType(isolate, old_descriptors, i, old_details.location(),
3786                           next_representation);
3787          next_field_type = old_field_type;
3788        }
3789
3790        Handle<Object> wrapped_type(WrapType(next_field_type));
3791
3792        DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
3793                         next_representation);
3794        current_offset += d.GetDetails().field_width_in_words();
3795        new_descriptors->Set(i, &d);
3796      } else {
3797        UNIMPLEMENTED();  // TODO(ishell): implement.
3798      }
3799    } else {
3800      PropertyDetails details(next_attributes, next_kind, next_location,
3801                              next_representation);
3802      Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
3803                   details);
3804      new_descriptors->Set(i, &d);
3805    }
3806  }
3807
3808  new_descriptors->Sort();
3809
3810  DCHECK(store_mode != FORCE_FIELD ||
3811         new_descriptors->GetDetails(modify_index).location() == kField);
3812
3813  Handle<Map> split_map(root_map->FindLastMatchMap(
3814          root_nof, old_nof, *new_descriptors), isolate);
3815  int split_nof = split_map->NumberOfOwnDescriptors();
3816  DCHECK_NE(old_nof, split_nof);
3817
3818  PropertyKind split_kind;
3819  PropertyAttributes split_attributes;
3820  if (modify_index == split_nof) {
3821    split_kind = new_kind;
3822    split_attributes = new_attributes;
3823  } else {
3824    PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
3825    split_kind = split_prop_details.kind();
3826    split_attributes = split_prop_details.attributes();
3827  }
3828
3829  // Invalidate a transition target at |key|.
3830  Map* maybe_transition = TransitionArray::SearchTransition(
3831      *split_map, split_kind, old_descriptors->GetKey(split_nof),
3832      split_attributes);
3833  if (maybe_transition != NULL) {
3834    maybe_transition->DeprecateTransitionTree();
3835  }
3836
3837  // If |maybe_transition| is not NULL then the transition array already
3838  // contains entry for given descriptor. This means that the transition
3839  // could be inserted regardless of whether transitions array is full or not.
3840  if (maybe_transition == NULL &&
3841      !TransitionArray::CanHaveMoreTransitions(split_map)) {
3842    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3843                                            new_kind, new_attributes,
3844                                            "GenAll_CantHaveMoreTransitions");
3845  }
3846
3847  old_map->NotifyLeafMapLayoutChange();
3848
3849  if (FLAG_trace_generalization && modify_index >= 0) {
3850    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
3851    PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
3852    Handle<HeapType> old_field_type =
3853        (old_details.type() == DATA)
3854            ? handle(old_descriptors->GetFieldType(modify_index), isolate)
3855            : HeapType::Constant(
3856                  handle(old_descriptors->GetValue(modify_index), isolate),
3857                  isolate);
3858    Handle<HeapType> new_field_type =
3859        (new_details.type() == DATA)
3860            ? handle(new_descriptors->GetFieldType(modify_index), isolate)
3861            : HeapType::Constant(
3862                  handle(new_descriptors->GetValue(modify_index), isolate),
3863                  isolate);
3864    old_map->PrintGeneralization(
3865        stdout, "", modify_index, split_nof, old_nof,
3866        old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
3867        old_details.representation(), new_details.representation(),
3868        *old_field_type, *new_field_type);
3869  }
3870
3871  Handle<LayoutDescriptor> new_layout_descriptor =
3872      LayoutDescriptor::New(split_map, new_descriptors, old_nof);
3873
3874  Handle<Map> new_map =
3875      AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
3876
3877  // Deprecated part of the transition tree is no longer reachable, so replace
3878  // current instance descriptors in the "survived" part of the tree with
3879  // the new descriptors to maintain descriptors sharing invariant.
3880  split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
3881  return new_map;
3882}
3883
3884
3885// Generalize the representation of all DATA descriptors.
3886Handle<Map> Map::GeneralizeAllFieldRepresentations(
3887    Handle<Map> map) {
3888  Handle<DescriptorArray> descriptors(map->instance_descriptors());
3889  for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
3890    PropertyDetails details = descriptors->GetDetails(i);
3891    if (details.type() == DATA) {
3892      map = ReconfigureProperty(map, i, kData, details.attributes(),
3893                                Representation::Tagged(),
3894                                HeapType::Any(map->GetIsolate()), FORCE_FIELD);
3895    }
3896  }
3897  return map;
3898}
3899
3900
3901// static
3902MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
3903  DisallowHeapAllocation no_allocation;
3904  DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
3905
3906  if (!old_map->is_deprecated()) return old_map;
3907
3908  // Check the state of the root map.
3909  Map* root_map = old_map->FindRootMap();
3910  if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
3911
3912  ElementsKind from_kind = root_map->elements_kind();
3913  ElementsKind to_kind = old_map->elements_kind();
3914  if (from_kind != to_kind) {
3915    // Try to follow existing elements kind transitions.
3916    root_map = root_map->LookupElementsTransitionMap(to_kind);
3917    if (root_map == NULL) return MaybeHandle<Map>();
3918    // From here on, use the map with correct elements kind as root map.
3919  }
3920  int root_nof = root_map->NumberOfOwnDescriptors();
3921
3922  int old_nof = old_map->NumberOfOwnDescriptors();
3923  DescriptorArray* old_descriptors = old_map->instance_descriptors();
3924
3925  Map* new_map = root_map;
3926  for (int i = root_nof; i < old_nof; ++i) {
3927    PropertyDetails old_details = old_descriptors->GetDetails(i);
3928    Map* transition = TransitionArray::SearchTransition(
3929        new_map, old_details.kind(), old_descriptors->GetKey(i),
3930        old_details.attributes());
3931    if (transition == NULL) return MaybeHandle<Map>();
3932    new_map = transition;
3933    DescriptorArray* new_descriptors = new_map->instance_descriptors();
3934
3935    PropertyDetails new_details = new_descriptors->GetDetails(i);
3936    DCHECK_EQ(old_details.kind(), new_details.kind());
3937    DCHECK_EQ(old_details.attributes(), new_details.attributes());
3938    if (!old_details.representation().fits_into(new_details.representation())) {
3939      return MaybeHandle<Map>();
3940    }
3941    switch (new_details.type()) {
3942      case DATA: {
3943        HeapType* new_type = new_descriptors->GetFieldType(i);
3944        // Cleared field types need special treatment. They represent lost
3945        // knowledge, so we must first generalize the new_type to "Any".
3946        if (FieldTypeIsCleared(new_details.representation(), new_type)) {
3947          return MaybeHandle<Map>();
3948        }
3949        PropertyType old_property_type = old_details.type();
3950        if (old_property_type == DATA) {
3951          HeapType* old_type = old_descriptors->GetFieldType(i);
3952          if (FieldTypeIsCleared(old_details.representation(), old_type) ||
3953              !old_type->NowIs(new_type)) {
3954            return MaybeHandle<Map>();
3955          }
3956        } else {
3957          DCHECK(old_property_type == DATA_CONSTANT);
3958          Object* old_value = old_descriptors->GetValue(i);
3959          if (!new_type->NowContains(old_value)) {
3960            return MaybeHandle<Map>();
3961          }
3962        }
3963        break;
3964      }
3965      case ACCESSOR: {
3966#ifdef DEBUG
3967        HeapType* new_type = new_descriptors->GetFieldType(i);
3968        DCHECK(HeapType::Any()->Is(new_type));
3969#endif
3970        break;
3971      }
3972
3973      case DATA_CONSTANT:
3974      case ACCESSOR_CONSTANT: {
3975        Object* old_value = old_descriptors->GetValue(i);
3976        Object* new_value = new_descriptors->GetValue(i);
3977        if (old_details.location() == kField || old_value != new_value) {
3978          return MaybeHandle<Map>();
3979        }
3980        break;
3981      }
3982    }
3983  }
3984  if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
3985  return handle(new_map);
3986}
3987
3988
3989// static
3990Handle<Map> Map::Update(Handle<Map> map) {
3991  if (!map->is_deprecated()) return map;
3992  return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
3993                             HeapType::None(map->GetIsolate()),
3994                             ALLOW_IN_DESCRIPTOR);
3995}
3996
3997
3998Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
3999                                                 Handle<Object> value) {
4000  Isolate* isolate = it->isolate();
4001  // Make sure that the top context does not change when doing callbacks or
4002  // interceptor calls.
4003  AssertNoContextChange ncc(isolate);
4004
4005  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
4006  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
4007  if (interceptor->setter()->IsUndefined()) return Just(false);
4008
4009  Handle<JSObject> holder = it->GetHolder<JSObject>();
4010  v8::Local<v8::Value> result;
4011  PropertyCallbackArguments args(isolate, interceptor->data(),
4012                                 *it->GetReceiver(), *holder);
4013
4014  if (it->IsElement()) {
4015    uint32_t index = it->index();
4016    v8::IndexedPropertySetterCallback setter =
4017        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
4018    LOG(isolate,
4019        ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
4020    result = args.Call(setter, index, v8::Utils::ToLocal(value));
4021  } else {
4022    Handle<Name> name = it->name();
4023    DCHECK(!name->IsPrivate());
4024
4025    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
4026      return Just(false);
4027    }
4028
4029    v8::GenericNamedPropertySetterCallback setter =
4030        v8::ToCData<v8::GenericNamedPropertySetterCallback>(
4031            interceptor->setter());
4032    LOG(it->isolate(),
4033        ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
4034    result =
4035        args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
4036  }
4037
4038  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
4039  if (result.IsEmpty()) return Just(false);
4040#ifdef DEBUG
4041  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
4042  result_internal->VerifyApiCallResultType();
4043#endif
4044  return Just(true);
4045  // TODO(neis): In the future, we may want to actually return the interceptor's
4046  // result, which then should be a boolean.
4047}
4048
4049
4050MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
4051                                        Handle<Name> name, Handle<Object> value,
4052                                        LanguageMode language_mode,
4053                                        StoreFromKeyed store_mode) {
4054  LookupIterator it(object, name);
4055  MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
4056  return value;
4057}
4058
4059
4060Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
4061                                        Handle<Object> value,
4062                                        LanguageMode language_mode,
4063                                        StoreFromKeyed store_mode,
4064                                        bool* found) {
4065  ShouldThrow should_throw =
4066      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4067
4068  // Make sure that the top context does not change when doing callbacks or
4069  // interceptor calls.
4070  AssertNoContextChange ncc(it->isolate());
4071
4072  *found = true;
4073
4074  bool done = false;
4075  for (; it->IsFound(); it->Next()) {
4076    switch (it->state()) {
4077      case LookupIterator::NOT_FOUND:
4078        UNREACHABLE();
4079
4080      case LookupIterator::ACCESS_CHECK:
4081        if (it->HasAccess()) break;
4082        // Check whether it makes sense to reuse the lookup iterator. Here it
4083        // might still call into setters up the prototype chain.
4084        return JSObject::SetPropertyWithFailedAccessCheck(it, value,
4085                                                          should_throw);
4086
4087      case LookupIterator::JSPROXY:
4088        return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
4089                                    value, it->GetReceiver(), language_mode);
4090
4091      case LookupIterator::INTERCEPTOR:
4092        if (it->HolderIsReceiverOrHiddenPrototype()) {
4093          Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value);
4094          if (result.IsNothing() || result.FromJust()) return result;
4095        } else {
4096          Maybe<PropertyAttributes> maybe_attributes =
4097              JSObject::GetPropertyAttributesWithInterceptor(it);
4098          if (!maybe_attributes.IsJust()) return Nothing<bool>();
4099          done = maybe_attributes.FromJust() != ABSENT;
4100          if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
4101            return WriteToReadOnlyProperty(it, value, should_throw);
4102          }
4103        }
4104        break;
4105
4106      case LookupIterator::ACCESSOR: {
4107        if (it->IsReadOnly()) {
4108          return WriteToReadOnlyProperty(it, value, should_throw);
4109        }
4110        Handle<Object> accessors = it->GetAccessors();
4111        if (accessors->IsAccessorInfo() &&
4112            !it->HolderIsReceiverOrHiddenPrototype() &&
4113            AccessorInfo::cast(*accessors)->is_special_data_property()) {
4114          done = true;
4115          break;
4116        }
4117        return SetPropertyWithAccessor(it, value, should_throw);
4118      }
4119      case LookupIterator::INTEGER_INDEXED_EXOTIC:
4120        // TODO(verwaest): We should throw an exception.
4121        return Just(true);
4122
4123      case LookupIterator::DATA:
4124        if (it->IsReadOnly()) {
4125          return WriteToReadOnlyProperty(it, value, should_throw);
4126        }
4127        if (it->HolderIsReceiverOrHiddenPrototype()) {
4128          return SetDataProperty(it, value);
4129        }
4130        done = true;
4131        break;
4132
4133      case LookupIterator::TRANSITION:
4134        done = true;
4135        break;
4136    }
4137
4138    if (done) break;
4139  }
4140
4141  // If the receiver is the JSGlobalObject, the store was contextual. In case
4142  // the property did not exist yet on the global object itself, we have to
4143  // throw a reference error in strict mode.  In sloppy mode, we continue.
4144  if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
4145    it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
4146        MessageTemplate::kNotDefined, it->name()));
4147    return Nothing<bool>();
4148  }
4149
4150  *found = false;
4151  return Nothing<bool>();
4152}
4153
4154
4155Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
4156                                LanguageMode language_mode,
4157                                StoreFromKeyed store_mode) {
4158  ShouldThrow should_throw =
4159      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4160  if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
4161    RETURN_FAILURE(it->isolate(), should_throw,
4162                   NewTypeError(MessageTemplate::kProxyPrivate));
4163  }
4164  bool found = false;
4165  Maybe<bool> result =
4166      SetPropertyInternal(it, value, language_mode, store_mode, &found);
4167  if (found) return result;
4168  return AddDataProperty(it, value, NONE, should_throw, store_mode);
4169}
4170
4171
4172Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
4173                                     LanguageMode language_mode,
4174                                     StoreFromKeyed store_mode) {
4175  ShouldThrow should_throw =
4176      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4177  Isolate* isolate = it->isolate();
4178  if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
4179    RETURN_FAILURE(isolate, should_throw,
4180                   NewTypeError(MessageTemplate::kProxyPrivate));
4181  }
4182
4183  bool found = false;
4184  Maybe<bool> result =
4185      SetPropertyInternal(it, value, language_mode, store_mode, &found);
4186  if (found) return result;
4187
4188  // The property either doesn't exist on the holder or exists there as a data
4189  // property.
4190
4191  if (!it->GetReceiver()->IsJSReceiver()) {
4192    return WriteToReadOnlyProperty(it, value, should_throw);
4193  }
4194  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
4195
4196  LookupIterator::Configuration c = LookupIterator::OWN;
4197  LookupIterator own_lookup =
4198      it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
4199                      : LookupIterator(receiver, it->name(), c);
4200
4201  for (; own_lookup.IsFound(); own_lookup.Next()) {
4202    switch (own_lookup.state()) {
4203      case LookupIterator::ACCESS_CHECK:
4204        if (!own_lookup.HasAccess()) {
4205          return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
4206                                                            should_throw);
4207        }
4208        break;
4209
4210      case LookupIterator::INTEGER_INDEXED_EXOTIC:
4211      case LookupIterator::ACCESSOR:
4212        return RedefineIncompatibleProperty(isolate, it->GetName(), value,
4213                                            should_throw);
4214
4215      case LookupIterator::DATA: {
4216        PropertyDetails details = own_lookup.property_details();
4217        if (details.IsReadOnly()) {
4218          return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
4219        }
4220        return SetDataProperty(&own_lookup, value);
4221      }
4222
4223      case LookupIterator::INTERCEPTOR:
4224      case LookupIterator::JSPROXY: {
4225        PropertyDescriptor desc;
4226        Maybe<bool> owned =
4227            JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
4228        MAYBE_RETURN(owned, Nothing<bool>());
4229        if (!owned.FromJust()) {
4230          return JSReceiver::CreateDataProperty(&own_lookup, value,
4231                                                should_throw);
4232        }
4233        if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
4234            !desc.writable()) {
4235          return RedefineIncompatibleProperty(isolate, it->GetName(), value,
4236                                              should_throw);
4237        }
4238
4239        PropertyDescriptor value_desc;
4240        value_desc.set_value(value);
4241        return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
4242                                             &value_desc, should_throw);
4243      }
4244
4245      case LookupIterator::NOT_FOUND:
4246      case LookupIterator::TRANSITION:
4247        UNREACHABLE();
4248    }
4249  }
4250
4251  return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw,
4252                                   store_mode);
4253}
4254
4255
4256MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it,
4257                                               LanguageMode language_mode) {
4258  if (is_strong(language_mode)) {
4259    THROW_NEW_ERROR(it->isolate(),
4260                    NewTypeError(MessageTemplate::kStrongPropertyAccess,
4261                                 it->GetName(), it->GetReceiver()),
4262                    Object);
4263  }
4264  return it->isolate()->factory()->undefined_value();
4265}
4266
4267MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
4268                                               Handle<Object> receiver,
4269                                               Handle<Object> name,
4270                                               LanguageMode language_mode) {
4271  if (is_strong(language_mode)) {
4272    THROW_NEW_ERROR(
4273        isolate,
4274        NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver),
4275        Object);
4276  }
4277  return isolate->factory()->undefined_value();
4278}
4279
4280
4281Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
4282                                         Handle<Object> receiver,
4283                                         Handle<Object> name,
4284                                         Handle<Object> value,
4285                                         ShouldThrow should_throw) {
4286  RETURN_FAILURE(
4287      isolate, should_throw,
4288      NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
4289                   Object::TypeOf(isolate, receiver), receiver));
4290}
4291
4292
4293Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
4294                                            Handle<Object> value,
4295                                            ShouldThrow should_throw) {
4296  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
4297                                 it->GetName(), value, should_throw);
4298}
4299
4300
4301Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
4302                                            Handle<Object> receiver,
4303                                            Handle<Object> name,
4304                                            Handle<Object> value,
4305                                            ShouldThrow should_throw) {
4306  RETURN_FAILURE(isolate, should_throw,
4307                 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
4308                              Object::TypeOf(isolate, receiver), receiver));
4309}
4310
4311
4312Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
4313                                                 Handle<Object> name,
4314                                                 Handle<Object> value,
4315                                                 ShouldThrow should_throw) {
4316  RETURN_FAILURE(isolate, should_throw,
4317                 NewTypeError(MessageTemplate::kRedefineDisallowed, name));
4318}
4319
4320
4321Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
4322  // Proxies are handled elsewhere. Other non-JSObjects cannot have own
4323  // properties.
4324  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
4325
4326  // Store on the holder which may be hidden behind the receiver.
4327  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
4328
4329  // Old value for the observation change record.
4330  // Fetch before transforming the object since the encoding may become
4331  // incompatible with what's cached in |it|.
4332  bool is_observed = receiver->map()->is_observed() &&
4333                     (it->IsElement() ||
4334                      !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4335  MaybeHandle<Object> maybe_old;
4336  if (is_observed) maybe_old = it->GetDataValue();
4337
4338  Handle<Object> to_assign = value;
4339  // Convert the incoming value to a number for storing into typed arrays.
4340  if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
4341    if (!value->IsNumber() && !value->IsUndefined()) {
4342      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4343          it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
4344      // ToNumber above might modify the receiver, causing the cached
4345      // holder_map to mismatch the actual holder->map() after this point.
4346      // Reload the map to be in consistent state. Other cached state cannot
4347      // have been invalidated since typed array elements cannot be reconfigured
4348      // in any way.
4349      it->ReloadHolderMap();
4350
4351      // We have to recheck the length. However, it can only change if the
4352      // underlying buffer was neutered, so just check that.
4353      if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
4354        return Just(true);
4355        // TODO(neis): According to the spec, this should throw a TypeError.
4356      }
4357    }
4358  }
4359
4360  // Possibly migrate to the most up-to-date map that will be able to store
4361  // |value| under it->name().
4362  it->PrepareForDataProperty(to_assign);
4363
4364  // Write the property value.
4365  it->WriteDataValue(to_assign);
4366
4367  // Send the change record if there are observers.
4368  if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
4369    RETURN_ON_EXCEPTION_VALUE(
4370        it->isolate(),
4371        JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(),
4372                                      maybe_old.ToHandleChecked()),
4373        Nothing<bool>());
4374  }
4375
4376#if VERIFY_HEAP
4377  if (FLAG_verify_heap) {
4378    receiver->JSObjectVerify();
4379  }
4380#endif
4381  return Just(true);
4382}
4383
4384
4385MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
4386    Handle<JSArray> object) {
4387  Isolate* isolate = object->GetIsolate();
4388  HandleScope scope(isolate);
4389  Handle<Object> args[] = {object};
4390
4391  return Execution::Call(
4392      isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
4393      isolate->factory()->undefined_value(), arraysize(args), args);
4394}
4395
4396
4397MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
4398    Handle<JSArray> object) {
4399  Isolate* isolate = object->GetIsolate();
4400  HandleScope scope(isolate);
4401  Handle<Object> args[] = {object};
4402
4403  return Execution::Call(
4404      isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
4405      isolate->factory()->undefined_value(), arraysize(args), args);
4406}
4407
4408
4409MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
4410    Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
4411    uint32_t add_count) {
4412  Isolate* isolate = object->GetIsolate();
4413  HandleScope scope(isolate);
4414  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
4415  Handle<Object> add_count_object =
4416      isolate->factory()->NewNumberFromUint(add_count);
4417
4418  Handle<Object> args[] = {object, index_object, deleted, add_count_object};
4419
4420  return Execution::Call(
4421      isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
4422      isolate->factory()->undefined_value(), arraysize(args), args);
4423}
4424
4425
4426Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
4427                                    PropertyAttributes attributes,
4428                                    ShouldThrow should_throw,
4429                                    StoreFromKeyed store_mode) {
4430  DCHECK(!it->GetReceiver()->IsJSProxy());
4431  if (!it->GetReceiver()->IsJSObject()) {
4432    return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
4433                                value, should_throw);
4434  }
4435
4436  DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
4437
4438  Handle<JSObject> receiver = it->GetStoreTarget();
4439
4440  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
4441  // instead. If the prototype is Null, the proxy is detached.
4442  if (receiver->IsJSGlobalProxy()) return Just(true);
4443
4444  Isolate* isolate = it->isolate();
4445
4446  if (!receiver->map()->is_extensible() &&
4447      (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
4448    RETURN_FAILURE(
4449        isolate, should_throw,
4450        NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
4451  }
4452
4453  if (it->IsElement()) {
4454    if (receiver->IsJSArray()) {
4455      Handle<JSArray> array = Handle<JSArray>::cast(receiver);
4456      if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
4457        RETURN_FAILURE(array->GetIsolate(), should_throw,
4458                       NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
4459                                    isolate->factory()->length_string(),
4460                                    Object::TypeOf(isolate, array), array));
4461      }
4462
4463      if (FLAG_trace_external_array_abuse &&
4464          array->HasFixedTypedArrayElements()) {
4465        CheckArrayAbuse(array, "typed elements write", it->index(), true);
4466      }
4467
4468      if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
4469        CheckArrayAbuse(array, "elements write", it->index(), false);
4470      }
4471    }
4472
4473    Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
4474                                                  attributes, should_throw);
4475    JSObject::ValidateElements(receiver);
4476    return result;
4477  } else {
4478    // Migrate to the most up-to-date map that will be able to store |value|
4479    // under it->name() with |attributes|.
4480    it->PrepareTransitionToDataProperty(value, attributes, store_mode);
4481    DCHECK_EQ(LookupIterator::TRANSITION, it->state());
4482    it->ApplyTransitionToDataProperty();
4483
4484    // TODO(verwaest): Encapsulate dictionary handling better.
4485    if (receiver->map()->is_dictionary_map()) {
4486      // TODO(verwaest): Probably should ensure this is done beforehand.
4487      it->InternalizeName();
4488      // TODO(dcarney): just populate TransitionPropertyCell here?
4489      JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
4490    } else {
4491      // Write the property value.
4492      it->WriteDataValue(value);
4493    }
4494
4495    // Send the change record if there are observers.
4496    if (receiver->map()->is_observed() &&
4497        !isolate->IsInternallyUsedPropertyName(it->name())) {
4498      RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord(
4499                                             receiver, "add", it->name(),
4500                                             it->factory()->the_hole_value()),
4501                                Nothing<bool>());
4502    }
4503#if VERIFY_HEAP
4504    if (FLAG_verify_heap) {
4505      receiver->JSObjectVerify();
4506    }
4507#endif
4508  }
4509
4510  return Just(true);
4511}
4512
4513
4514void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
4515  // Only supports adding slack to owned descriptors.
4516  DCHECK(map->owns_descriptors());
4517
4518  Handle<DescriptorArray> descriptors(map->instance_descriptors());
4519  int old_size = map->NumberOfOwnDescriptors();
4520  if (slack <= descriptors->NumberOfSlackDescriptors()) return;
4521
4522  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
4523      descriptors, old_size, slack);
4524
4525  DisallowHeapAllocation no_allocation;
4526  // The descriptors are still the same, so keep the layout descriptor.
4527  LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
4528
4529  if (old_size == 0) {
4530    map->UpdateDescriptors(*new_descriptors, layout_descriptor);
4531    return;
4532  }
4533
4534  // If the source descriptors had an enum cache we copy it. This ensures
4535  // that the maps to which we push the new descriptor array back can rely
4536  // on a cache always being available once it is set. If the map has more
4537  // enumerated descriptors than available in the original cache, the cache
4538  // will be lazily replaced by the extended cache when needed.
4539  if (descriptors->HasEnumCache()) {
4540    new_descriptors->CopyEnumCacheFrom(*descriptors);
4541  }
4542
4543  // Replace descriptors by new_descriptors in all maps that share it.
4544  map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
4545
4546  Map* current = *map;
4547  while (current->instance_descriptors() == *descriptors) {
4548    Object* next = current->GetBackPointer();
4549    if (next->IsUndefined()) break;  // Stop overwriting at initial map.
4550    current->UpdateDescriptors(*new_descriptors, layout_descriptor);
4551    current = Map::cast(next);
4552  }
4553  map->UpdateDescriptors(*new_descriptors, layout_descriptor);
4554}
4555
4556
4557template<class T>
4558static int AppendUniqueCallbacks(NeanderArray* callbacks,
4559                                 Handle<typename T::Array> array,
4560                                 int valid_descriptors) {
4561  int nof_callbacks = callbacks->length();
4562
4563  Isolate* isolate = array->GetIsolate();
4564  // Ensure the keys are unique names before writing them into the
4565  // instance descriptor. Since it may cause a GC, it has to be done before we
4566  // temporarily put the heap in an invalid state while appending descriptors.
4567  for (int i = 0; i < nof_callbacks; ++i) {
4568    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
4569    if (entry->name()->IsUniqueName()) continue;
4570    Handle<String> key =
4571        isolate->factory()->InternalizeString(
4572            Handle<String>(String::cast(entry->name())));
4573    entry->set_name(*key);
4574  }
4575
4576  // Fill in new callback descriptors.  Process the callbacks from
4577  // back to front so that the last callback with a given name takes
4578  // precedence over previously added callbacks with that name.
4579  for (int i = nof_callbacks - 1; i >= 0; i--) {
4580    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
4581    Handle<Name> key(Name::cast(entry->name()));
4582    // Check if a descriptor with this name already exists before writing.
4583    if (!T::Contains(key, entry, valid_descriptors, array)) {
4584      T::Insert(key, entry, valid_descriptors, array);
4585      valid_descriptors++;
4586    }
4587  }
4588
4589  return valid_descriptors;
4590}
4591
4592struct DescriptorArrayAppender {
4593  typedef DescriptorArray Array;
4594  static bool Contains(Handle<Name> key,
4595                       Handle<AccessorInfo> entry,
4596                       int valid_descriptors,
4597                       Handle<DescriptorArray> array) {
4598    DisallowHeapAllocation no_gc;
4599    return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
4600  }
4601  static void Insert(Handle<Name> key,
4602                     Handle<AccessorInfo> entry,
4603                     int valid_descriptors,
4604                     Handle<DescriptorArray> array) {
4605    DisallowHeapAllocation no_gc;
4606    AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
4607    array->Append(&desc);
4608  }
4609};
4610
4611
4612struct FixedArrayAppender {
4613  typedef FixedArray Array;
4614  static bool Contains(Handle<Name> key,
4615                       Handle<AccessorInfo> entry,
4616                       int valid_descriptors,
4617                       Handle<FixedArray> array) {
4618    for (int i = 0; i < valid_descriptors; i++) {
4619      if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
4620    }
4621    return false;
4622  }
4623  static void Insert(Handle<Name> key,
4624                     Handle<AccessorInfo> entry,
4625                     int valid_descriptors,
4626                     Handle<FixedArray> array) {
4627    DisallowHeapAllocation no_gc;
4628    array->set(valid_descriptors, *entry);
4629  }
4630};
4631
4632
4633void Map::AppendCallbackDescriptors(Handle<Map> map,
4634                                    Handle<Object> descriptors) {
4635  int nof = map->NumberOfOwnDescriptors();
4636  Handle<DescriptorArray> array(map->instance_descriptors());
4637  NeanderArray callbacks(descriptors);
4638  DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
4639  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
4640  map->SetNumberOfOwnDescriptors(nof);
4641}
4642
4643
4644int AccessorInfo::AppendUnique(Handle<Object> descriptors,
4645                               Handle<FixedArray> array,
4646                               int valid_descriptors) {
4647  NeanderArray callbacks(descriptors);
4648  DCHECK(array->length() >= callbacks.length() + valid_descriptors);
4649  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
4650                                                   array,
4651                                                   valid_descriptors);
4652}
4653
4654
4655static bool ContainsMap(MapHandleList* maps, Map* map) {
4656  DCHECK_NOT_NULL(map);
4657  for (int i = 0; i < maps->length(); ++i) {
4658    if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
4659  }
4660  return false;
4661}
4662
4663
4664Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
4665                                     MapHandleList* candidates) {
4666  ElementsKind kind = map->elements_kind();
4667  bool packed = IsFastPackedElementsKind(kind);
4668
4669  Map* transition = nullptr;
4670  if (IsTransitionableFastElementsKind(kind)) {
4671    for (Map* current = map->ElementsTransitionMap();
4672         current != nullptr && current->has_fast_elements();
4673         current = current->ElementsTransitionMap()) {
4674      if (ContainsMap(candidates, current) &&
4675          (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
4676        transition = current;
4677        packed = packed && IsFastPackedElementsKind(current->elements_kind());
4678      }
4679    }
4680  }
4681  return transition == nullptr ? Handle<Map>() : handle(transition);
4682}
4683
4684
4685static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
4686  Map* current_map = map;
4687
4688  ElementsKind kind = map->elements_kind();
4689  while (kind != to_kind) {
4690    Map* next_map = current_map->ElementsTransitionMap();
4691    if (next_map == nullptr) return current_map;
4692    kind = next_map->elements_kind();
4693    current_map = next_map;
4694  }
4695
4696  DCHECK_EQ(to_kind, current_map->elements_kind());
4697  return current_map;
4698}
4699
4700
4701Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
4702  Map* to_map = FindClosestElementsTransition(this, to_kind);
4703  if (to_map->elements_kind() == to_kind) return to_map;
4704  return nullptr;
4705}
4706
4707
4708bool Map::IsMapInArrayPrototypeChain() {
4709  Isolate* isolate = GetIsolate();
4710  if (isolate->initial_array_prototype()->map() == this) {
4711    return true;
4712  }
4713
4714  if (isolate->initial_object_prototype()->map() == this) {
4715    return true;
4716  }
4717
4718  return false;
4719}
4720
4721
4722Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
4723  Isolate* isolate = map->GetIsolate();
4724  if (map->weak_cell_cache()->IsWeakCell()) {
4725    return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
4726  }
4727  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
4728  map->set_weak_cell_cache(*weak_cell);
4729  return weak_cell;
4730}
4731
4732
4733static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
4734                                                 ElementsKind to_kind) {
4735  DCHECK(IsTransitionElementsKind(map->elements_kind()));
4736
4737  Handle<Map> current_map = map;
4738
4739  ElementsKind kind = map->elements_kind();
4740  TransitionFlag flag;
4741  if (map->is_prototype_map()) {
4742    flag = OMIT_TRANSITION;
4743  } else {
4744    flag = INSERT_TRANSITION;
4745    if (IsFastElementsKind(kind)) {
4746      while (kind != to_kind && !IsTerminalElementsKind(kind)) {
4747        kind = GetNextTransitionElementsKind(kind);
4748        current_map = Map::CopyAsElementsKind(current_map, kind, flag);
4749      }
4750    }
4751  }
4752
4753  // In case we are exiting the fast elements kind system, just add the map in
4754  // the end.
4755  if (kind != to_kind) {
4756    current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
4757  }
4758
4759  DCHECK(current_map->elements_kind() == to_kind);
4760  return current_map;
4761}
4762
4763
4764Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
4765                                      ElementsKind to_kind) {
4766  ElementsKind from_kind = map->elements_kind();
4767  if (from_kind == to_kind) return map;
4768
4769  Isolate* isolate = map->GetIsolate();
4770  Context* native_context = isolate->context()->native_context();
4771  if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
4772    if (*map == native_context->fast_aliased_arguments_map()) {
4773      DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
4774      return handle(native_context->slow_aliased_arguments_map());
4775    }
4776  } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
4777    if (*map == native_context->slow_aliased_arguments_map()) {
4778      DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
4779      return handle(native_context->fast_aliased_arguments_map());
4780    }
4781  } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
4782    // Reuse map transitions for JSArrays.
4783    DisallowHeapAllocation no_gc;
4784    Strength strength = map->is_strong() ? Strength::STRONG : Strength::WEAK;
4785    if (native_context->get(Context::ArrayMapIndex(from_kind, strength)) ==
4786        *map) {
4787      Object* maybe_transitioned_map =
4788          native_context->get(Context::ArrayMapIndex(to_kind, strength));
4789      if (maybe_transitioned_map->IsMap()) {
4790        return handle(Map::cast(maybe_transitioned_map), isolate);
4791      }
4792    }
4793  }
4794
4795  DCHECK(!map->IsUndefined());
4796  // Check if we can go back in the elements kind transition chain.
4797  if (IsHoleyElementsKind(from_kind) &&
4798      to_kind == GetPackedElementsKind(from_kind) &&
4799      map->GetBackPointer()->IsMap() &&
4800      Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
4801    return handle(Map::cast(map->GetBackPointer()));
4802  }
4803
4804  bool allow_store_transition = IsTransitionElementsKind(from_kind);
4805  // Only store fast element maps in ascending generality.
4806  if (IsFastElementsKind(to_kind)) {
4807    allow_store_transition =
4808        allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
4809        IsMoreGeneralElementsKindTransition(from_kind, to_kind);
4810  }
4811
4812  if (!allow_store_transition) {
4813    return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
4814  }
4815
4816  return Map::AsElementsKind(map, to_kind);
4817}
4818
4819
4820// static
4821Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
4822  Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
4823
4824  if (closest_map->elements_kind() == kind) {
4825    return closest_map;
4826  }
4827
4828  return AddMissingElementsTransitions(closest_map, kind);
4829}
4830
4831
4832Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
4833                                               ElementsKind to_kind) {
4834  Handle<Map> map(object->map());
4835  return Map::TransitionElementsTo(map, to_kind);
4836}
4837
4838
4839void JSProxy::Revoke(Handle<JSProxy> proxy) {
4840  Isolate* isolate = proxy->GetIsolate();
4841  if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value());
4842  DCHECK(proxy->IsRevoked());
4843}
4844
4845
4846Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
4847                                 Handle<Name> name) {
4848  DCHECK(!name->IsPrivate());
4849  STACK_CHECK(Nothing<bool>());
4850  // 1. (Assert)
4851  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
4852  Handle<Object> handler(proxy->handler(), isolate);
4853  // 3. If handler is null, throw a TypeError exception.
4854  // 4. Assert: Type(handler) is Object.
4855  if (proxy->IsRevoked()) {
4856    isolate->Throw(*isolate->factory()->NewTypeError(
4857        MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
4858    return Nothing<bool>();
4859  }
4860  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
4861  Handle<JSReceiver> target(proxy->target(), isolate);
4862  // 6. Let trap be ? GetMethod(handler, "has").
4863  Handle<Object> trap;
4864  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4865      isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
4866                                       isolate->factory()->has_string()),
4867      Nothing<bool>());
4868  // 7. If trap is undefined, then
4869  if (trap->IsUndefined()) {
4870    // 7a. Return target.[[HasProperty]](P).
4871    return JSReceiver::HasProperty(target, name);
4872  }
4873  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)).
4874  Handle<Object> trap_result_obj;
4875  Handle<Object> args[] = {target, name};
4876  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4877      isolate, trap_result_obj,
4878      Execution::Call(isolate, trap, handler, arraysize(args), args),
4879      Nothing<bool>());
4880  bool boolean_trap_result = trap_result_obj->BooleanValue();
4881  // 9. If booleanTrapResult is false, then:
4882  if (!boolean_trap_result) {
4883    // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
4884    PropertyDescriptor target_desc;
4885    Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor(
4886        isolate, target, name, &target_desc);
4887    MAYBE_RETURN(target_found, Nothing<bool>());
4888    // 9b. If targetDesc is not undefined, then:
4889    if (target_found.FromJust()) {
4890      // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
4891      //       exception.
4892      if (!target_desc.configurable()) {
4893        isolate->Throw(*isolate->factory()->NewTypeError(
4894            MessageTemplate::kProxyHasNonConfigurable, name));
4895        return Nothing<bool>();
4896      }
4897      // 9b ii. Let extensibleTarget be ? IsExtensible(target).
4898      Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
4899      MAYBE_RETURN(extensible_target, Nothing<bool>());
4900      // 9b iii. If extensibleTarget is false, throw a TypeError exception.
4901      if (!extensible_target.FromJust()) {
4902        isolate->Throw(*isolate->factory()->NewTypeError(
4903            MessageTemplate::kProxyHasNonExtensible, name));
4904        return Nothing<bool>();
4905      }
4906    }
4907  }
4908  // 10. Return booleanTrapResult.
4909  return Just(boolean_trap_result);
4910}
4911
4912
4913Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
4914                                 Handle<Object> value, Handle<Object> receiver,
4915                                 LanguageMode language_mode) {
4916  DCHECK(!name->IsPrivate());
4917  Isolate* isolate = proxy->GetIsolate();
4918  STACK_CHECK(Nothing<bool>());
4919  Factory* factory = isolate->factory();
4920  Handle<String> trap_name = factory->set_string();
4921  ShouldThrow should_throw =
4922      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4923
4924  if (proxy->IsRevoked()) {
4925    isolate->Throw(
4926        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
4927    return Nothing<bool>();
4928  }
4929  Handle<JSReceiver> target(proxy->target(), isolate);
4930  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
4931
4932  Handle<Object> trap;
4933  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4934      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
4935  if (trap->IsUndefined()) {
4936    LookupIterator it =
4937        LookupIterator::PropertyOrElement(isolate, receiver, name, target);
4938    return Object::SetSuperProperty(&it, value, language_mode,
4939                                    Object::MAY_BE_STORE_FROM_KEYED);
4940  }
4941
4942  Handle<Object> trap_result;
4943  Handle<Object> args[] = {target, name, value, receiver};
4944  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4945      isolate, trap_result,
4946      Execution::Call(isolate, trap, handler, arraysize(args), args),
4947      Nothing<bool>());
4948  if (!trap_result->BooleanValue()) {
4949    RETURN_FAILURE(isolate, should_throw,
4950                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
4951                                trap_name, name));
4952  }
4953
4954  // Enforce the invariant.
4955  PropertyDescriptor target_desc;
4956  Maybe<bool> owned =
4957      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
4958  MAYBE_RETURN(owned, Nothing<bool>());
4959  if (owned.FromJust()) {
4960    bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
4961                        !target_desc.configurable() &&
4962                        !target_desc.writable() &&
4963                        !value->SameValue(*target_desc.value());
4964    if (inconsistent) {
4965      isolate->Throw(*isolate->factory()->NewTypeError(
4966          MessageTemplate::kProxySetFrozenData, name));
4967      return Nothing<bool>();
4968    }
4969    inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
4970                   !target_desc.configurable() &&
4971                   target_desc.set()->IsUndefined();
4972    if (inconsistent) {
4973      isolate->Throw(*isolate->factory()->NewTypeError(
4974          MessageTemplate::kProxySetFrozenAccessor, name));
4975      return Nothing<bool>();
4976    }
4977  }
4978  return Just(true);
4979}
4980
4981
4982Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
4983                                             Handle<Name> name,
4984                                             LanguageMode language_mode) {
4985  DCHECK(!name->IsPrivate());
4986  ShouldThrow should_throw =
4987      is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
4988  Isolate* isolate = proxy->GetIsolate();
4989  STACK_CHECK(Nothing<bool>());
4990  Factory* factory = isolate->factory();
4991  Handle<String> trap_name = factory->deleteProperty_string();
4992
4993  if (proxy->IsRevoked()) {
4994    isolate->Throw(
4995        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
4996    return Nothing<bool>();
4997  }
4998  Handle<JSReceiver> target(proxy->target(), isolate);
4999  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
5000
5001  Handle<Object> trap;
5002  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5003      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
5004  if (trap->IsUndefined()) {
5005    return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
5006  }
5007
5008  Handle<Object> trap_result;
5009  Handle<Object> args[] = {target, name};
5010  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5011      isolate, trap_result,
5012      Execution::Call(isolate, trap, handler, arraysize(args), args),
5013      Nothing<bool>());
5014  if (!trap_result->BooleanValue()) {
5015    RETURN_FAILURE(isolate, should_throw,
5016                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
5017                                trap_name, name));
5018  }
5019
5020  // Enforce the invariant.
5021  PropertyDescriptor target_desc;
5022  Maybe<bool> owned =
5023      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
5024  MAYBE_RETURN(owned, Nothing<bool>());
5025  if (owned.FromJust() && !target_desc.configurable()) {
5026    isolate->Throw(*factory->NewTypeError(
5027        MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
5028    return Nothing<bool>();
5029  }
5030  return Just(true);
5031}
5032
5033
5034// static
5035MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
5036                                  Handle<Object> handler) {
5037  if (!target->IsJSReceiver()) {
5038    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
5039                    JSProxy);
5040  }
5041  if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
5042    THROW_NEW_ERROR(isolate,
5043                    NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
5044                    JSProxy);
5045  }
5046  if (!handler->IsJSReceiver()) {
5047    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
5048                    JSProxy);
5049  }
5050  if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
5051    THROW_NEW_ERROR(isolate,
5052                    NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
5053                    JSProxy);
5054  }
5055  return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
5056                                        Handle<JSReceiver>::cast(handler));
5057}
5058
5059
5060// static
5061MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
5062  DCHECK(proxy->map()->is_constructor());
5063  if (proxy->IsRevoked()) {
5064    THROW_NEW_ERROR(proxy->GetIsolate(),
5065                    NewTypeError(MessageTemplate::kProxyRevoked), Context);
5066  }
5067  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()));
5068  return JSReceiver::GetFunctionRealm(target);
5069}
5070
5071
5072// static
5073MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
5074    Handle<JSBoundFunction> function) {
5075  DCHECK(function->map()->is_constructor());
5076  return JSReceiver::GetFunctionRealm(
5077      handle(function->bound_target_function()));
5078}
5079
5080
5081// static
5082Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
5083  DCHECK(function->map()->is_constructor());
5084  return handle(function->context()->native_context());
5085}
5086
5087
5088// static
5089MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
5090  DCHECK(object->map()->is_constructor());
5091  DCHECK(!object->IsJSFunction());
5092  return handle(object->GetCreationContext());
5093}
5094
5095
5096// static
5097MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
5098  if (receiver->IsJSProxy()) {
5099    return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
5100  }
5101
5102  if (receiver->IsJSFunction()) {
5103    return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
5104  }
5105
5106  if (receiver->IsJSBoundFunction()) {
5107    return JSBoundFunction::GetFunctionRealm(
5108        Handle<JSBoundFunction>::cast(receiver));
5109  }
5110
5111  return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
5112}
5113
5114
5115Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
5116  Isolate* isolate = it->isolate();
5117  HandleScope scope(isolate);
5118  PropertyDescriptor desc;
5119  Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
5120      isolate, it->GetHolder<JSProxy>(), it->GetName(), &desc);
5121  MAYBE_RETURN(found, Nothing<PropertyAttributes>());
5122  if (!found.FromJust()) return Just(ABSENT);
5123  return Just(desc.ToAttributes());
5124}
5125
5126
5127void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
5128  DCHECK(object->map()->GetInObjectProperties() ==
5129         map->GetInObjectProperties());
5130  ElementsKind obj_kind = object->map()->elements_kind();
5131  ElementsKind map_kind = map->elements_kind();
5132  if (map_kind != obj_kind) {
5133    ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
5134    if (IsDictionaryElementsKind(obj_kind)) {
5135      to_kind = obj_kind;
5136    }
5137    if (IsDictionaryElementsKind(to_kind)) {
5138      NormalizeElements(object);
5139    } else {
5140      TransitionElementsKind(object, to_kind);
5141    }
5142    map = Map::AsElementsKind(map, to_kind);
5143  }
5144  JSObject::MigrateToMap(object, map);
5145}
5146
5147
5148void JSObject::MigrateInstance(Handle<JSObject> object) {
5149  Handle<Map> original_map(object->map());
5150  Handle<Map> map = Map::Update(original_map);
5151  map->set_migration_target(true);
5152  MigrateToMap(object, map);
5153  if (FLAG_trace_migration) {
5154    object->PrintInstanceMigration(stdout, *original_map, *map);
5155  }
5156#if VERIFY_HEAP
5157  if (FLAG_verify_heap) {
5158    object->JSObjectVerify();
5159  }
5160#endif
5161}
5162
5163
5164// static
5165bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
5166  Isolate* isolate = object->GetIsolate();
5167  DisallowDeoptimization no_deoptimization(isolate);
5168  Handle<Map> original_map(object->map(), isolate);
5169  Handle<Map> new_map;
5170  if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
5171    return false;
5172  }
5173  JSObject::MigrateToMap(object, new_map);
5174  if (FLAG_trace_migration) {
5175    object->PrintInstanceMigration(stdout, *original_map, object->map());
5176  }
5177#if VERIFY_HEAP
5178  if (FLAG_verify_heap) {
5179    object->JSObjectVerify();
5180  }
5181#endif
5182  return true;
5183}
5184
5185
5186void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
5187                           Handle<Object> value,
5188                           PropertyAttributes attributes) {
5189  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
5190  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
5191#ifdef DEBUG
5192  uint32_t index;
5193  DCHECK(!object->IsJSProxy());
5194  DCHECK(!name->AsArrayIndex(&index));
5195  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5196  DCHECK(maybe.IsJust());
5197  DCHECK(!it.IsFound());
5198  DCHECK(object->map()->is_extensible() ||
5199         it.isolate()->IsInternallyUsedPropertyName(name));
5200#endif
5201  CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
5202                        CERTAINLY_NOT_STORE_FROM_KEYED)
5203            .IsJust());
5204}
5205
5206
5207// static
5208void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
5209  Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr);
5210  info->set_setter(*object);
5211}
5212
5213
5214// Reconfigures a property to a data property with attributes, even if it is not
5215// reconfigurable.
5216// Requires a LookupIterator that does not look at the prototype chain beyond
5217// hidden prototypes.
5218MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
5219    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5220    ExecutableAccessorInfoHandling handling) {
5221  MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
5222      it, value, attributes, THROW_ON_ERROR, handling));
5223  return value;
5224}
5225
5226
5227Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
5228    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5229    ShouldThrow should_throw, ExecutableAccessorInfoHandling handling) {
5230  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
5231  bool is_observed = object->map()->is_observed() &&
5232                     (it->IsElement() ||
5233                      !it->isolate()->IsInternallyUsedPropertyName(it->name()));
5234
5235  for (; it->IsFound(); it->Next()) {
5236    switch (it->state()) {
5237      case LookupIterator::JSPROXY:
5238      case LookupIterator::NOT_FOUND:
5239      case LookupIterator::TRANSITION:
5240        UNREACHABLE();
5241
5242      case LookupIterator::ACCESS_CHECK:
5243        if (!it->HasAccess()) {
5244          it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
5245          RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
5246          return Just(true);
5247        }
5248        break;
5249
5250      // If there's an interceptor, try to store the property with the
5251      // interceptor.
5252      // In case of success, the attributes will have been reset to the default
5253      // attributes of the interceptor, rather than the incoming attributes.
5254      //
5255      // TODO(verwaest): JSProxy afterwards verify the attributes that the
5256      // JSProxy claims it has, and verifies that they are compatible. If not,
5257      // they throw. Here we should do the same.
5258      case LookupIterator::INTERCEPTOR:
5259        if (handling == DONT_FORCE_FIELD) {
5260          Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value);
5261          if (result.IsNothing() || result.FromJust()) return result;
5262        }
5263        break;
5264
5265      case LookupIterator::ACCESSOR: {
5266        Handle<Object> accessors = it->GetAccessors();
5267
5268        // Special handling for ExecutableAccessorInfo, which behaves like a
5269        // data property.
5270        if (accessors->IsExecutableAccessorInfo() &&
5271            handling == DONT_FORCE_FIELD) {
5272          PropertyDetails details = it->property_details();
5273          // Ensure the context isn't changed after calling into accessors.
5274          AssertNoContextChange ncc(it->isolate());
5275
5276          Maybe<bool> result =
5277              JSObject::SetPropertyWithAccessor(it, value, should_throw);
5278          if (result.IsNothing() || !result.FromJust()) return result;
5279
5280          if (details.attributes() == attributes) return Just(true);
5281
5282          // Reconfigure the accessor if attributes mismatch.
5283          Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
5284              it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
5285          new_data->set_property_attributes(attributes);
5286          // By clearing the setter we don't have to introduce a lookup to
5287          // the setter, simply make it unavailable to reflect the
5288          // attributes.
5289          if (attributes & READ_ONLY) {
5290            ExecutableAccessorInfo::ClearSetter(new_data);
5291          }
5292
5293          it->TransitionToAccessorPair(new_data, attributes);
5294        } else {
5295          it->ReconfigureDataProperty(value, attributes);
5296        }
5297
5298        if (is_observed) {
5299          RETURN_ON_EXCEPTION_VALUE(
5300              it->isolate(),
5301              EnqueueChangeRecord(object, "reconfigure", it->GetName(),
5302                                  it->factory()->the_hole_value()),
5303              Nothing<bool>());
5304        }
5305
5306        return Just(true);
5307      }
5308      case LookupIterator::INTEGER_INDEXED_EXOTIC:
5309        return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
5310                                            should_throw);
5311
5312      case LookupIterator::DATA: {
5313        PropertyDetails details = it->property_details();
5314        Handle<Object> old_value = it->factory()->the_hole_value();
5315        // Regular property update if the attributes match.
5316        if (details.attributes() == attributes) {
5317          return SetDataProperty(it, value);
5318        }
5319
5320        // Special case: properties of typed arrays cannot be reconfigured to
5321        // non-writable nor to non-enumerable.
5322        if (it->IsElement() && object->HasFixedTypedArrayElements()) {
5323          return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
5324                                              value, should_throw);
5325        }
5326
5327        // Reconfigure the data property if the attributes mismatch.
5328        if (is_observed) old_value = it->GetDataValue();
5329
5330        it->ReconfigureDataProperty(value, attributes);
5331
5332        if (is_observed) {
5333          if (old_value->SameValue(*value)) {
5334            old_value = it->factory()->the_hole_value();
5335          }
5336          RETURN_ON_EXCEPTION_VALUE(
5337              it->isolate(), EnqueueChangeRecord(object, "reconfigure",
5338                                                 it->GetName(), old_value),
5339              Nothing<bool>());
5340        }
5341        return Just(true);
5342      }
5343    }
5344  }
5345
5346  return AddDataProperty(it, value, attributes, should_throw,
5347                         CERTAINLY_NOT_STORE_FROM_KEYED);
5348}
5349
5350
5351MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
5352    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
5353    PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
5354  DCHECK(!value->IsTheHole());
5355  LookupIterator it(object, name, LookupIterator::OWN);
5356  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
5357}
5358
5359
5360MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
5361    Handle<JSObject> object, uint32_t index, Handle<Object> value,
5362    PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
5363  Isolate* isolate = object->GetIsolate();
5364  LookupIterator it(isolate, object, index, LookupIterator::OWN);
5365  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
5366}
5367
5368
5369MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
5370    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
5371    PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
5372  Isolate* isolate = object->GetIsolate();
5373  LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
5374                                                        LookupIterator::OWN);
5375  return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
5376}
5377
5378
5379Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
5380    LookupIterator* it) {
5381  Isolate* isolate = it->isolate();
5382  // Make sure that the top context does not change when doing
5383  // callbacks or interceptor calls.
5384  AssertNoContextChange ncc(isolate);
5385  HandleScope scope(isolate);
5386
5387  Handle<JSObject> holder = it->GetHolder<JSObject>();
5388  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
5389  if (!it->IsElement() && it->name()->IsSymbol() &&
5390      !interceptor->can_intercept_symbols()) {
5391    return Just(ABSENT);
5392  }
5393  PropertyCallbackArguments args(isolate, interceptor->data(),
5394                                 *it->GetReceiver(), *holder);
5395  if (!interceptor->query()->IsUndefined()) {
5396    v8::Local<v8::Integer> result;
5397    if (it->IsElement()) {
5398      uint32_t index = it->index();
5399      v8::IndexedPropertyQueryCallback query =
5400          v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
5401      LOG(isolate,
5402          ApiIndexedPropertyAccess("interceptor-indexed-has", *holder, index));
5403      result = args.Call(query, index);
5404    } else {
5405      Handle<Name> name = it->name();
5406      DCHECK(!name->IsPrivate());
5407      v8::GenericNamedPropertyQueryCallback query =
5408          v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
5409              interceptor->query());
5410      LOG(isolate,
5411          ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
5412      result = args.Call(query, v8::Utils::ToLocal(name));
5413    }
5414    if (!result.IsEmpty()) {
5415      DCHECK(result->IsInt32());
5416      return Just(static_cast<PropertyAttributes>(
5417          result->Int32Value(reinterpret_cast<v8::Isolate*>(isolate)
5418                                 ->GetCurrentContext()).FromJust()));
5419    }
5420  } else if (!interceptor->getter()->IsUndefined()) {
5421    // TODO(verwaest): Use GetPropertyWithInterceptor?
5422    v8::Local<v8::Value> result;
5423    if (it->IsElement()) {
5424      uint32_t index = it->index();
5425      v8::IndexedPropertyGetterCallback getter =
5426          v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
5427      LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-get-has",
5428                                            *holder, index));
5429      result = args.Call(getter, index);
5430    } else {
5431      Handle<Name> name = it->name();
5432      DCHECK(!name->IsPrivate());
5433      v8::GenericNamedPropertyGetterCallback getter =
5434          v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
5435              interceptor->getter());
5436      LOG(isolate,
5437          ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
5438      result = args.Call(getter, v8::Utils::ToLocal(name));
5439    }
5440    if (!result.IsEmpty()) return Just(DONT_ENUM);
5441  }
5442
5443  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
5444  return Just(ABSENT);
5445}
5446
5447
5448Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
5449    LookupIterator* it) {
5450  for (; it->IsFound(); it->Next()) {
5451    switch (it->state()) {
5452      case LookupIterator::NOT_FOUND:
5453      case LookupIterator::TRANSITION:
5454        UNREACHABLE();
5455      case LookupIterator::JSPROXY:
5456        return JSProxy::GetPropertyAttributes(it);
5457      case LookupIterator::INTERCEPTOR: {
5458        Maybe<PropertyAttributes> result =
5459            JSObject::GetPropertyAttributesWithInterceptor(it);
5460        if (!result.IsJust()) return result;
5461        if (result.FromJust() != ABSENT) return result;
5462        break;
5463      }
5464      case LookupIterator::ACCESS_CHECK:
5465        if (it->HasAccess()) break;
5466        return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
5467      case LookupIterator::INTEGER_INDEXED_EXOTIC:
5468        return Just(ABSENT);
5469      case LookupIterator::ACCESSOR:
5470      case LookupIterator::DATA:
5471        return Just(it->property_details().attributes());
5472    }
5473  }
5474  return Just(ABSENT);
5475}
5476
5477
5478Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
5479  Handle<FixedArray> array(
5480      isolate->factory()->NewFixedArray(kEntries, TENURED));
5481  return Handle<NormalizedMapCache>::cast(array);
5482}
5483
5484
5485MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
5486                                         PropertyNormalizationMode mode) {
5487  DisallowHeapAllocation no_gc;
5488  Object* value = FixedArray::get(GetIndex(fast_map));
5489  if (!value->IsMap() ||
5490      !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
5491    return MaybeHandle<Map>();
5492  }
5493  return handle(Map::cast(value));
5494}
5495
5496
5497void NormalizedMapCache::Set(Handle<Map> fast_map,
5498                             Handle<Map> normalized_map) {
5499  DisallowHeapAllocation no_gc;
5500  DCHECK(normalized_map->is_dictionary_map());
5501  FixedArray::set(GetIndex(fast_map), *normalized_map);
5502}
5503
5504
5505void NormalizedMapCache::Clear() {
5506  int entries = length();
5507  for (int i = 0; i != entries; i++) {
5508    set_undefined(i);
5509  }
5510}
5511
5512
5513void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
5514                                    Handle<Name> name,
5515                                    Handle<Code> code) {
5516  Handle<Map> map(object->map());
5517  Map::UpdateCodeCache(map, name, code);
5518}
5519
5520
5521void JSObject::NormalizeProperties(Handle<JSObject> object,
5522                                   PropertyNormalizationMode mode,
5523                                   int expected_additional_properties,
5524                                   const char* reason) {
5525  if (!object->HasFastProperties()) return;
5526
5527  Handle<Map> map(object->map());
5528  Handle<Map> new_map = Map::Normalize(map, mode, reason);
5529
5530  MigrateToMap(object, new_map, expected_additional_properties);
5531}
5532
5533
5534void JSObject::MigrateFastToSlow(Handle<JSObject> object,
5535                                 Handle<Map> new_map,
5536                                 int expected_additional_properties) {
5537  // The global object is always normalized.
5538  DCHECK(!object->IsJSGlobalObject());
5539  // JSGlobalProxy must never be normalized
5540  DCHECK(!object->IsJSGlobalProxy());
5541
5542  Isolate* isolate = object->GetIsolate();
5543  HandleScope scope(isolate);
5544  Handle<Map> map(object->map());
5545
5546  // Allocate new content.
5547  int real_size = map->NumberOfOwnDescriptors();
5548  int property_count = real_size;
5549  if (expected_additional_properties > 0) {
5550    property_count += expected_additional_properties;
5551  } else {
5552    property_count += 2;  // Make space for two more properties.
5553  }
5554  Handle<NameDictionary> dictionary =
5555      NameDictionary::New(isolate, property_count);
5556
5557  Handle<DescriptorArray> descs(map->instance_descriptors());
5558  for (int i = 0; i < real_size; i++) {
5559    PropertyDetails details = descs->GetDetails(i);
5560    Handle<Name> key(descs->GetKey(i));
5561    switch (details.type()) {
5562      case DATA_CONSTANT: {
5563        Handle<Object> value(descs->GetConstant(i), isolate);
5564        PropertyDetails d(details.attributes(), DATA, i + 1,
5565                          PropertyCellType::kNoCell);
5566        dictionary = NameDictionary::Add(dictionary, key, value, d);
5567        break;
5568      }
5569      case DATA: {
5570        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
5571        Handle<Object> value;
5572        if (object->IsUnboxedDoubleField(index)) {
5573          double old_value = object->RawFastDoublePropertyAt(index);
5574          value = isolate->factory()->NewHeapNumber(old_value);
5575        } else {
5576          value = handle(object->RawFastPropertyAt(index), isolate);
5577          if (details.representation().IsDouble()) {
5578            DCHECK(value->IsMutableHeapNumber());
5579            Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
5580            value = isolate->factory()->NewHeapNumber(old->value());
5581          }
5582        }
5583        PropertyDetails d(details.attributes(), DATA, i + 1,
5584                          PropertyCellType::kNoCell);
5585        dictionary = NameDictionary::Add(dictionary, key, value, d);
5586        break;
5587      }
5588      case ACCESSOR: {
5589        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
5590        Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5591        PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
5592                          PropertyCellType::kNoCell);
5593        dictionary = NameDictionary::Add(dictionary, key, value, d);
5594        break;
5595      }
5596      case ACCESSOR_CONSTANT: {
5597        Handle<Object> value(descs->GetCallbacksObject(i), isolate);
5598        PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
5599                          PropertyCellType::kNoCell);
5600        dictionary = NameDictionary::Add(dictionary, key, value, d);
5601        break;
5602      }
5603    }
5604  }
5605
5606  // Copy the next enumeration index from instance descriptor.
5607  dictionary->SetNextEnumerationIndex(real_size + 1);
5608
5609  // From here on we cannot fail and we shouldn't GC anymore.
5610  DisallowHeapAllocation no_allocation;
5611
5612  // Resize the object in the heap if necessary.
5613  int new_instance_size = new_map->instance_size();
5614  int instance_size_delta = map->instance_size() - new_instance_size;
5615  DCHECK(instance_size_delta >= 0);
5616
5617  if (instance_size_delta > 0) {
5618    Heap* heap = isolate->heap();
5619    heap->CreateFillerObjectAt(object->address() + new_instance_size,
5620                               instance_size_delta);
5621    heap->AdjustLiveBytes(*object, -instance_size_delta,
5622                          Heap::CONCURRENT_TO_SWEEPER);
5623  }
5624
5625  // We are storing the new map using release store after creating a filler for
5626  // the left-over space to avoid races with the sweeper thread.
5627  object->synchronized_set_map(*new_map);
5628
5629  object->set_properties(*dictionary);
5630
5631  // Ensure that in-object space of slow-mode object does not contain random
5632  // garbage.
5633  int inobject_properties = new_map->GetInObjectProperties();
5634  for (int i = 0; i < inobject_properties; i++) {
5635    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
5636    object->RawFastPropertyAtPut(index, Smi::FromInt(0));
5637  }
5638
5639  isolate->counters()->props_to_dictionary()->Increment();
5640
5641#ifdef DEBUG
5642  if (FLAG_trace_normalization) {
5643    OFStream os(stdout);
5644    os << "Object properties have been normalized:\n";
5645    object->Print(os);
5646  }
5647#endif
5648}
5649
5650
5651void JSObject::MigrateSlowToFast(Handle<JSObject> object,
5652                                 int unused_property_fields,
5653                                 const char* reason) {
5654  if (object->HasFastProperties()) return;
5655  DCHECK(!object->IsJSGlobalObject());
5656  Isolate* isolate = object->GetIsolate();
5657  Factory* factory = isolate->factory();
5658  Handle<NameDictionary> dictionary(object->property_dictionary());
5659
5660  // Make sure we preserve dictionary representation if there are too many
5661  // descriptors.
5662  int number_of_elements = dictionary->NumberOfElements();
5663  if (number_of_elements > kMaxNumberOfDescriptors) return;
5664
5665  Handle<FixedArray> iteration_order;
5666  if (number_of_elements != dictionary->NextEnumerationIndex()) {
5667    iteration_order =
5668        NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
5669  } else {
5670    iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
5671  }
5672
5673  int instance_descriptor_length = iteration_order->length();
5674  int number_of_fields = 0;
5675
5676  // Compute the length of the instance descriptor.
5677  for (int i = 0; i < instance_descriptor_length; i++) {
5678    int index = Smi::cast(iteration_order->get(i))->value();
5679    DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
5680
5681    Object* value = dictionary->ValueAt(index);
5682    PropertyType type = dictionary->DetailsAt(index).type();
5683    if (type == DATA && !value->IsJSFunction()) {
5684      number_of_fields += 1;
5685    }
5686  }
5687
5688  Handle<Map> old_map(object->map(), isolate);
5689
5690  int inobject_props = old_map->GetInObjectProperties();
5691
5692  // Allocate new map.
5693  Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
5694  new_map->set_dictionary_map(false);
5695
5696  UpdatePrototypeUserRegistration(old_map, new_map, isolate);
5697
5698#if TRACE_MAPS
5699  if (FLAG_trace_maps) {
5700    PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
5701           reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map),
5702           reason);
5703  }
5704#endif
5705
5706  if (instance_descriptor_length == 0) {
5707    DisallowHeapAllocation no_gc;
5708    DCHECK_LE(unused_property_fields, inobject_props);
5709    // Transform the object.
5710    new_map->set_unused_property_fields(inobject_props);
5711    object->synchronized_set_map(*new_map);
5712    object->set_properties(isolate->heap()->empty_fixed_array());
5713    // Check that it really works.
5714    DCHECK(object->HasFastProperties());
5715    return;
5716  }
5717
5718  // Allocate the instance descriptor.
5719  Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
5720      isolate, instance_descriptor_length);
5721
5722  int number_of_allocated_fields =
5723      number_of_fields + unused_property_fields - inobject_props;
5724  if (number_of_allocated_fields < 0) {
5725    // There is enough inobject space for all fields (including unused).
5726    number_of_allocated_fields = 0;
5727    unused_property_fields = inobject_props - number_of_fields;
5728  }
5729
5730  // Allocate the fixed array for the fields.
5731  Handle<FixedArray> fields = factory->NewFixedArray(
5732      number_of_allocated_fields);
5733
5734  // Fill in the instance descriptor and the fields.
5735  int current_offset = 0;
5736  for (int i = 0; i < instance_descriptor_length; i++) {
5737    int index = Smi::cast(iteration_order->get(i))->value();
5738    Object* k = dictionary->KeyAt(index);
5739    DCHECK(dictionary->IsKey(k));
5740    // Dictionary keys are internalized upon insertion.
5741    // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
5742    CHECK(k->IsUniqueName());
5743    Handle<Name> key(Name::cast(k), isolate);
5744
5745    Object* value = dictionary->ValueAt(index);
5746
5747    PropertyDetails details = dictionary->DetailsAt(index);
5748    int enumeration_index = details.dictionary_index();
5749    PropertyType type = details.type();
5750
5751    if (value->IsJSFunction()) {
5752      DataConstantDescriptor d(key, handle(value, isolate),
5753                               details.attributes());
5754      descriptors->Set(enumeration_index - 1, &d);
5755    } else if (type == DATA) {
5756      if (current_offset < inobject_props) {
5757        object->InObjectPropertyAtPut(current_offset, value,
5758                                      UPDATE_WRITE_BARRIER);
5759      } else {
5760        int offset = current_offset - inobject_props;
5761        fields->set(offset, value);
5762      }
5763      DataDescriptor d(key, current_offset, details.attributes(),
5764                       // TODO(verwaest): value->OptimalRepresentation();
5765                       Representation::Tagged());
5766      current_offset += d.GetDetails().field_width_in_words();
5767      descriptors->Set(enumeration_index - 1, &d);
5768    } else if (type == ACCESSOR_CONSTANT) {
5769      AccessorConstantDescriptor d(key, handle(value, isolate),
5770                                   details.attributes());
5771      descriptors->Set(enumeration_index - 1, &d);
5772    } else {
5773      UNREACHABLE();
5774    }
5775  }
5776  DCHECK(current_offset == number_of_fields);
5777
5778  descriptors->Sort();
5779
5780  Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
5781      new_map, descriptors, descriptors->number_of_descriptors());
5782
5783  DisallowHeapAllocation no_gc;
5784  new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
5785  new_map->set_unused_property_fields(unused_property_fields);
5786
5787  // Transform the object.
5788  object->synchronized_set_map(*new_map);
5789
5790  object->set_properties(*fields);
5791  DCHECK(object->IsJSObject());
5792
5793  // Check that it really works.
5794  DCHECK(object->HasFastProperties());
5795}
5796
5797
5798void JSObject::ResetElements(Handle<JSObject> object) {
5799  Isolate* isolate = object->GetIsolate();
5800  CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
5801  if (object->map()->has_dictionary_elements()) {
5802    Handle<SeededNumberDictionary> new_elements =
5803        SeededNumberDictionary::New(isolate, 0);
5804    object->set_elements(*new_elements);
5805  } else {
5806    object->set_elements(object->map()->GetInitialElements());
5807  }
5808}
5809
5810
5811static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
5812    Handle<FixedArrayBase> array, int length,
5813    Handle<SeededNumberDictionary> dictionary, bool used_as_prototype) {
5814  Isolate* isolate = array->GetIsolate();
5815  Factory* factory = isolate->factory();
5816  bool has_double_elements = array->IsFixedDoubleArray();
5817  for (int i = 0; i < length; i++) {
5818    Handle<Object> value;
5819    if (has_double_elements) {
5820      Handle<FixedDoubleArray> double_array =
5821          Handle<FixedDoubleArray>::cast(array);
5822      if (double_array->is_the_hole(i)) {
5823        value = factory->the_hole_value();
5824      } else {
5825        value = factory->NewHeapNumber(double_array->get_scalar(i));
5826      }
5827    } else {
5828      value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
5829    }
5830    if (!value->IsTheHole()) {
5831      PropertyDetails details = PropertyDetails::Empty();
5832      dictionary = SeededNumberDictionary::AddNumberEntry(
5833          dictionary, i, value, details, used_as_prototype);
5834    }
5835  }
5836  return dictionary;
5837}
5838
5839
5840void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
5841  if (dictionary->requires_slow_elements()) return;
5842  dictionary->set_requires_slow_elements();
5843  // TODO(verwaest): Remove this hack.
5844  if (map()->is_prototype_map()) {
5845    TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
5846  }
5847}
5848
5849
5850Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
5851    Handle<JSObject> object, Handle<FixedArrayBase> elements) {
5852  DCHECK(!object->HasDictionaryElements());
5853  DCHECK(!object->HasSlowArgumentsElements());
5854  Isolate* isolate = object->GetIsolate();
5855  // Ensure that notifications fire if the array or object prototypes are
5856  // normalizing.
5857  isolate->UpdateArrayProtectorOnNormalizeElements(object);
5858  int length = object->IsJSArray()
5859                   ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5860                   : elements->length();
5861  int used = object->GetFastElementsUsage();
5862  Handle<SeededNumberDictionary> dictionary =
5863      SeededNumberDictionary::New(isolate, used);
5864  return CopyFastElementsToDictionary(elements, length, dictionary,
5865                                      object->map()->is_prototype_map());
5866}
5867
5868
5869Handle<SeededNumberDictionary> JSObject::NormalizeElements(
5870    Handle<JSObject> object) {
5871  DCHECK(!object->HasFixedTypedArrayElements());
5872  Isolate* isolate = object->GetIsolate();
5873
5874  // Find the backing store.
5875  Handle<FixedArrayBase> elements(object->elements(), isolate);
5876  bool is_arguments = object->HasSloppyArgumentsElements();
5877  if (is_arguments) {
5878    FixedArray* parameter_map = FixedArray::cast(*elements);
5879    elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
5880  }
5881
5882  if (elements->IsDictionary()) {
5883    return Handle<SeededNumberDictionary>::cast(elements);
5884  }
5885
5886  DCHECK(object->HasFastSmiOrObjectElements() ||
5887         object->HasFastDoubleElements() ||
5888         object->HasFastArgumentsElements());
5889
5890  Handle<SeededNumberDictionary> dictionary =
5891      GetNormalizedElementDictionary(object, elements);
5892
5893  // Switch to using the dictionary as the backing storage for elements.
5894  ElementsKind target_kind =
5895      is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
5896  Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
5897  // Set the new map first to satify the elements type assert in set_elements().
5898  JSObject::MigrateToMap(object, new_map);
5899
5900  if (is_arguments) {
5901    FixedArray::cast(object->elements())->set(1, *dictionary);
5902  } else {
5903    object->set_elements(*dictionary);
5904  }
5905
5906  isolate->counters()->elements_to_dictionary()->Increment();
5907
5908#ifdef DEBUG
5909  if (FLAG_trace_normalization) {
5910    OFStream os(stdout);
5911    os << "Object elements have been normalized:\n";
5912    object->Print(os);
5913  }
5914#endif
5915
5916  DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
5917  return dictionary;
5918}
5919
5920
5921static Smi* GenerateIdentityHash(Isolate* isolate) {
5922  int hash_value;
5923  int attempts = 0;
5924  do {
5925    // Generate a random 32-bit hash value but limit range to fit
5926    // within a smi.
5927    hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
5928    attempts++;
5929  } while (hash_value == 0 && attempts < 30);
5930  hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
5931
5932  return Smi::FromInt(hash_value);
5933}
5934
5935
5936void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
5937  DCHECK(!object->IsJSGlobalProxy());
5938  Isolate* isolate = object->GetIsolate();
5939  Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
5940  JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
5941}
5942
5943
5944template<typename ProxyType>
5945static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
5946  Isolate* isolate = proxy->GetIsolate();
5947
5948  Handle<Object> maybe_hash(proxy->hash(), isolate);
5949  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
5950
5951  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
5952  proxy->set_hash(*hash);
5953  return hash;
5954}
5955
5956
5957Object* JSObject::GetIdentityHash() {
5958  DisallowHeapAllocation no_gc;
5959  Isolate* isolate = GetIsolate();
5960  if (IsJSGlobalProxy()) {
5961    return JSGlobalProxy::cast(this)->hash();
5962  }
5963  Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
5964  Handle<Object> stored_value =
5965      Object::GetPropertyOrElement(Handle<Object>(this, isolate),
5966                                   hash_code_symbol).ToHandleChecked();
5967  return stored_value->IsSmi() ? *stored_value
5968                               : isolate->heap()->undefined_value();
5969}
5970
5971
5972Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
5973  if (object->IsJSGlobalProxy()) {
5974    return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
5975  }
5976  Isolate* isolate = object->GetIsolate();
5977
5978  Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
5979  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
5980
5981  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
5982  Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
5983  JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
5984  return hash;
5985}
5986
5987
5988Object* JSProxy::GetIdentityHash() {
5989  return this->hash();
5990}
5991
5992
5993Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
5994  return GetOrCreateIdentityHashHelper(proxy);
5995}
5996
5997
5998Object* JSObject::GetHiddenProperty(Handle<Name> key) {
5999  DisallowHeapAllocation no_gc;
6000  DCHECK(key->IsUniqueName());
6001  if (IsJSGlobalProxy()) {
6002    // For a proxy, use the prototype as target object.
6003    PrototypeIterator iter(GetIsolate(), this);
6004    // If the proxy is detached, return undefined.
6005    if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
6006    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
6007    return iter.GetCurrent<JSObject>()->GetHiddenProperty(key);
6008  }
6009  DCHECK(!IsJSGlobalProxy());
6010  Object* inline_value = GetHiddenPropertiesHashTable();
6011
6012  if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
6013
6014  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
6015  Object* entry = hashtable->Lookup(key);
6016  return entry;
6017}
6018
6019
6020Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
6021                                           Handle<Name> key,
6022                                           Handle<Object> value) {
6023  Isolate* isolate = object->GetIsolate();
6024
6025  DCHECK(key->IsUniqueName());
6026  if (object->IsJSGlobalProxy()) {
6027    // For a proxy, use the prototype as target object.
6028    PrototypeIterator iter(isolate, object);
6029    // If the proxy is detached, return undefined.
6030    if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6031    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6032    return SetHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), key,
6033                             value);
6034  }
6035  DCHECK(!object->IsJSGlobalProxy());
6036
6037  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
6038
6039  Handle<ObjectHashTable> hashtable =
6040      GetOrCreateHiddenPropertiesHashtable(object);
6041
6042  // If it was found, check if the key is already in the dictionary.
6043  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
6044                                                           value);
6045  if (*new_table != *hashtable) {
6046    // If adding the key expanded the dictionary (i.e., Add returned a new
6047    // dictionary), store it back to the object.
6048    SetHiddenPropertiesHashTable(object, new_table);
6049  }
6050
6051  // Return this to mark success.
6052  return object;
6053}
6054
6055
6056void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
6057  Isolate* isolate = object->GetIsolate();
6058  DCHECK(key->IsUniqueName());
6059
6060  if (object->IsJSGlobalProxy()) {
6061    PrototypeIterator iter(isolate, object);
6062    if (iter.IsAtEnd()) return;
6063    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6064    return DeleteHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter),
6065                                key);
6066  }
6067
6068  Object* inline_value = object->GetHiddenPropertiesHashTable();
6069
6070  if (inline_value->IsUndefined()) return;
6071
6072  Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
6073  bool was_present = false;
6074  ObjectHashTable::Remove(hashtable, key, &was_present);
6075}
6076
6077
6078bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
6079  Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
6080  LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
6081  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
6082  // Cannot get an exception since the hidden_string isn't accessible to JS.
6083  DCHECK(maybe.IsJust());
6084  return maybe.FromJust() != ABSENT;
6085}
6086
6087
6088Object* JSObject::GetHiddenPropertiesHashTable() {
6089  DCHECK(!IsJSGlobalProxy());
6090  if (HasFastProperties()) {
6091    // If the object has fast properties, check whether the first slot
6092    // in the descriptor array matches the hidden string. Since the
6093    // hidden strings hash code is zero (and no other name has hash
6094    // code zero) it will always occupy the first entry if present.
6095    DescriptorArray* descriptors = this->map()->instance_descriptors();
6096    if (descriptors->number_of_descriptors() > 0) {
6097      int sorted_index = descriptors->GetSortedKeyIndex(0);
6098      if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
6099          sorted_index < map()->NumberOfOwnDescriptors()) {
6100        DCHECK(descriptors->GetType(sorted_index) == DATA);
6101        DCHECK(descriptors->GetDetails(sorted_index).representation().
6102               IsCompatibleForLoad(Representation::Tagged()));
6103        FieldIndex index = FieldIndex::ForDescriptor(this->map(),
6104                                                     sorted_index);
6105        return this->RawFastPropertyAt(index);
6106      } else {
6107        return GetHeap()->undefined_value();
6108      }
6109    } else {
6110      return GetHeap()->undefined_value();
6111    }
6112  } else {
6113    Isolate* isolate = GetIsolate();
6114    LookupIterator it(handle(this), isolate->factory()->hidden_string(),
6115                      LookupIterator::OWN_SKIP_INTERCEPTOR);
6116    // Access check is always skipped for the hidden string anyways.
6117    return *GetDataProperty(&it);
6118  }
6119}
6120
6121Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
6122    Handle<JSObject> object) {
6123  Isolate* isolate = object->GetIsolate();
6124
6125  static const int kInitialCapacity = 4;
6126  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
6127  if (inline_value->IsHashTable()) {
6128    return Handle<ObjectHashTable>::cast(inline_value);
6129  }
6130
6131  Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
6132      isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
6133
6134  DCHECK(inline_value->IsUndefined());
6135  SetHiddenPropertiesHashTable(object, hashtable);
6136  return hashtable;
6137}
6138
6139
6140Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
6141                                                      Handle<Object> value) {
6142  DCHECK(!object->IsJSGlobalProxy());
6143  Isolate* isolate = object->GetIsolate();
6144  Handle<Name> name = isolate->factory()->hidden_string();
6145  SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
6146  return object;
6147}
6148
6149
6150Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it) {
6151  Isolate* isolate = it->isolate();
6152  // Make sure that the top context does not change when doing callbacks or
6153  // interceptor calls.
6154  AssertNoContextChange ncc(isolate);
6155
6156  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
6157  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
6158  if (interceptor->deleter()->IsUndefined()) return Nothing<bool>();
6159
6160  Handle<JSObject> holder = it->GetHolder<JSObject>();
6161
6162  PropertyCallbackArguments args(isolate, interceptor->data(),
6163                                 *it->GetReceiver(), *holder);
6164  v8::Local<v8::Boolean> result;
6165  if (it->IsElement()) {
6166    uint32_t index = it->index();
6167    v8::IndexedPropertyDeleterCallback deleter =
6168        v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
6169    LOG(isolate,
6170        ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index));
6171    result = args.Call(deleter, index);
6172  } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
6173    return Nothing<bool>();
6174  } else {
6175    Handle<Name> name = it->name();
6176    DCHECK(!name->IsPrivate());
6177    v8::GenericNamedPropertyDeleterCallback deleter =
6178        v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
6179            interceptor->deleter());
6180    LOG(isolate,
6181        ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
6182    result = args.Call(deleter, v8::Utils::ToLocal(name));
6183  }
6184
6185  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6186  if (result.IsEmpty()) return Nothing<bool>();
6187
6188  DCHECK(result->IsBoolean());
6189  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
6190  result_internal->VerifyApiCallResultType();
6191  // Rebox CustomArguments::kReturnValueOffset before returning.
6192  return Just(result_internal->BooleanValue());
6193}
6194
6195
6196void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
6197                                          Handle<Name> name, int entry) {
6198  DCHECK(!object->HasFastProperties());
6199  Isolate* isolate = object->GetIsolate();
6200
6201  if (object->IsJSGlobalObject()) {
6202    // If we have a global object, invalidate the cell and swap in a new one.
6203    Handle<GlobalDictionary> dictionary(
6204        JSObject::cast(*object)->global_dictionary());
6205    DCHECK_NE(GlobalDictionary::kNotFound, entry);
6206
6207    auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
6208    cell->set_value(isolate->heap()->the_hole_value());
6209    // TODO(ishell): InvalidateForDelete
6210    cell->set_property_details(
6211        cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
6212  } else {
6213    Handle<NameDictionary> dictionary(object->property_dictionary());
6214    DCHECK_NE(NameDictionary::kNotFound, entry);
6215
6216    NameDictionary::DeleteProperty(dictionary, entry);
6217    Handle<NameDictionary> new_properties =
6218        NameDictionary::Shrink(dictionary, name);
6219    object->set_properties(*new_properties);
6220  }
6221}
6222
6223
6224Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
6225                                       LanguageMode language_mode) {
6226  Isolate* isolate = it->isolate();
6227
6228  if (it->state() == LookupIterator::JSPROXY) {
6229    return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
6230                                            it->GetName(), language_mode);
6231  }
6232
6233  if (it->GetReceiver()->IsJSProxy()) {
6234    if (it->state() != LookupIterator::NOT_FOUND) {
6235      DCHECK_EQ(LookupIterator::DATA, it->state());
6236      DCHECK(it->GetName()->IsPrivate());
6237      it->Delete();
6238    }
6239    return Just(true);
6240  }
6241  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
6242
6243  bool is_observed =
6244      receiver->map()->is_observed() &&
6245      (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()));
6246
6247  Handle<Object> old_value = it->factory()->the_hole_value();
6248
6249  for (; it->IsFound(); it->Next()) {
6250    switch (it->state()) {
6251      case LookupIterator::JSPROXY:
6252      case LookupIterator::NOT_FOUND:
6253      case LookupIterator::TRANSITION:
6254        UNREACHABLE();
6255      case LookupIterator::ACCESS_CHECK:
6256        if (it->HasAccess()) break;
6257        isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
6258        RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6259        return Just(false);
6260      case LookupIterator::INTERCEPTOR: {
6261        Maybe<bool> result = JSObject::DeletePropertyWithInterceptor(it);
6262        // An exception was thrown in the interceptor. Propagate.
6263        if (isolate->has_pending_exception()) return Nothing<bool>();
6264        // Delete with interceptor succeeded. Return result.
6265        // TODO(neis): In strict mode, we should probably throw if the
6266        // interceptor returns false.
6267        if (result.IsJust()) return result;
6268        break;
6269      }
6270      case LookupIterator::INTEGER_INDEXED_EXOTIC:
6271        return Just(true);
6272      case LookupIterator::DATA:
6273        if (is_observed) {
6274          old_value = it->GetDataValue();
6275        }
6276      // Fall through.
6277      case LookupIterator::ACCESSOR: {
6278        if (!it->IsConfigurable() || receiver->map()->is_strong()) {
6279          // Fail if the property is not configurable, or on a strong object.
6280          if (is_strict(language_mode)) {
6281            MessageTemplate::Template templ =
6282                receiver->map()->is_strong()
6283                    ? MessageTemplate::kStrongDeleteProperty
6284                    : MessageTemplate::kStrictDeleteProperty;
6285            isolate->Throw(*isolate->factory()->NewTypeError(
6286                templ, it->GetName(), receiver));
6287            return Nothing<bool>();
6288          }
6289          return Just(false);
6290        }
6291
6292        it->Delete();
6293
6294        if (is_observed) {
6295          RETURN_ON_EXCEPTION_VALUE(
6296              isolate, JSObject::EnqueueChangeRecord(receiver, "delete",
6297                                                     it->GetName(), old_value),
6298              Nothing<bool>());
6299        }
6300
6301        return Just(true);
6302      }
6303    }
6304  }
6305
6306  return Just(true);
6307}
6308
6309
6310Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
6311                                      LanguageMode language_mode) {
6312  LookupIterator it(object->GetIsolate(), object, index,
6313                    LookupIterator::HIDDEN);
6314  return DeleteProperty(&it, language_mode);
6315}
6316
6317
6318Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
6319                                       Handle<Name> name,
6320                                       LanguageMode language_mode) {
6321  LookupIterator it(object, name, LookupIterator::HIDDEN);
6322  return DeleteProperty(&it, language_mode);
6323}
6324
6325
6326Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
6327                                                Handle<Name> name,
6328                                                LanguageMode language_mode) {
6329  LookupIterator it = LookupIterator::PropertyOrElement(
6330      name->GetIsolate(), object, name, LookupIterator::HIDDEN);
6331  return DeleteProperty(&it, language_mode);
6332}
6333
6334
6335// ES6 7.1.14
6336MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) {
6337  // 1. Let key be ToPrimitive(argument, hint String).
6338  MaybeHandle<Object> maybe_key =
6339      Object::ToPrimitive(value, ToPrimitiveHint::kString);
6340  // 2. ReturnIfAbrupt(key).
6341  Handle<Object> key;
6342  if (!maybe_key.ToHandle(&key)) return key;
6343  // 3. If Type(key) is Symbol, then return key.
6344  if (key->IsSymbol()) return key;
6345  // 4. Return ToString(key).
6346  // Extending spec'ed behavior, we'd be happy to return an element index.
6347  if (key->IsSmi()) return key;
6348  if (key->IsHeapNumber()) {
6349    uint32_t uint_value;
6350    if (value->ToArrayLength(&uint_value) &&
6351        uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
6352      return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
6353    }
6354  }
6355  return Object::ToString(isolate, key);
6356}
6357
6358
6359// ES6 19.1.2.4
6360// static
6361Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
6362                                   Handle<Object> key,
6363                                   Handle<Object> attributes) {
6364  // 1. If Type(O) is not Object, throw a TypeError exception.
6365  if (!object->IsJSReceiver()) {
6366    Handle<String> fun_name =
6367        isolate->factory()->InternalizeUtf8String("Object.defineProperty");
6368    THROW_NEW_ERROR_RETURN_FAILURE(
6369        isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
6370  }
6371  // 2. Let key be ToPropertyKey(P).
6372  // 3. ReturnIfAbrupt(key).
6373  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
6374  // 4. Let desc be ToPropertyDescriptor(Attributes).
6375  // 5. ReturnIfAbrupt(desc).
6376  PropertyDescriptor desc;
6377  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
6378    return isolate->heap()->exception();
6379  }
6380  // 6. Let success be DefinePropertyOrThrow(O,key, desc).
6381  Maybe<bool> success = DefineOwnProperty(
6382      isolate, Handle<JSReceiver>::cast(object), key, &desc, THROW_ON_ERROR);
6383  // 7. ReturnIfAbrupt(success).
6384  MAYBE_RETURN(success, isolate->heap()->exception());
6385  CHECK(success.FromJust());
6386  // 8. Return O.
6387  return *object;
6388}
6389
6390
6391// ES6 19.1.2.3.1
6392// static
6393MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
6394                                                 Handle<Object> object,
6395                                                 Handle<Object> properties) {
6396  // 1. If Type(O) is not Object, throw a TypeError exception.
6397  if (!object->IsJSReceiver()) {
6398    Handle<String> fun_name =
6399        isolate->factory()->InternalizeUtf8String("Object.defineProperties");
6400    THROW_NEW_ERROR(isolate,
6401                    NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
6402                    Object);
6403  }
6404  // 2. Let props be ToObject(Properties).
6405  // 3. ReturnIfAbrupt(props).
6406  Handle<JSReceiver> props;
6407  if (!Object::ToObject(isolate, properties).ToHandle(&props)) {
6408    THROW_NEW_ERROR(isolate,
6409                    NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
6410                    Object);
6411  }
6412  // 4. Let keys be props.[[OwnPropertyKeys]]().
6413  // 5. ReturnIfAbrupt(keys).
6414  Handle<FixedArray> keys;
6415  ASSIGN_RETURN_ON_EXCEPTION(
6416      isolate, keys,
6417      JSReceiver::GetKeys(props, JSReceiver::OWN_ONLY, ALL_PROPERTIES), Object);
6418  // 6. Let descriptors be an empty List.
6419  int capacity = keys->length();
6420  std::vector<PropertyDescriptor> descriptors(capacity);
6421  size_t descriptors_index = 0;
6422  // 7. Repeat for each element nextKey of keys in List order,
6423  for (int i = 0; i < keys->length(); ++i) {
6424    Handle<Object> next_key(keys->get(i), isolate);
6425    // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
6426    // 7b. ReturnIfAbrupt(propDesc).
6427    bool success = false;
6428    LookupIterator it = LookupIterator::PropertyOrElement(
6429        isolate, props, next_key, &success, LookupIterator::HIDDEN);
6430    DCHECK(success);
6431    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
6432    if (!maybe.IsJust()) return MaybeHandle<Object>();
6433    PropertyAttributes attrs = maybe.FromJust();
6434    // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
6435    if (attrs == ABSENT) continue;
6436    if (attrs & DONT_ENUM) continue;
6437    // 7c i. Let descObj be Get(props, nextKey).
6438    // 7c ii. ReturnIfAbrupt(descObj).
6439    Handle<Object> desc_obj;
6440    ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
6441                               Object);
6442    // 7c iii. Let desc be ToPropertyDescriptor(descObj).
6443    success = PropertyDescriptor::ToPropertyDescriptor(
6444        isolate, desc_obj, &descriptors[descriptors_index]);
6445    // 7c iv. ReturnIfAbrupt(desc).
6446    if (!success) return MaybeHandle<Object>();
6447    // 7c v. Append the pair (a two element List) consisting of nextKey and
6448    //       desc to the end of descriptors.
6449    descriptors[descriptors_index].set_name(next_key);
6450    descriptors_index++;
6451  }
6452  // 8. For each pair from descriptors in list order,
6453  for (size_t i = 0; i < descriptors_index; ++i) {
6454    PropertyDescriptor* desc = &descriptors[i];
6455    // 8a. Let P be the first element of pair.
6456    // 8b. Let desc be the second element of pair.
6457    // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
6458    Maybe<bool> status =
6459        DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
6460                          desc->name(), desc, THROW_ON_ERROR);
6461    // 8d. ReturnIfAbrupt(status).
6462    if (!status.IsJust()) return MaybeHandle<Object>();
6463    CHECK(status.FromJust());
6464  }
6465  // 9. Return o.
6466  return object;
6467}
6468
6469
6470// static
6471Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
6472                                          Handle<JSReceiver> object,
6473                                          Handle<Object> key,
6474                                          PropertyDescriptor* desc,
6475                                          ShouldThrow should_throw) {
6476  if (object->IsJSArray()) {
6477    return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
6478                                      key, desc, should_throw);
6479  }
6480  if (object->IsJSProxy()) {
6481    return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
6482                                      key, desc, should_throw);
6483  }
6484  // TODO(jkummerow): Support Modules (ES6 9.4.6.6)
6485
6486  // OrdinaryDefineOwnProperty, by virtue of calling
6487  // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
6488  // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception:
6489  // TODO(jkummerow): Setting an indexed accessor on a typed array should throw.
6490  return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
6491                                   desc, should_throw);
6492}
6493
6494
6495// static
6496Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
6497                                                  Handle<JSObject> object,
6498                                                  Handle<Object> key,
6499                                                  PropertyDescriptor* desc,
6500                                                  ShouldThrow should_throw) {
6501  bool success = false;
6502  DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
6503  LookupIterator it = LookupIterator::PropertyOrElement(
6504      isolate, object, key, &success, LookupIterator::HIDDEN);
6505  DCHECK(success);  // ...so creating a LookupIterator can't fail.
6506
6507  // Deal with access checks first.
6508  if (it.state() == LookupIterator::ACCESS_CHECK) {
6509    if (!it.HasAccess()) {
6510      isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6511      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6512      return Just(true);
6513    }
6514    it.Next();
6515  }
6516
6517  return OrdinaryDefineOwnProperty(&it, desc, should_throw);
6518}
6519
6520
6521// ES6 9.1.6.1
6522// static
6523Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
6524                                                  PropertyDescriptor* desc,
6525                                                  ShouldThrow should_throw) {
6526  Isolate* isolate = it->isolate();
6527  // 1. Let current be O.[[GetOwnProperty]](P).
6528  // 2. ReturnIfAbrupt(current).
6529  PropertyDescriptor current;
6530  MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
6531
6532  // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
6533  // the iterator every time. Currently, the reasons why we need it are:
6534  // - handle interceptors correctly
6535  // - handle accessors correctly (which might change the holder's map)
6536  it->Restart();
6537  // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
6538  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
6539  bool extensible = JSObject::IsExtensible(object);
6540
6541  return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc,
6542                                            &current, should_throw);
6543}
6544
6545
6546// ES6 9.1.6.2
6547// static
6548Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
6549    Isolate* isolate, bool extensible, PropertyDescriptor* desc,
6550    PropertyDescriptor* current, Handle<Name> property_name,
6551    ShouldThrow should_throw) {
6552  // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
6553  //    Extensible, Desc, Current).
6554  return ValidateAndApplyPropertyDescriptor(
6555      isolate, NULL, extensible, desc, current, should_throw, property_name);
6556}
6557
6558
6559// ES6 9.1.6.3
6560// static
6561Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
6562    Isolate* isolate, LookupIterator* it, bool extensible,
6563    PropertyDescriptor* desc, PropertyDescriptor* current,
6564    ShouldThrow should_throw, Handle<Name> property_name) {
6565  // We either need a LookupIterator, or a property name.
6566  DCHECK((it == NULL) != property_name.is_null());
6567  Handle<JSObject> object;
6568  if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver());
6569  bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
6570  bool desc_is_accessor_descriptor =
6571      PropertyDescriptor::IsAccessorDescriptor(desc);
6572  bool desc_is_generic_descriptor =
6573      PropertyDescriptor::IsGenericDescriptor(desc);
6574  // 1. (Assert)
6575  // 2. If current is undefined, then
6576  if (current->is_empty()) {
6577    // 2a. If extensible is false, return false.
6578    if (!extensible) {
6579      RETURN_FAILURE(isolate, should_throw,
6580                     NewTypeError(MessageTemplate::kDefineDisallowed,
6581                                  it != NULL ? it->GetName() : property_name));
6582    }
6583    // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
6584    // (This is equivalent to !IsAccessorDescriptor(desc).)
6585    DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
6586           !desc_is_accessor_descriptor);
6587    if (!desc_is_accessor_descriptor) {
6588      // 2c i. If O is not undefined, create an own data property named P of
6589      // object O whose [[Value]], [[Writable]], [[Enumerable]] and
6590      // [[Configurable]] attribute values are described by Desc. If the value
6591      // of an attribute field of Desc is absent, the attribute of the newly
6592      // created property is set to its default value.
6593      if (it != NULL) {
6594        if (!desc->has_writable()) desc->set_writable(false);
6595        if (!desc->has_enumerable()) desc->set_enumerable(false);
6596        if (!desc->has_configurable()) desc->set_configurable(false);
6597        Handle<Object> value(
6598            desc->has_value()
6599                ? desc->value()
6600                : Handle<Object>::cast(isolate->factory()->undefined_value()));
6601        MaybeHandle<Object> result =
6602            JSObject::DefineOwnPropertyIgnoreAttributes(
6603                it, value, desc->ToAttributes(), JSObject::DONT_FORCE_FIELD);
6604        if (result.is_null()) return Nothing<bool>();
6605      }
6606    } else {
6607      // 2d. Else Desc must be an accessor Property Descriptor,
6608      DCHECK(desc_is_accessor_descriptor);
6609      // 2d i. If O is not undefined, create an own accessor property named P
6610      // of object O whose [[Get]], [[Set]], [[Enumerable]] and
6611      // [[Configurable]] attribute values are described by Desc. If the value
6612      // of an attribute field of Desc is absent, the attribute of the newly
6613      // created property is set to its default value.
6614      if (it != NULL) {
6615        if (!desc->has_enumerable()) desc->set_enumerable(false);
6616        if (!desc->has_configurable()) desc->set_configurable(false);
6617        Handle<Object> getter(
6618            desc->has_get()
6619                ? desc->get()
6620                : Handle<Object>::cast(isolate->factory()->null_value()));
6621        Handle<Object> setter(
6622            desc->has_set()
6623                ? desc->set()
6624                : Handle<Object>::cast(isolate->factory()->null_value()));
6625        MaybeHandle<Object> result =
6626            JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
6627        if (result.is_null()) return Nothing<bool>();
6628      }
6629    }
6630    // 2e. Return true.
6631    return Just(true);
6632  }
6633  // 3. Return true, if every field in Desc is absent.
6634  // 4. Return true, if every field in Desc also occurs in current and the
6635  // value of every field in Desc is the same value as the corresponding field
6636  // in current when compared using the SameValue algorithm.
6637  if ((!desc->has_enumerable() ||
6638       desc->enumerable() == current->enumerable()) &&
6639      (!desc->has_configurable() ||
6640       desc->configurable() == current->configurable()) &&
6641      (!desc->has_value() ||
6642       (current->has_value() && current->value()->SameValue(*desc->value()))) &&
6643      (!desc->has_writable() ||
6644       (current->has_writable() && current->writable() == desc->writable())) &&
6645      (!desc->has_get() ||
6646       (current->has_get() && current->get()->SameValue(*desc->get()))) &&
6647      (!desc->has_set() ||
6648       (current->has_set() && current->set()->SameValue(*desc->set())))) {
6649    return Just(true);
6650  }
6651  // 5. If the [[Configurable]] field of current is false, then
6652  if (!current->configurable()) {
6653    // 5a. Return false, if the [[Configurable]] field of Desc is true.
6654    if (desc->has_configurable() && desc->configurable()) {
6655      RETURN_FAILURE(isolate, should_throw,
6656                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6657                                  it != NULL ? it->GetName() : property_name));
6658    }
6659    // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
6660    // [[Enumerable]] fields of current and Desc are the Boolean negation of
6661    // each other.
6662    if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
6663      RETURN_FAILURE(isolate, should_throw,
6664                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6665                                  it != NULL ? it->GetName() : property_name));
6666    }
6667  }
6668
6669  bool current_is_data_descriptor =
6670      PropertyDescriptor::IsDataDescriptor(current);
6671  // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
6672  if (desc_is_generic_descriptor) {
6673    // Nothing to see here.
6674
6675    // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
6676    // different results, then:
6677  } else if (current_is_data_descriptor != desc_is_data_descriptor) {
6678    // 7a. Return false, if the [[Configurable]] field of current is false.
6679    if (!current->configurable()) {
6680      RETURN_FAILURE(isolate, should_throw,
6681                     NewTypeError(MessageTemplate::kRedefineDisallowed,
6682                                  it != NULL ? it->GetName() : property_name));
6683    }
6684    // 7b. If IsDataDescriptor(current) is true, then:
6685    if (current_is_data_descriptor) {
6686      // 7b i. If O is not undefined, convert the property named P of object O
6687      // from a data property to an accessor property. Preserve the existing
6688      // values of the converted property's [[Configurable]] and [[Enumerable]]
6689      // attributes and set the rest of the property's attributes to their
6690      // default values.
6691      // --> Folded into step 10.
6692    } else {
6693      // 7c i. If O is not undefined, convert the property named P of object O
6694      // from an accessor property to a data property. Preserve the existing
6695      // values of the converted property’s [[Configurable]] and [[Enumerable]]
6696      // attributes and set the rest of the property’s attributes to their
6697      // default values.
6698      // --> Folded into step 10.
6699    }
6700
6701    // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
6702    // true, then:
6703  } else if (current_is_data_descriptor && desc_is_data_descriptor) {
6704    // 8a. If the [[Configurable]] field of current is false, then:
6705    if (!current->configurable()) {
6706      // [Strong mode] Disallow changing writable -> readonly for
6707      // non-configurable properties.
6708      if (it != NULL && current->writable() && desc->has_writable() &&
6709          !desc->writable() && object->map()->is_strong()) {
6710        RETURN_FAILURE(isolate, should_throw,
6711                       NewTypeError(MessageTemplate::kStrongRedefineDisallowed,
6712                                    object, it->GetName()));
6713      }
6714      // 8a i. Return false, if the [[Writable]] field of current is false and
6715      // the [[Writable]] field of Desc is true.
6716      if (!current->writable() && desc->has_writable() && desc->writable()) {
6717        RETURN_FAILURE(
6718            isolate, should_throw,
6719            NewTypeError(MessageTemplate::kRedefineDisallowed,
6720                         it != NULL ? it->GetName() : property_name));
6721      }
6722      // 8a ii. If the [[Writable]] field of current is false, then:
6723      if (!current->writable()) {
6724        // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
6725        // SameValue(Desc.[[Value]], current.[[Value]]) is false.
6726        if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
6727          RETURN_FAILURE(
6728              isolate, should_throw,
6729              NewTypeError(MessageTemplate::kRedefineDisallowed,
6730                           it != NULL ? it->GetName() : property_name));
6731        }
6732      }
6733    }
6734  } else {
6735    // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
6736    // are both true,
6737    DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
6738           desc_is_accessor_descriptor);
6739    // 9a. If the [[Configurable]] field of current is false, then:
6740    if (!current->configurable()) {
6741      // 9a i. Return false, if the [[Set]] field of Desc is present and
6742      // SameValue(Desc.[[Set]], current.[[Set]]) is false.
6743      if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
6744        RETURN_FAILURE(
6745            isolate, should_throw,
6746            NewTypeError(MessageTemplate::kRedefineDisallowed,
6747                         it != NULL ? it->GetName() : property_name));
6748      }
6749      // 9a ii. Return false, if the [[Get]] field of Desc is present and
6750      // SameValue(Desc.[[Get]], current.[[Get]]) is false.
6751      if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
6752        RETURN_FAILURE(
6753            isolate, should_throw,
6754            NewTypeError(MessageTemplate::kRedefineDisallowed,
6755                         it != NULL ? it->GetName() : property_name));
6756      }
6757    }
6758  }
6759
6760  // 10. If O is not undefined, then:
6761  if (it != NULL) {
6762    // 10a. For each field of Desc that is present, set the corresponding
6763    // attribute of the property named P of object O to the value of the field.
6764    PropertyAttributes attrs = NONE;
6765
6766    if (desc->has_enumerable()) {
6767      attrs = static_cast<PropertyAttributes>(
6768          attrs | (desc->enumerable() ? NONE : DONT_ENUM));
6769    } else {
6770      attrs = static_cast<PropertyAttributes>(
6771          attrs | (current->enumerable() ? NONE : DONT_ENUM));
6772    }
6773    if (desc->has_configurable()) {
6774      attrs = static_cast<PropertyAttributes>(
6775          attrs | (desc->configurable() ? NONE : DONT_DELETE));
6776    } else {
6777      attrs = static_cast<PropertyAttributes>(
6778          attrs | (current->configurable() ? NONE : DONT_DELETE));
6779    }
6780    if (desc_is_data_descriptor ||
6781        (desc_is_generic_descriptor && current_is_data_descriptor)) {
6782      if (desc->has_writable()) {
6783        attrs = static_cast<PropertyAttributes>(
6784            attrs | (desc->writable() ? NONE : READ_ONLY));
6785      } else {
6786        attrs = static_cast<PropertyAttributes>(
6787            attrs | (current->writable() ? NONE : READ_ONLY));
6788      }
6789      Handle<Object> value(
6790          desc->has_value() ? desc->value()
6791                            : current->has_value()
6792                                  ? current->value()
6793                                  : Handle<Object>::cast(
6794                                        isolate->factory()->undefined_value()));
6795      MaybeHandle<Object> result = JSObject::DefineOwnPropertyIgnoreAttributes(
6796          it, value, attrs, JSObject::DONT_FORCE_FIELD);
6797      if (result.is_null()) return Nothing<bool>();
6798    } else {
6799      DCHECK(desc_is_accessor_descriptor ||
6800             (desc_is_generic_descriptor &&
6801              PropertyDescriptor::IsAccessorDescriptor(current)));
6802      Handle<Object> getter(
6803          desc->has_get()
6804              ? desc->get()
6805              : current->has_get()
6806                    ? current->get()
6807                    : Handle<Object>::cast(isolate->factory()->null_value()));
6808      Handle<Object> setter(
6809          desc->has_set()
6810              ? desc->set()
6811              : current->has_set()
6812                    ? current->set()
6813                    : Handle<Object>::cast(isolate->factory()->null_value()));
6814      MaybeHandle<Object> result =
6815          JSObject::DefineAccessor(it, getter, setter, attrs);
6816      if (result.is_null()) return Nothing<bool>();
6817    }
6818  }
6819
6820  // 11. Return true.
6821  return Just(true);
6822}
6823
6824
6825// static
6826Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
6827                                           Handle<Object> value,
6828                                           ShouldThrow should_throw) {
6829  DCHECK(!it->check_prototype_chain());
6830  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
6831  Isolate* isolate = receiver->GetIsolate();
6832
6833  if (receiver->IsJSObject()) {
6834    return JSObject::CreateDataProperty(it, value);  // Shortcut.
6835  }
6836
6837  PropertyDescriptor new_desc;
6838  new_desc.set_value(value);
6839  new_desc.set_writable(true);
6840  new_desc.set_enumerable(true);
6841  new_desc.set_configurable(true);
6842
6843  return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
6844                                       &new_desc, should_throw);
6845}
6846
6847
6848Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
6849                                         Handle<Object> value) {
6850  DCHECK(it->GetReceiver()->IsJSObject());
6851  MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
6852
6853  if (it->IsFound()) {
6854    if (!it->IsConfigurable()) return Just(false);
6855  } else {
6856    if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver())))
6857      return Just(false);
6858  }
6859
6860  RETURN_ON_EXCEPTION_VALUE(
6861      it->isolate(),
6862      DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD),
6863      Nothing<bool>());
6864
6865  return Just(true);
6866}
6867
6868
6869// TODO(jkummerow): Consider unification with FastAsArrayLength() in
6870// accessors.cc.
6871bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
6872  DCHECK(value->IsNumber() || value->IsName());
6873  if (value->ToArrayLength(length)) return true;
6874  if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
6875  return false;
6876}
6877
6878
6879bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
6880  return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
6881}
6882
6883
6884// ES6 9.4.2.1
6885// static
6886Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
6887                                       Handle<Object> name,
6888                                       PropertyDescriptor* desc,
6889                                       ShouldThrow should_throw) {
6890  // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
6891  // 2. If P is "length", then:
6892  // TODO(jkummerow): Check if we need slow string comparison.
6893  if (*name == isolate->heap()->length_string()) {
6894    // 2a. Return ArraySetLength(A, Desc).
6895    return ArraySetLength(isolate, o, desc, should_throw);
6896  }
6897  // 3. Else if P is an array index, then:
6898  uint32_t index = 0;
6899  if (PropertyKeyToArrayIndex(name, &index)) {
6900    // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
6901    PropertyDescriptor old_len_desc;
6902    Maybe<bool> success = GetOwnPropertyDescriptor(
6903        isolate, o, isolate->factory()->length_string(), &old_len_desc);
6904    // 3b. (Assert)
6905    DCHECK(success.FromJust());
6906    USE(success);
6907    // 3c. Let oldLen be oldLenDesc.[[Value]].
6908    uint32_t old_len = 0;
6909    CHECK(old_len_desc.value()->ToArrayLength(&old_len));
6910    // 3d. Let index be ToUint32(P).
6911    // (Already done above.)
6912    // 3e. (Assert)
6913    // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
6914    //     return false.
6915    if (index >= old_len && old_len_desc.has_writable() &&
6916        !old_len_desc.writable()) {
6917      RETURN_FAILURE(isolate, should_throw,
6918                     NewTypeError(MessageTemplate::kDefineDisallowed, name));
6919    }
6920    // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
6921    Maybe<bool> succeeded =
6922        OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
6923    // 3h. Assert: succeeded is not an abrupt completion.
6924    //     In our case, if should_throw == THROW_ON_ERROR, it can be!
6925    // 3i. If succeeded is false, return false.
6926    if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
6927    // 3j. If index >= oldLen, then:
6928    if (index >= old_len) {
6929      // 3j i. Set oldLenDesc.[[Value]] to index + 1.
6930      old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
6931      // 3j ii. Let succeeded be
6932      //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
6933      succeeded = OrdinaryDefineOwnProperty(isolate, o,
6934                                            isolate->factory()->length_string(),
6935                                            &old_len_desc, should_throw);
6936      // 3j iii. Assert: succeeded is true.
6937      DCHECK(succeeded.FromJust());
6938      USE(succeeded);
6939    }
6940    // 3k. Return true.
6941    return Just(true);
6942  }
6943
6944  // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
6945  return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
6946}
6947
6948
6949// Part of ES6 9.4.2.4 ArraySetLength.
6950// static
6951bool JSArray::AnythingToArrayLength(Isolate* isolate,
6952                                    Handle<Object> length_object,
6953                                    uint32_t* output) {
6954  // Fast path: check numbers and strings that can be converted directly
6955  // and unobservably.
6956  if (length_object->ToArrayLength(output)) return true;
6957  if (length_object->IsString() &&
6958      Handle<String>::cast(length_object)->AsArrayIndex(output)) {
6959    return true;
6960  }
6961  // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
6962  // 3. Let newLen be ToUint32(Desc.[[Value]]).
6963  Handle<Object> uint32_v;
6964  if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
6965    // 4. ReturnIfAbrupt(newLen).
6966    return false;
6967  }
6968  // 5. Let numberLen be ToNumber(Desc.[[Value]]).
6969  Handle<Object> number_v;
6970  if (!Object::ToNumber(length_object).ToHandle(&number_v)) {
6971    // 6. ReturnIfAbrupt(newLen).
6972    return false;
6973  }
6974  // 7. If newLen != numberLen, throw a RangeError exception.
6975  if (uint32_v->Number() != number_v->Number()) {
6976    Handle<Object> exception =
6977        isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
6978    isolate->Throw(*exception);
6979    return false;
6980  }
6981  CHECK(uint32_v->ToArrayLength(output));
6982  return true;
6983}
6984
6985
6986// ES6 9.4.2.4
6987// static
6988Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
6989                                    PropertyDescriptor* desc,
6990                                    ShouldThrow should_throw) {
6991  // 1. If the [[Value]] field of Desc is absent, then
6992  if (!desc->has_value()) {
6993    // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
6994    return OrdinaryDefineOwnProperty(
6995        isolate, a, isolate->factory()->length_string(), desc, should_throw);
6996  }
6997  // 2. Let newLenDesc be a copy of Desc.
6998  // (Actual copying is not necessary.)
6999  PropertyDescriptor* new_len_desc = desc;
7000  // 3. - 7. Convert Desc.[[Value]] to newLen.
7001  uint32_t new_len = 0;
7002  if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
7003    DCHECK(isolate->has_pending_exception());
7004    return Nothing<bool>();
7005  }
7006  // 8. Set newLenDesc.[[Value]] to newLen.
7007  // (Done below, if needed.)
7008  // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
7009  PropertyDescriptor old_len_desc;
7010  Maybe<bool> success = GetOwnPropertyDescriptor(
7011      isolate, a, isolate->factory()->length_string(), &old_len_desc);
7012  // 10. (Assert)
7013  DCHECK(success.FromJust());
7014  USE(success);
7015  // 11. Let oldLen be oldLenDesc.[[Value]].
7016  uint32_t old_len = 0;
7017  CHECK(old_len_desc.value()->ToArrayLength(&old_len));
7018  // 12. If newLen >= oldLen, then
7019  if (new_len >= old_len) {
7020    // 8. Set newLenDesc.[[Value]] to newLen.
7021    // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
7022    new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
7023    return OrdinaryDefineOwnProperty(isolate, a,
7024                                     isolate->factory()->length_string(),
7025                                     new_len_desc, should_throw);
7026  }
7027  // 13. If oldLenDesc.[[Writable]] is false, return false.
7028  if (!old_len_desc.writable()) {
7029    RETURN_FAILURE(isolate, should_throw,
7030                   NewTypeError(MessageTemplate::kRedefineDisallowed,
7031                                isolate->factory()->length_string()));
7032  }
7033  // 14. If newLenDesc.[[Writable]] is absent or has the value true,
7034  // let newWritable be true.
7035  bool new_writable = false;
7036  if (!new_len_desc->has_writable() || new_len_desc->writable()) {
7037    new_writable = true;
7038  } else {
7039    // 15. Else,
7040    // 15a. Need to defer setting the [[Writable]] attribute to false in case
7041    //      any elements cannot be deleted.
7042    // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
7043    // 15c. Set newLenDesc.[[Writable]] to true.
7044    // (Not needed.)
7045  }
7046  // Most of steps 16 through 19 is implemented by JSArray::SetLength.
7047  if (JSArray::ObservableSetLength(a, new_len).is_null()) {
7048    DCHECK(isolate->has_pending_exception());
7049    return Nothing<bool>();
7050  }
7051  // Steps 19d-ii, 20.
7052  if (!new_writable) {
7053    PropertyDescriptor readonly;
7054    readonly.set_writable(false);
7055    Maybe<bool> success = OrdinaryDefineOwnProperty(
7056        isolate, a, isolate->factory()->length_string(), &readonly,
7057        should_throw);
7058    DCHECK(success.FromJust());
7059    USE(success);
7060  }
7061  uint32_t actual_new_len = 0;
7062  CHECK(a->length()->ToArrayLength(&actual_new_len));
7063  // Steps 19d-v, 21. Return false if there were non-deletable elements.
7064  bool result = actual_new_len == new_len;
7065  if (!result) {
7066    RETURN_FAILURE(
7067        isolate, should_throw,
7068        NewTypeError(MessageTemplate::kStrictDeleteProperty,
7069                     isolate->factory()->NewNumberFromUint(actual_new_len - 1),
7070                     a));
7071  }
7072  return Just(result);
7073}
7074
7075
7076// ES6 9.5.6
7077// static
7078Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
7079                                       Handle<Object> key,
7080                                       PropertyDescriptor* desc,
7081                                       ShouldThrow should_throw) {
7082  STACK_CHECK(Nothing<bool>());
7083  if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
7084    return AddPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc,
7085                              should_throw);
7086  }
7087  Handle<String> trap_name = isolate->factory()->defineProperty_string();
7088  // 1. Assert: IsPropertyKey(P) is true.
7089  DCHECK(key->IsName() || key->IsNumber());
7090  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
7091  Handle<Object> handler(proxy->handler(), isolate);
7092  // 3. If handler is null, throw a TypeError exception.
7093  // 4. Assert: Type(handler) is Object.
7094  if (proxy->IsRevoked()) {
7095    isolate->Throw(*isolate->factory()->NewTypeError(
7096        MessageTemplate::kProxyRevoked, trap_name));
7097    return Nothing<bool>();
7098  }
7099  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
7100  Handle<JSReceiver> target(proxy->target(), isolate);
7101  // 6. Let trap be ? GetMethod(handler, "defineProperty").
7102  Handle<Object> trap;
7103  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7104      isolate, trap,
7105      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
7106      Nothing<bool>());
7107  // 7. If trap is undefined, then:
7108  if (trap->IsUndefined()) {
7109    // 7a. Return target.[[DefineOwnProperty]](P, Desc).
7110    return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
7111                                         should_throw);
7112  }
7113  // 8. Let descObj be FromPropertyDescriptor(Desc).
7114  Handle<Object> desc_obj = desc->ToObject(isolate);
7115  // 9. Let booleanTrapResult be
7116  //    ToBoolean(? Call(trap, handler, «target, P, descObj»)).
7117  Handle<Name> property_name =
7118      key->IsName()
7119          ? Handle<Name>::cast(key)
7120          : Handle<Name>::cast(isolate->factory()->NumberToString(key));
7121  // Do not leak private property names.
7122  DCHECK(!property_name->IsPrivate());
7123  Handle<Object> trap_result_obj;
7124  Handle<Object> args[] = {target, property_name, desc_obj};
7125  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7126      isolate, trap_result_obj,
7127      Execution::Call(isolate, trap, handler, arraysize(args), args),
7128      Nothing<bool>());
7129  // 10. If booleanTrapResult is false, return false.
7130  if (!trap_result_obj->BooleanValue()) {
7131    RETURN_FAILURE(isolate, should_throw,
7132                   NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
7133                                trap_name, property_name));
7134  }
7135  // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
7136  PropertyDescriptor target_desc;
7137  Maybe<bool> target_found =
7138      JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
7139  MAYBE_RETURN(target_found, Nothing<bool>());
7140  // 12. Let extensibleTarget be ? IsExtensible(target).
7141  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
7142  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
7143  bool extensible_target = maybe_extensible.FromJust();
7144  // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
7145  //     is false, then:
7146  // 13a. Let settingConfigFalse be true.
7147  // 14. Else let settingConfigFalse be false.
7148  bool setting_config_false = desc->has_configurable() && !desc->configurable();
7149  // 15. If targetDesc is undefined, then
7150  if (!target_found.FromJust()) {
7151    // 15a. If extensibleTarget is false, throw a TypeError exception.
7152    if (!extensible_target) {
7153      isolate->Throw(*isolate->factory()->NewTypeError(
7154          MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
7155      return Nothing<bool>();
7156    }
7157    // 15b. If settingConfigFalse is true, throw a TypeError exception.
7158    if (setting_config_false) {
7159      isolate->Throw(*isolate->factory()->NewTypeError(
7160          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7161      return Nothing<bool>();
7162    }
7163  } else {
7164    // 16. Else targetDesc is not undefined,
7165    // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
7166    //      targetDesc) is false, throw a TypeError exception.
7167    Maybe<bool> valid =
7168        IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
7169                                       &target_desc, property_name, DONT_THROW);
7170    MAYBE_RETURN(valid, Nothing<bool>());
7171    if (!valid.FromJust()) {
7172      isolate->Throw(*isolate->factory()->NewTypeError(
7173          MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
7174      return Nothing<bool>();
7175    }
7176    // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
7177    //      true, throw a TypeError exception.
7178    if (setting_config_false && target_desc.configurable()) {
7179      isolate->Throw(*isolate->factory()->NewTypeError(
7180          MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
7181      return Nothing<bool>();
7182    }
7183  }
7184  // 17. Return true.
7185  return Just(true);
7186}
7187
7188
7189// static
7190Maybe<bool> JSProxy::AddPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy,
7191                                        Handle<Symbol> private_name,
7192                                        PropertyDescriptor* desc,
7193                                        ShouldThrow should_throw) {
7194  // Despite the generic name, this can only add private data properties.
7195  if (!PropertyDescriptor::IsDataDescriptor(desc) ||
7196      desc->ToAttributes() != DONT_ENUM) {
7197    RETURN_FAILURE(isolate, should_throw,
7198                   NewTypeError(MessageTemplate::kProxyPrivate));
7199  }
7200  DCHECK(proxy->map()->is_dictionary_map());
7201  Handle<Object> value =
7202      desc->has_value()
7203          ? desc->value()
7204          : Handle<Object>::cast(isolate->factory()->undefined_value());
7205
7206  LookupIterator it(proxy, private_name);
7207
7208  if (it.IsFound()) {
7209    DCHECK_EQ(LookupIterator::DATA, it.state());
7210    DCHECK_EQ(DONT_ENUM, it.property_details().attributes());
7211    it.WriteDataValue(value);
7212    return Just(true);
7213  }
7214
7215  Handle<NameDictionary> dict(proxy->property_dictionary());
7216  PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell);
7217  Handle<NameDictionary> result =
7218      NameDictionary::Add(dict, private_name, value, details);
7219  if (!dict.is_identical_to(result)) proxy->set_properties(*result);
7220  return Just(true);
7221}
7222
7223
7224// static
7225Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
7226                                                 Handle<JSReceiver> object,
7227                                                 Handle<Object> key,
7228                                                 PropertyDescriptor* desc) {
7229  bool success = false;
7230  DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
7231  LookupIterator it = LookupIterator::PropertyOrElement(
7232      isolate, object, key, &success, LookupIterator::HIDDEN);
7233  DCHECK(success);  // ...so creating a LookupIterator can't fail.
7234  return GetOwnPropertyDescriptor(&it, desc);
7235}
7236
7237
7238// ES6 9.1.5.1
7239// Returns true on success, false if the property didn't exist, nothing if
7240// an exception was thrown.
7241// static
7242Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
7243                                                 PropertyDescriptor* desc) {
7244  Isolate* isolate = it->isolate();
7245  // "Virtual" dispatch.
7246  if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
7247    return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
7248                                             it->GetName(), desc);
7249  }
7250
7251  // 1. (Assert)
7252  // 2. If O does not have an own property with key P, return undefined.
7253  Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
7254  MAYBE_RETURN(maybe, Nothing<bool>());
7255  PropertyAttributes attrs = maybe.FromJust();
7256  if (attrs == ABSENT) return Just(false);
7257  DCHECK(!isolate->has_pending_exception());
7258
7259  // 3. Let D be a newly created Property Descriptor with no fields.
7260  DCHECK(desc->is_empty());
7261  // 4. Let X be O's own property whose key is P.
7262  // 5. If X is a data property, then
7263  bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
7264                          it->GetAccessors()->IsAccessorPair();
7265  if (!is_accessor_pair) {
7266    // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
7267    Handle<Object> value;
7268    if (!JSObject::GetProperty(it).ToHandle(&value)) {
7269      DCHECK(isolate->has_pending_exception());
7270      return Nothing<bool>();
7271    }
7272    desc->set_value(value);
7273    // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
7274    desc->set_writable((attrs & READ_ONLY) == 0);
7275  } else {
7276    // 6. Else X is an accessor property, so
7277    Handle<AccessorPair> accessors =
7278        Handle<AccessorPair>::cast(it->GetAccessors());
7279    // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
7280    desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate));
7281    // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
7282    desc->set_set(handle(accessors->GetComponent(ACCESSOR_SETTER), isolate));
7283  }
7284
7285  // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
7286  desc->set_enumerable((attrs & DONT_ENUM) == 0);
7287  // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
7288  desc->set_configurable((attrs & DONT_DELETE) == 0);
7289  // 9. Return D.
7290  DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
7291         PropertyDescriptor::IsDataDescriptor(desc));
7292  return Just(true);
7293}
7294
7295
7296// ES6 9.5.5
7297// static
7298Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
7299                                              Handle<JSProxy> proxy,
7300                                              Handle<Name> name,
7301                                              PropertyDescriptor* desc) {
7302  DCHECK(!name->IsPrivate());
7303  STACK_CHECK(Nothing<bool>());
7304
7305  Handle<String> trap_name =
7306      isolate->factory()->getOwnPropertyDescriptor_string();
7307  // 1. (Assert)
7308  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
7309  Handle<Object> handler(proxy->handler(), isolate);
7310  // 3. If handler is null, throw a TypeError exception.
7311  // 4. Assert: Type(handler) is Object.
7312  if (proxy->IsRevoked()) {
7313    isolate->Throw(*isolate->factory()->NewTypeError(
7314        MessageTemplate::kProxyRevoked, trap_name));
7315    return Nothing<bool>();
7316  }
7317  // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
7318  Handle<JSReceiver> target(proxy->target(), isolate);
7319  // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
7320  Handle<Object> trap;
7321  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7322      isolate, trap,
7323      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
7324      Nothing<bool>());
7325  // 7. If trap is undefined, then
7326  if (trap->IsUndefined()) {
7327    // 7a. Return target.[[GetOwnProperty]](P).
7328    return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
7329  }
7330  // 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
7331  Handle<Object> trap_result_obj;
7332  Handle<Object> args[] = {target, name};
7333  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7334      isolate, trap_result_obj,
7335      Execution::Call(isolate, trap, handler, arraysize(args), args),
7336      Nothing<bool>());
7337  // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
7338  //    TypeError exception.
7339  if (!trap_result_obj->IsJSReceiver() && !trap_result_obj->IsUndefined()) {
7340    isolate->Throw(*isolate->factory()->NewTypeError(
7341        MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
7342    return Nothing<bool>();
7343  }
7344  // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
7345  PropertyDescriptor target_desc;
7346  Maybe<bool> found =
7347      JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
7348  MAYBE_RETURN(found, Nothing<bool>());
7349  // 11. If trapResultObj is undefined, then
7350  if (trap_result_obj->IsUndefined()) {
7351    // 11a. If targetDesc is undefined, return undefined.
7352    if (!found.FromJust()) return Just(false);
7353    // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
7354    //      exception.
7355    if (!target_desc.configurable()) {
7356      isolate->Throw(*isolate->factory()->NewTypeError(
7357          MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
7358      return Nothing<bool>();
7359    }
7360    // 11c. Let extensibleTarget be ? IsExtensible(target).
7361    Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
7362    MAYBE_RETURN(extensible_target, Nothing<bool>());
7363    // 11d. (Assert)
7364    // 11e. If extensibleTarget is false, throw a TypeError exception.
7365    if (!extensible_target.FromJust()) {
7366      isolate->Throw(*isolate->factory()->NewTypeError(
7367          MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
7368      return Nothing<bool>();
7369    }
7370    // 11f. Return undefined.
7371    return Just(false);
7372  }
7373  // 12. Let extensibleTarget be ? IsExtensible(target).
7374  Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
7375  MAYBE_RETURN(extensible_target, Nothing<bool>());
7376  // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
7377  if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
7378                                                desc)) {
7379    DCHECK(isolate->has_pending_exception());
7380    return Nothing<bool>();
7381  }
7382  // 14. Call CompletePropertyDescriptor(resultDesc).
7383  PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
7384  // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
7385  //     resultDesc, targetDesc).
7386  Maybe<bool> valid =
7387      IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
7388                                     desc, &target_desc, name, DONT_THROW);
7389  MAYBE_RETURN(valid, Nothing<bool>());
7390  // 16. If valid is false, throw a TypeError exception.
7391  if (!valid.FromJust()) {
7392    isolate->Throw(*isolate->factory()->NewTypeError(
7393        MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
7394    return Nothing<bool>();
7395  }
7396  // 17. If resultDesc.[[Configurable]] is false, then
7397  if (!desc->configurable()) {
7398    // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
7399    if (target_desc.is_empty() || target_desc.configurable()) {
7400      // 17a i. Throw a TypeError exception.
7401      isolate->Throw(*isolate->factory()->NewTypeError(
7402          MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
7403          name));
7404      return Nothing<bool>();
7405    }
7406  }
7407  // 18. Return resultDesc.
7408  return Just(true);
7409}
7410
7411
7412bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
7413                                            ElementsKind kind,
7414                                            Object* object) {
7415  DCHECK(IsFastObjectElementsKind(kind) ||
7416         kind == DICTIONARY_ELEMENTS);
7417  if (IsFastObjectElementsKind(kind)) {
7418    int length = IsJSArray()
7419        ? Smi::cast(JSArray::cast(this)->length())->value()
7420        : elements->length();
7421    for (int i = 0; i < length; ++i) {
7422      Object* element = elements->get(i);
7423      if (!element->IsTheHole() && element == object) return true;
7424    }
7425  } else {
7426    Object* key =
7427        SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
7428    if (!key->IsUndefined()) return true;
7429  }
7430  return false;
7431}
7432
7433
7434// Check whether this object references another object.
7435bool JSObject::ReferencesObject(Object* obj) {
7436  Map* map_of_this = map();
7437  Heap* heap = GetHeap();
7438  DisallowHeapAllocation no_allocation;
7439
7440  // Is the object the constructor for this object?
7441  if (map_of_this->GetConstructor() == obj) {
7442    return true;
7443  }
7444
7445  // Is the object the prototype for this object?
7446  if (map_of_this->prototype() == obj) {
7447    return true;
7448  }
7449
7450  // Check if the object is among the named properties.
7451  Object* key = SlowReverseLookup(obj);
7452  if (!key->IsUndefined()) {
7453    return true;
7454  }
7455
7456  // Check if the object is among the indexed properties.
7457  ElementsKind kind = GetElementsKind();
7458  switch (kind) {
7459    // Raw pixels and external arrays do not reference other
7460    // objects.
7461#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
7462    case TYPE##_ELEMENTS:                                                      \
7463      break;
7464
7465    TYPED_ARRAYS(TYPED_ARRAY_CASE)
7466#undef TYPED_ARRAY_CASE
7467
7468    case FAST_DOUBLE_ELEMENTS:
7469    case FAST_HOLEY_DOUBLE_ELEMENTS:
7470      break;
7471    case FAST_SMI_ELEMENTS:
7472    case FAST_HOLEY_SMI_ELEMENTS:
7473      break;
7474    case FAST_ELEMENTS:
7475    case FAST_HOLEY_ELEMENTS:
7476    case DICTIONARY_ELEMENTS: {
7477      FixedArray* elements = FixedArray::cast(this->elements());
7478      if (ReferencesObjectFromElements(elements, kind, obj)) return true;
7479      break;
7480    }
7481    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
7482    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
7483      FixedArray* parameter_map = FixedArray::cast(elements());
7484      // Check the mapped parameters.
7485      int length = parameter_map->length();
7486      for (int i = 2; i < length; ++i) {
7487        Object* value = parameter_map->get(i);
7488        if (!value->IsTheHole() && value == obj) return true;
7489      }
7490      // Check the arguments.
7491      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7492      kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
7493          FAST_HOLEY_ELEMENTS;
7494      if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
7495      break;
7496    }
7497  }
7498
7499  // For functions check the context.
7500  if (IsJSFunction()) {
7501    // Get the constructor function for arguments array.
7502    Map* arguments_map =
7503        heap->isolate()->context()->native_context()->sloppy_arguments_map();
7504    JSFunction* arguments_function =
7505        JSFunction::cast(arguments_map->GetConstructor());
7506
7507    // Get the context and don't check if it is the native context.
7508    JSFunction* f = JSFunction::cast(this);
7509    Context* context = f->context();
7510    if (context->IsNativeContext()) {
7511      return false;
7512    }
7513
7514    // Check the non-special context slots.
7515    for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
7516      // Only check JS objects.
7517      if (context->get(i)->IsJSObject()) {
7518        JSObject* ctxobj = JSObject::cast(context->get(i));
7519        // If it is an arguments array check the content.
7520        if (ctxobj->map()->GetConstructor() == arguments_function) {
7521          if (ctxobj->ReferencesObject(obj)) {
7522            return true;
7523          }
7524        } else if (ctxobj == obj) {
7525          return true;
7526        }
7527      }
7528    }
7529
7530    // Check the context extension (if any) if it can have references.
7531    if (context->has_extension() && !context->IsCatchContext()) {
7532      // With harmony scoping, a JSFunction may have a script context.
7533      // TODO(mvstanton): walk into the ScopeInfo.
7534      if (context->IsScriptContext()) {
7535        return false;
7536      }
7537
7538      return context->extension_object()->ReferencesObject(obj);
7539    }
7540  }
7541
7542  // No references to object.
7543  return false;
7544}
7545
7546
7547Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
7548                                          IntegrityLevel level,
7549                                          ShouldThrow should_throw) {
7550  DCHECK(level == SEALED || level == FROZEN);
7551
7552  if (receiver->IsJSObject()) {
7553    Handle<JSObject> object = Handle<JSObject>::cast(receiver);
7554    if (!object->HasSloppyArgumentsElements() &&
7555        !object->map()->is_observed() &&
7556        (!object->map()->is_strong() || level == SEALED)) {  // Fast path.
7557      if (level == SEALED) {
7558        return JSObject::PreventExtensionsWithTransition<SEALED>(object,
7559                                                                 should_throw);
7560      } else {
7561        return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
7562                                                                 should_throw);
7563      }
7564    }
7565  }
7566
7567  Isolate* isolate = receiver->GetIsolate();
7568
7569  MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
7570               Nothing<bool>());
7571
7572  Handle<FixedArray> keys;
7573  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7574      isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
7575
7576  PropertyDescriptor no_conf;
7577  no_conf.set_configurable(false);
7578
7579  PropertyDescriptor no_conf_no_write;
7580  no_conf_no_write.set_configurable(false);
7581  no_conf_no_write.set_writable(false);
7582
7583  if (level == SEALED) {
7584    for (int i = 0; i < keys->length(); ++i) {
7585      Handle<Object> key(keys->get(i), isolate);
7586      MAYBE_RETURN(
7587          DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR),
7588          Nothing<bool>());
7589    }
7590    return Just(true);
7591  }
7592
7593  for (int i = 0; i < keys->length(); ++i) {
7594    Handle<Object> key(keys->get(i), isolate);
7595    PropertyDescriptor current_desc;
7596    Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
7597        isolate, receiver, key, &current_desc);
7598    MAYBE_RETURN(owned, Nothing<bool>());
7599    if (owned.FromJust()) {
7600      PropertyDescriptor desc =
7601          PropertyDescriptor::IsAccessorDescriptor(&current_desc)
7602              ? no_conf
7603              : no_conf_no_write;
7604      MAYBE_RETURN(
7605          DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR),
7606          Nothing<bool>());
7607    }
7608  }
7609  return Just(true);
7610}
7611
7612
7613Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object,
7614                                           IntegrityLevel level) {
7615  DCHECK(level == SEALED || level == FROZEN);
7616  Isolate* isolate = object->GetIsolate();
7617
7618  Maybe<bool> extensible = JSReceiver::IsExtensible(object);
7619  MAYBE_RETURN(extensible, Nothing<bool>());
7620  if (extensible.FromJust()) return Just(false);
7621
7622  Handle<FixedArray> keys;
7623  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7624      isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>());
7625
7626  for (int i = 0; i < keys->length(); ++i) {
7627    Handle<Object> key(keys->get(i), isolate);
7628    PropertyDescriptor current_desc;
7629    Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
7630        isolate, object, key, &current_desc);
7631    MAYBE_RETURN(owned, Nothing<bool>());
7632    if (owned.FromJust()) {
7633      if (current_desc.configurable()) return Just(false);
7634      if (level == FROZEN &&
7635          PropertyDescriptor::IsDataDescriptor(&current_desc) &&
7636          current_desc.writable()) {
7637        return Just(false);
7638      }
7639    }
7640  }
7641  return Just(true);
7642}
7643
7644
7645Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
7646                                          ShouldThrow should_throw) {
7647  if (object->IsJSProxy()) {
7648    return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
7649                                      should_throw);
7650  }
7651  DCHECK(object->IsJSObject());
7652  return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
7653                                     should_throw);
7654}
7655
7656
7657Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
7658                                       ShouldThrow should_throw) {
7659  Isolate* isolate = proxy->GetIsolate();
7660  STACK_CHECK(Nothing<bool>());
7661  Factory* factory = isolate->factory();
7662  Handle<String> trap_name = factory->preventExtensions_string();
7663
7664  if (proxy->IsRevoked()) {
7665    isolate->Throw(
7666        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
7667    return Nothing<bool>();
7668  }
7669  Handle<JSReceiver> target(proxy->target(), isolate);
7670  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
7671
7672  Handle<Object> trap;
7673  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7674      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
7675  if (trap->IsUndefined()) {
7676    return JSReceiver::PreventExtensions(target, should_throw);
7677  }
7678
7679  Handle<Object> trap_result;
7680  Handle<Object> args[] = {target};
7681  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7682      isolate, trap_result,
7683      Execution::Call(isolate, trap, handler, arraysize(args), args),
7684      Nothing<bool>());
7685  if (!trap_result->BooleanValue()) {
7686    RETURN_FAILURE(
7687        isolate, should_throw,
7688        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
7689  }
7690
7691  // Enforce the invariant.
7692  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
7693  MAYBE_RETURN(target_result, Nothing<bool>());
7694  if (target_result.FromJust()) {
7695    isolate->Throw(*factory->NewTypeError(
7696        MessageTemplate::kProxyPreventExtensionsExtensible));
7697    return Nothing<bool>();
7698  }
7699  return Just(true);
7700}
7701
7702
7703Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
7704                                        ShouldThrow should_throw) {
7705  Isolate* isolate = object->GetIsolate();
7706
7707  if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
7708    return PreventExtensionsWithTransition<NONE>(object, should_throw);
7709  }
7710
7711  if (object->IsAccessCheckNeeded() &&
7712      !isolate->MayAccess(handle(isolate->context()), object)) {
7713    isolate->ReportFailedAccessCheck(object);
7714    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7715    RETURN_FAILURE(isolate, should_throw,
7716                   NewTypeError(MessageTemplate::kNoAccess));
7717  }
7718
7719  if (!object->map()->is_extensible()) return Just(true);
7720
7721  if (object->IsJSGlobalProxy()) {
7722    PrototypeIterator iter(isolate, object);
7723    if (iter.IsAtEnd()) return Just(true);
7724    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
7725    return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
7726                             should_throw);
7727  }
7728
7729  if (!object->HasFixedTypedArrayElements()) {
7730    // If there are fast elements we normalize.
7731    Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
7732    DCHECK(object->HasDictionaryElements() ||
7733           object->HasSlowArgumentsElements());
7734
7735    // Make sure that we never go back to fast case.
7736    object->RequireSlowElements(*dictionary);
7737  }
7738
7739  // Do a map transition, other objects with this map may still
7740  // be extensible.
7741  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
7742  Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
7743
7744  new_map->set_is_extensible(false);
7745  JSObject::MigrateToMap(object, new_map);
7746  DCHECK(!object->map()->is_extensible());
7747
7748  if (object->map()->is_observed()) {
7749    RETURN_ON_EXCEPTION_VALUE(
7750        isolate,
7751        EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
7752                            isolate->factory()->the_hole_value()),
7753        Nothing<bool>());
7754  }
7755  return Just(true);
7756}
7757
7758
7759Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
7760  if (object->IsJSProxy()) {
7761    return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
7762  }
7763  return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
7764}
7765
7766
7767Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
7768  Isolate* isolate = proxy->GetIsolate();
7769  STACK_CHECK(Nothing<bool>());
7770  Factory* factory = isolate->factory();
7771  Handle<String> trap_name = factory->isExtensible_string();
7772
7773  if (proxy->IsRevoked()) {
7774    isolate->Throw(
7775        *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
7776    return Nothing<bool>();
7777  }
7778  Handle<JSReceiver> target(proxy->target(), isolate);
7779  Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
7780
7781  Handle<Object> trap;
7782  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7783      isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
7784  if (trap->IsUndefined()) {
7785    return JSReceiver::IsExtensible(target);
7786  }
7787
7788  Handle<Object> trap_result;
7789  Handle<Object> args[] = {target};
7790  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7791      isolate, trap_result,
7792      Execution::Call(isolate, trap, handler, arraysize(args), args),
7793      Nothing<bool>());
7794
7795  // Enforce the invariant.
7796  Maybe<bool> target_result = JSReceiver::IsExtensible(target);
7797  MAYBE_RETURN(target_result, Nothing<bool>());
7798  if (target_result.FromJust() != trap_result->BooleanValue()) {
7799    isolate->Throw(
7800        *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
7801                               factory->ToBoolean(target_result.FromJust())));
7802    return Nothing<bool>();
7803  }
7804  return target_result;
7805}
7806
7807
7808bool JSObject::IsExtensible(Handle<JSObject> object) {
7809  Isolate* isolate = object->GetIsolate();
7810  if (object->IsAccessCheckNeeded() &&
7811      !isolate->MayAccess(handle(isolate->context()), object)) {
7812    return true;
7813  }
7814  if (object->IsJSGlobalProxy()) {
7815    PrototypeIterator iter(isolate, *object);
7816    if (iter.IsAtEnd()) return false;
7817    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
7818    return iter.GetCurrent<JSObject>()->map()->is_extensible();
7819  }
7820  return object->map()->is_extensible();
7821}
7822
7823
7824template <typename Dictionary>
7825static void ApplyAttributesToDictionary(Dictionary* dictionary,
7826                                        const PropertyAttributes attributes) {
7827  int capacity = dictionary->Capacity();
7828  for (int i = 0; i < capacity; i++) {
7829    Object* k = dictionary->KeyAt(i);
7830    if (dictionary->IsKey(k) &&
7831        !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
7832      PropertyDetails details = dictionary->DetailsAt(i);
7833      int attrs = attributes;
7834      // READ_ONLY is an invalid attribute for JS setters/getters.
7835      if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
7836        Object* v = dictionary->ValueAt(i);
7837        if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
7838        if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
7839      }
7840      details = details.CopyAddAttributes(
7841          static_cast<PropertyAttributes>(attrs));
7842      dictionary->DetailsAtPut(i, details);
7843    }
7844  }
7845}
7846
7847
7848template <PropertyAttributes attrs>
7849Maybe<bool> JSObject::PreventExtensionsWithTransition(
7850    Handle<JSObject> object, ShouldThrow should_throw) {
7851  STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
7852
7853  // Sealing/freezing sloppy arguments should be handled elsewhere.
7854  DCHECK(!object->HasSloppyArgumentsElements());
7855  DCHECK(!object->map()->is_observed());
7856
7857  Isolate* isolate = object->GetIsolate();
7858  if (object->IsAccessCheckNeeded() &&
7859      !isolate->MayAccess(handle(isolate->context()), object)) {
7860    isolate->ReportFailedAccessCheck(object);
7861    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7862    RETURN_FAILURE(isolate, should_throw,
7863                   NewTypeError(MessageTemplate::kNoAccess));
7864  }
7865
7866  if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
7867
7868  if (object->IsJSGlobalProxy()) {
7869    PrototypeIterator iter(isolate, object);
7870    if (iter.IsAtEnd()) return Just(true);
7871    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
7872    return PreventExtensionsWithTransition<attrs>(
7873        PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
7874  }
7875
7876  Handle<SeededNumberDictionary> new_element_dictionary;
7877  if (!object->HasFixedTypedArrayElements() &&
7878      !object->HasDictionaryElements()) {
7879    int length =
7880        object->IsJSArray()
7881            ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
7882            : object->elements()->length();
7883    new_element_dictionary =
7884        length == 0 ? isolate->factory()->empty_slow_element_dictionary()
7885                    : GetNormalizedElementDictionary(
7886                          object, handle(object->elements()));
7887  }
7888
7889  Handle<Symbol> transition_marker;
7890  if (attrs == NONE) {
7891    transition_marker = isolate->factory()->nonextensible_symbol();
7892  } else if (attrs == SEALED) {
7893    transition_marker = isolate->factory()->sealed_symbol();
7894  } else {
7895    DCHECK(attrs == FROZEN);
7896    transition_marker = isolate->factory()->frozen_symbol();
7897  }
7898
7899  Handle<Map> old_map(object->map(), isolate);
7900  Map* transition =
7901      TransitionArray::SearchSpecial(*old_map, *transition_marker);
7902  if (transition != NULL) {
7903    Handle<Map> transition_map(transition, isolate);
7904    DCHECK(transition_map->has_dictionary_elements() ||
7905           transition_map->has_fixed_typed_array_elements());
7906    DCHECK(!transition_map->is_extensible());
7907    JSObject::MigrateToMap(object, transition_map);
7908  } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
7909    // Create a new descriptor array with the appropriate property attributes
7910    Handle<Map> new_map = Map::CopyForPreventExtensions(
7911        old_map, attrs, transition_marker, "CopyForPreventExtensions");
7912    JSObject::MigrateToMap(object, new_map);
7913  } else {
7914    DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
7915    // Slow path: need to normalize properties for safety
7916    NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
7917                        "SlowPreventExtensions");
7918
7919    // Create a new map, since other objects with this map may be extensible.
7920    // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
7921    Handle<Map> new_map =
7922        Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
7923    new_map->set_is_extensible(false);
7924    if (!new_element_dictionary.is_null()) {
7925      new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7926    }
7927    JSObject::MigrateToMap(object, new_map);
7928
7929    if (attrs != NONE) {
7930      if (object->IsJSGlobalObject()) {
7931        ApplyAttributesToDictionary(object->global_dictionary(), attrs);
7932      } else {
7933        ApplyAttributesToDictionary(object->property_dictionary(), attrs);
7934      }
7935    }
7936  }
7937
7938  // Both seal and preventExtensions always go through without modifications to
7939  // typed array elements. Freeze works only if there are no actual elements.
7940  if (object->HasFixedTypedArrayElements()) {
7941    if (attrs == FROZEN &&
7942        JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) {
7943      isolate->Throw(*isolate->factory()->NewTypeError(
7944          MessageTemplate::kCannotFreezeArrayBufferView));
7945      return Nothing<bool>();
7946    }
7947    return Just(true);
7948  }
7949
7950  DCHECK(object->map()->has_dictionary_elements());
7951  if (!new_element_dictionary.is_null()) {
7952    object->set_elements(*new_element_dictionary);
7953  }
7954
7955  if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
7956    SeededNumberDictionary* dictionary = object->element_dictionary();
7957    // Make sure we never go back to the fast case
7958    object->RequireSlowElements(dictionary);
7959    if (attrs != NONE) {
7960      ApplyAttributesToDictionary(dictionary, attrs);
7961    }
7962  }
7963
7964  return Just(true);
7965}
7966
7967
7968void JSObject::SetObserved(Handle<JSObject> object) {
7969  DCHECK(!object->IsJSGlobalProxy());
7970  DCHECK(!object->IsJSGlobalObject());
7971  Isolate* isolate = object->GetIsolate();
7972  Handle<Map> new_map;
7973  Handle<Map> old_map(object->map(), isolate);
7974  DCHECK(!old_map->is_observed());
7975  Map* transition = TransitionArray::SearchSpecial(
7976      *old_map, isolate->heap()->observed_symbol());
7977  if (transition != NULL) {
7978    new_map = handle(transition, isolate);
7979    DCHECK(new_map->is_observed());
7980  } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
7981    new_map = Map::CopyForObserved(old_map);
7982  } else {
7983    new_map = Map::Copy(old_map, "SlowObserved");
7984    new_map->set_is_observed();
7985  }
7986  JSObject::MigrateToMap(object, new_map);
7987}
7988
7989
7990Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
7991                                        Representation representation,
7992                                        FieldIndex index) {
7993  Isolate* isolate = object->GetIsolate();
7994  if (object->IsUnboxedDoubleField(index)) {
7995    double value = object->RawFastDoublePropertyAt(index);
7996    return isolate->factory()->NewHeapNumber(value);
7997  }
7998  Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
7999  return Object::WrapForRead(isolate, raw_value, representation);
8000}
8001
8002
8003template<class ContextObject>
8004class JSObjectWalkVisitor {
8005 public:
8006  JSObjectWalkVisitor(ContextObject* site_context, bool copying,
8007                      JSObject::DeepCopyHints hints)
8008    : site_context_(site_context),
8009      copying_(copying),
8010      hints_(hints) {}
8011
8012  MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
8013
8014 protected:
8015  MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
8016      Handle<JSObject> object,
8017      Handle<JSObject> value) {
8018    Handle<AllocationSite> current_site = site_context()->EnterNewScope();
8019    MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
8020    site_context()->ExitScope(current_site, value);
8021    return copy_of_value;
8022  }
8023
8024  inline ContextObject* site_context() { return site_context_; }
8025  inline Isolate* isolate() { return site_context()->isolate(); }
8026
8027  inline bool copying() const { return copying_; }
8028
8029 private:
8030  ContextObject* site_context_;
8031  const bool copying_;
8032  const JSObject::DeepCopyHints hints_;
8033};
8034
8035
8036template <class ContextObject>
8037MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
8038    Handle<JSObject> object) {
8039  Isolate* isolate = this->isolate();
8040  bool copying = this->copying();
8041  bool shallow = hints_ == JSObject::kObjectIsShallow;
8042
8043  if (!shallow) {
8044    StackLimitCheck check(isolate);
8045
8046    if (check.HasOverflowed()) {
8047      isolate->StackOverflow();
8048      return MaybeHandle<JSObject>();
8049    }
8050  }
8051
8052  if (object->map()->is_deprecated()) {
8053    JSObject::MigrateInstance(object);
8054  }
8055
8056  Handle<JSObject> copy;
8057  if (copying) {
8058    Handle<AllocationSite> site_to_pass;
8059    if (site_context()->ShouldCreateMemento(object)) {
8060      site_to_pass = site_context()->current();
8061    }
8062    copy = isolate->factory()->CopyJSObjectWithAllocationSite(
8063        object, site_to_pass);
8064  } else {
8065    copy = object;
8066  }
8067
8068  DCHECK(copying || copy.is_identical_to(object));
8069
8070  ElementsKind kind = copy->GetElementsKind();
8071  if (copying && IsFastSmiOrObjectElementsKind(kind) &&
8072      FixedArray::cast(copy->elements())->map() ==
8073        isolate->heap()->fixed_cow_array_map()) {
8074    isolate->counters()->cow_arrays_created_runtime()->Increment();
8075  }
8076
8077  if (!shallow) {
8078    HandleScope scope(isolate);
8079
8080    // Deep copy own properties.
8081    if (copy->HasFastProperties()) {
8082      Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
8083      int limit = copy->map()->NumberOfOwnDescriptors();
8084      for (int i = 0; i < limit; i++) {
8085        PropertyDetails details = descriptors->GetDetails(i);
8086        if (details.type() != DATA) continue;
8087        FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
8088        if (object->IsUnboxedDoubleField(index)) {
8089          if (copying) {
8090            double value = object->RawFastDoublePropertyAt(index);
8091            copy->RawFastDoublePropertyAtPut(index, value);
8092          }
8093        } else {
8094          Handle<Object> value(object->RawFastPropertyAt(index), isolate);
8095          if (value->IsJSObject()) {
8096            ASSIGN_RETURN_ON_EXCEPTION(
8097                isolate, value,
8098                VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8099                JSObject);
8100            if (copying) {
8101              copy->FastPropertyAtPut(index, *value);
8102            }
8103          } else {
8104            if (copying) {
8105              Representation representation = details.representation();
8106              value = Object::NewStorageFor(isolate, value, representation);
8107              copy->FastPropertyAtPut(index, *value);
8108            }
8109          }
8110        }
8111      }
8112    } else {
8113      // Only deep copy fields from the object literal expression.
8114      // In particular, don't try to copy the length attribute of
8115      // an array.
8116      PropertyFilter filter = static_cast<PropertyFilter>(
8117          ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
8118      KeyAccumulator accumulator(isolate, filter);
8119      accumulator.NextPrototype();
8120      copy->CollectOwnPropertyNames(&accumulator, filter);
8121      Handle<FixedArray> names = accumulator.GetKeys();
8122      for (int i = 0; i < names->length(); i++) {
8123        DCHECK(names->get(i)->IsName());
8124        Handle<Name> name(Name::cast(names->get(i)));
8125        Handle<Object> value =
8126            Object::GetProperty(copy, name).ToHandleChecked();
8127        if (value->IsJSObject()) {
8128          Handle<JSObject> result;
8129          ASSIGN_RETURN_ON_EXCEPTION(
8130              isolate, result,
8131              VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8132              JSObject);
8133          if (copying) {
8134            // Creating object copy for literals. No strict mode needed.
8135            JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
8136          }
8137        }
8138      }
8139    }
8140
8141    // Deep copy own elements.
8142    // Pixel elements cannot be created using an object literal.
8143    DCHECK(!copy->HasFixedTypedArrayElements());
8144    switch (kind) {
8145      case FAST_SMI_ELEMENTS:
8146      case FAST_ELEMENTS:
8147      case FAST_HOLEY_SMI_ELEMENTS:
8148      case FAST_HOLEY_ELEMENTS: {
8149        Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
8150        if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
8151#ifdef DEBUG
8152          for (int i = 0; i < elements->length(); i++) {
8153            DCHECK(!elements->get(i)->IsJSObject());
8154          }
8155#endif
8156        } else {
8157          for (int i = 0; i < elements->length(); i++) {
8158            Handle<Object> value(elements->get(i), isolate);
8159            DCHECK(value->IsSmi() ||
8160                   value->IsTheHole() ||
8161                   (IsFastObjectElementsKind(copy->GetElementsKind())));
8162            if (value->IsJSObject()) {
8163              Handle<JSObject> result;
8164              ASSIGN_RETURN_ON_EXCEPTION(
8165                  isolate, result,
8166                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8167                  JSObject);
8168              if (copying) {
8169                elements->set(i, *result);
8170              }
8171            }
8172          }
8173        }
8174        break;
8175      }
8176      case DICTIONARY_ELEMENTS: {
8177        Handle<SeededNumberDictionary> element_dictionary(
8178            copy->element_dictionary());
8179        int capacity = element_dictionary->Capacity();
8180        for (int i = 0; i < capacity; i++) {
8181          Object* k = element_dictionary->KeyAt(i);
8182          if (element_dictionary->IsKey(k)) {
8183            Handle<Object> value(element_dictionary->ValueAt(i), isolate);
8184            if (value->IsJSObject()) {
8185              Handle<JSObject> result;
8186              ASSIGN_RETURN_ON_EXCEPTION(
8187                  isolate, result,
8188                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
8189                  JSObject);
8190              if (copying) {
8191                element_dictionary->ValueAtPut(i, *result);
8192              }
8193            }
8194          }
8195        }
8196        break;
8197      }
8198      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8199      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8200        UNIMPLEMENTED();
8201        break;
8202
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      case FAST_DOUBLE_ELEMENTS:
8211      case FAST_HOLEY_DOUBLE_ELEMENTS:
8212        // No contained objects, nothing to do.
8213        break;
8214    }
8215  }
8216
8217  return copy;
8218}
8219
8220
8221MaybeHandle<JSObject> JSObject::DeepWalk(
8222    Handle<JSObject> object,
8223    AllocationSiteCreationContext* site_context) {
8224  JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
8225                                                       kNoHints);
8226  MaybeHandle<JSObject> result = v.StructureWalk(object);
8227  Handle<JSObject> for_assert;
8228  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
8229  return result;
8230}
8231
8232
8233MaybeHandle<JSObject> JSObject::DeepCopy(
8234    Handle<JSObject> object,
8235    AllocationSiteUsageContext* site_context,
8236    DeepCopyHints hints) {
8237  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
8238  MaybeHandle<JSObject> copy = v.StructureWalk(object);
8239  Handle<JSObject> for_assert;
8240  DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
8241  return copy;
8242}
8243
8244
8245// static
8246MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
8247                                            ToPrimitiveHint hint) {
8248  Isolate* const isolate = receiver->GetIsolate();
8249  Handle<Object> exotic_to_prim;
8250  ASSIGN_RETURN_ON_EXCEPTION(
8251      isolate, exotic_to_prim,
8252      GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
8253  if (!exotic_to_prim->IsUndefined()) {
8254    Handle<Object> hint_string;
8255    switch (hint) {
8256      case ToPrimitiveHint::kDefault:
8257        hint_string = isolate->factory()->default_string();
8258        break;
8259      case ToPrimitiveHint::kNumber:
8260        hint_string = isolate->factory()->number_string();
8261        break;
8262      case ToPrimitiveHint::kString:
8263        hint_string = isolate->factory()->string_string();
8264        break;
8265    }
8266    Handle<Object> result;
8267    ASSIGN_RETURN_ON_EXCEPTION(
8268        isolate, result,
8269        Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
8270        Object);
8271    if (result->IsPrimitive()) return result;
8272    THROW_NEW_ERROR(isolate,
8273                    NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8274                    Object);
8275  }
8276  return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
8277                                           ? OrdinaryToPrimitiveHint::kString
8278                                           : OrdinaryToPrimitiveHint::kNumber);
8279}
8280
8281
8282// static
8283MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
8284    Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
8285  Isolate* const isolate = receiver->GetIsolate();
8286  Handle<String> method_names[2];
8287  switch (hint) {
8288    case OrdinaryToPrimitiveHint::kNumber:
8289      method_names[0] = isolate->factory()->valueOf_string();
8290      method_names[1] = isolate->factory()->toString_string();
8291      break;
8292    case OrdinaryToPrimitiveHint::kString:
8293      method_names[0] = isolate->factory()->toString_string();
8294      method_names[1] = isolate->factory()->valueOf_string();
8295      break;
8296  }
8297  for (Handle<String> name : method_names) {
8298    Handle<Object> method;
8299    ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
8300                               JSReceiver::GetProperty(receiver, name), Object);
8301    if (method->IsCallable()) {
8302      Handle<Object> result;
8303      ASSIGN_RETURN_ON_EXCEPTION(
8304          isolate, result, Execution::Call(isolate, method, receiver, 0, NULL),
8305          Object);
8306      if (result->IsPrimitive()) return result;
8307    }
8308  }
8309  THROW_NEW_ERROR(isolate,
8310                  NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8311                  Object);
8312}
8313
8314
8315// TODO(cbruni/jkummerow): Consider moving this into elements.cc.
8316bool HasEnumerableElements(JSObject* object) {
8317  if (object->IsJSValue()) {
8318    Object* value = JSValue::cast(object)->value();
8319    if (value->IsString()) {
8320      if (String::cast(value)->length() > 0) return true;
8321    }
8322  }
8323  switch (object->GetElementsKind()) {
8324    case FAST_SMI_ELEMENTS:
8325    case FAST_ELEMENTS:
8326    case FAST_DOUBLE_ELEMENTS: {
8327      int length = object->IsJSArray()
8328                       ? Smi::cast(JSArray::cast(object)->length())->value()
8329                       : object->elements()->length();
8330      return length > 0;
8331    }
8332    case FAST_HOLEY_SMI_ELEMENTS:
8333    case FAST_HOLEY_ELEMENTS: {
8334      FixedArray* elements = FixedArray::cast(object->elements());
8335      int length = object->IsJSArray()
8336                       ? Smi::cast(JSArray::cast(object)->length())->value()
8337                       : elements->length();
8338      for (int i = 0; i < length; i++) {
8339        if (!elements->is_the_hole(i)) return true;
8340      }
8341      return false;
8342    }
8343    case FAST_HOLEY_DOUBLE_ELEMENTS: {
8344      int length = object->IsJSArray()
8345                       ? Smi::cast(JSArray::cast(object)->length())->value()
8346                       : object->elements()->length();
8347      // Zero-length arrays would use the empty FixedArray...
8348      if (length == 0) return false;
8349      // ...so only cast to FixedDoubleArray otherwise.
8350      FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements());
8351      for (int i = 0; i < length; i++) {
8352        if (!elements->is_the_hole(i)) return true;
8353      }
8354      return false;
8355    }
8356#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
8357    case TYPE##_ELEMENTS:
8358
8359      TYPED_ARRAYS(TYPED_ARRAY_CASE)
8360#undef TYPED_ARRAY_CASE
8361      {
8362        int length = object->elements()->length();
8363        return length > 0;
8364      }
8365    case DICTIONARY_ELEMENTS: {
8366      SeededNumberDictionary* elements =
8367          SeededNumberDictionary::cast(object->elements());
8368      return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0;
8369    }
8370    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
8371    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
8372      // We're approximating non-empty arguments objects here.
8373      return true;
8374  }
8375  UNREACHABLE();
8376  return true;
8377}
8378
8379
8380// Tests for the fast common case for property enumeration:
8381// - This object and all prototypes has an enum cache (which means that
8382//   it is no proxy, has no interceptors and needs no access checks).
8383// - This object has no elements.
8384// - No prototype has enumerable properties/elements.
8385bool JSReceiver::IsSimpleEnum() {
8386  for (PrototypeIterator iter(GetIsolate(), this,
8387                              PrototypeIterator::START_AT_RECEIVER);
8388       !iter.IsAtEnd(); iter.Advance()) {
8389    if (!iter.GetCurrent()->IsJSObject()) return false;
8390    JSObject* current = iter.GetCurrent<JSObject>();
8391    int enum_length = current->map()->EnumLength();
8392    if (enum_length == kInvalidEnumCacheSentinel) return false;
8393    if (current->IsAccessCheckNeeded()) return false;
8394    DCHECK(!current->HasNamedInterceptor());
8395    DCHECK(!current->HasIndexedInterceptor());
8396    if (HasEnumerableElements(current)) return false;
8397    if (current != this && enum_length != 0) return false;
8398  }
8399  return true;
8400}
8401
8402
8403int Map::NumberOfDescribedProperties(DescriptorFlag which,
8404                                     PropertyFilter filter) {
8405  int result = 0;
8406  DescriptorArray* descs = instance_descriptors();
8407  int limit = which == ALL_DESCRIPTORS
8408      ? descs->number_of_descriptors()
8409      : NumberOfOwnDescriptors();
8410  for (int i = 0; i < limit; i++) {
8411    if ((descs->GetDetails(i).attributes() & filter) == 0 &&
8412        !descs->GetKey(i)->FilterKey(filter)) {
8413      result++;
8414    }
8415  }
8416  return result;
8417}
8418
8419
8420int Map::NextFreePropertyIndex() {
8421  int free_index = 0;
8422  int number_of_own_descriptors = NumberOfOwnDescriptors();
8423  DescriptorArray* descs = instance_descriptors();
8424  for (int i = 0; i < number_of_own_descriptors; i++) {
8425    PropertyDetails details = descs->GetDetails(i);
8426    if (details.location() == kField) {
8427      int candidate = details.field_index() + details.field_width_in_words();
8428      if (candidate > free_index) free_index = candidate;
8429    }
8430  }
8431  return free_index;
8432}
8433
8434
8435static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
8436  int len = array->length();
8437  for (int i = 0; i < len; i++) {
8438    Object* e = array->get(i);
8439    if (!(e->IsName() || e->IsNumber())) return false;
8440  }
8441  return true;
8442}
8443
8444
8445static Handle<FixedArray> ReduceFixedArrayTo(
8446    Handle<FixedArray> array, int length) {
8447  DCHECK(array->length() >= length);
8448  if (array->length() == length) return array;
8449
8450  Handle<FixedArray> new_array =
8451      array->GetIsolate()->factory()->NewFixedArray(length);
8452  for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
8453  return new_array;
8454}
8455
8456
8457namespace {
8458
8459Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
8460                                           Handle<JSObject> object,
8461                                           bool cache_enum_length) {
8462  Handle<Map> map(object->map());
8463  Handle<DescriptorArray> descs =
8464      Handle<DescriptorArray>(map->instance_descriptors(), isolate);
8465  int own_property_count = map->EnumLength();
8466  // If the enum length of the given map is set to kInvalidEnumCache, this
8467  // means that the map itself has never used the present enum cache. The
8468  // first step to using the cache is to set the enum length of the map by
8469  // counting the number of own descriptors that are ENUMERABLE_STRINGS.
8470  if (own_property_count == kInvalidEnumCacheSentinel) {
8471    own_property_count =
8472        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS);
8473  } else {
8474    DCHECK(
8475        own_property_count ==
8476        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS));
8477  }
8478
8479  if (descs->HasEnumCache()) {
8480    Handle<FixedArray> keys(descs->GetEnumCache(), isolate);
8481    // In case the number of properties required in the enum are actually
8482    // present, we can reuse the enum cache. Otherwise, this means that the
8483    // enum cache was generated for a previous (smaller) version of the
8484    // Descriptor Array. In that case we regenerate the enum cache.
8485    if (own_property_count <= keys->length()) {
8486      isolate->counters()->enum_cache_hits()->Increment();
8487      if (cache_enum_length) map->SetEnumLength(own_property_count);
8488      return ReduceFixedArrayTo(keys, own_property_count);
8489    }
8490  }
8491
8492  if (descs->IsEmpty()) {
8493    isolate->counters()->enum_cache_hits()->Increment();
8494    if (cache_enum_length) map->SetEnumLength(0);
8495    return isolate->factory()->empty_fixed_array();
8496  }
8497
8498  isolate->counters()->enum_cache_misses()->Increment();
8499
8500  Handle<FixedArray> storage =
8501      isolate->factory()->NewFixedArray(own_property_count);
8502  Handle<FixedArray> indices =
8503      isolate->factory()->NewFixedArray(own_property_count);
8504
8505  int size = map->NumberOfOwnDescriptors();
8506  int index = 0;
8507
8508  for (int i = 0; i < size; i++) {
8509    PropertyDetails details = descs->GetDetails(i);
8510    Object* key = descs->GetKey(i);
8511    if (details.IsDontEnum() || key->IsSymbol()) continue;
8512    storage->set(index, key);
8513    if (!indices.is_null()) {
8514      if (details.type() != DATA) {
8515        indices = Handle<FixedArray>();
8516      } else {
8517        FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
8518        int load_by_field_index = field_index.GetLoadByFieldIndex();
8519        indices->set(index, Smi::FromInt(load_by_field_index));
8520      }
8521    }
8522    index++;
8523  }
8524  DCHECK(index == storage->length());
8525
8526  DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
8527  if (cache_enum_length) {
8528    map->SetEnumLength(own_property_count);
8529  }
8530  return storage;
8531}
8532
8533}  // namespace
8534
8535
8536Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
8537                                                 bool cache_enum_length) {
8538  Isolate* isolate = object->GetIsolate();
8539  if (object->HasFastProperties()) {
8540    return GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
8541  } else if (object->IsJSGlobalObject()) {
8542    Handle<GlobalDictionary> dictionary(object->global_dictionary());
8543    int length = dictionary->NumberOfEnumElements();
8544    if (length == 0) {
8545      return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
8546    }
8547    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
8548    dictionary->CopyEnumKeysTo(*storage);
8549    return storage;
8550  } else {
8551    Handle<NameDictionary> dictionary(object->property_dictionary());
8552    int length = dictionary->NumberOfEnumElements();
8553    if (length == 0) {
8554      return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
8555    }
8556    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
8557    dictionary->CopyEnumKeysTo(*storage);
8558    return storage;
8559  }
8560}
8561
8562
8563enum IndexedOrNamed { kIndexed, kNamed };
8564
8565
8566// Returns |true| on success, |nothing| on exception.
8567template <class Callback, IndexedOrNamed type>
8568static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate,
8569                                          Handle<JSReceiver> receiver,
8570                                          Handle<JSObject> object,
8571                                          PropertyFilter filter,
8572                                          KeyAccumulator* accumulator) {
8573  if (type == kIndexed) {
8574    if (!object->HasIndexedInterceptor()) return Just(true);
8575  } else {
8576    if (!object->HasNamedInterceptor()) return Just(true);
8577  }
8578  Handle<InterceptorInfo> interceptor(type == kIndexed
8579                                          ? object->GetIndexedInterceptor()
8580                                          : object->GetNamedInterceptor(),
8581                                      isolate);
8582  if ((filter & ONLY_ALL_CAN_READ) && !interceptor->all_can_read()) {
8583    return Just(true);
8584  }
8585  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
8586                                 *object);
8587  v8::Local<v8::Object> result;
8588  if (!interceptor->enumerator()->IsUndefined()) {
8589    Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator());
8590    const char* log_tag = type == kIndexed ? "interceptor-indexed-enum"
8591                                           : "interceptor-named-enum";
8592    LOG(isolate, ApiObjectAccess(log_tag, *object));
8593    result = args.Call(enum_fun);
8594  }
8595  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
8596  if (result.IsEmpty()) return Just(true);
8597  DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
8598         (v8::Utils::OpenHandle(*result)->IsJSObject() &&
8599          Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))
8600              ->HasSloppyArgumentsElements()));
8601  // The accumulator takes care of string/symbol filtering.
8602  if (type == kIndexed) {
8603    accumulator->AddElementKeysFromInterceptor(
8604        Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)));
8605  } else {
8606    accumulator->AddKeys(
8607        Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)));
8608  }
8609  return Just(true);
8610}
8611
8612
8613// Returns |true| on success, |false| if prototype walking should be stopped,
8614// |nothing| if an exception was thrown.
8615static Maybe<bool> GetKeysFromJSObject(Isolate* isolate,
8616                                       Handle<JSReceiver> receiver,
8617                                       Handle<JSObject> object,
8618                                       PropertyFilter* filter,
8619                                       JSReceiver::KeyCollectionType type,
8620                                       KeyAccumulator* accumulator) {
8621  accumulator->NextPrototype();
8622  // Check access rights if required.
8623  if (object->IsAccessCheckNeeded() &&
8624      !isolate->MayAccess(handle(isolate->context()), object)) {
8625    // The cross-origin spec says that [[Enumerate]] shall return an empty
8626    // iterator when it doesn't have access...
8627    if (type == JSReceiver::INCLUDE_PROTOS) {
8628      return Just(false);
8629    }
8630    // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties.
8631    DCHECK(type == JSReceiver::OWN_ONLY);
8632    *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ);
8633  }
8634
8635  JSObject::CollectOwnElementKeys(object, accumulator, *filter);
8636
8637  // Add the element keys from the interceptor.
8638  Maybe<bool> success =
8639      GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>(
8640          isolate, receiver, object, *filter, accumulator);
8641  MAYBE_RETURN(success, Nothing<bool>());
8642
8643  if (*filter == ENUMERABLE_STRINGS) {
8644    // We can cache the computed property keys if access checks are
8645    // not needed and no interceptors are involved.
8646    //
8647    // We do not use the cache if the object has elements and
8648    // therefore it does not make sense to cache the property names
8649    // for arguments objects.  Arguments objects will always have
8650    // elements.
8651    // Wrapped strings have elements, but don't have an elements
8652    // array or dictionary.  So the fast inline test for whether to
8653    // use the cache says yes, so we should not create a cache.
8654    Handle<JSFunction> arguments_function(
8655        JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
8656    bool has_hidden_prototype = false;
8657    Object* prototype = object->map()->prototype();
8658    if (prototype->IsJSObject()) {
8659      has_hidden_prototype =
8660          JSObject::cast(prototype)->map()->is_hidden_prototype();
8661    }
8662    bool cache_enum_length =
8663        ((object->map()->GetConstructor() != *arguments_function) &&
8664         !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
8665         !object->HasNamedInterceptor() && !object->HasIndexedInterceptor() &&
8666         !has_hidden_prototype);
8667    // Compute the property keys and cache them if possible.
8668    Handle<FixedArray> enum_keys =
8669        JSObject::GetEnumPropertyKeys(object, cache_enum_length);
8670    accumulator->AddKeys(enum_keys);
8671  } else {
8672    object->CollectOwnPropertyNames(accumulator, *filter);
8673  }
8674
8675  // Add the property keys from the interceptor.
8676  success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
8677                                   kNamed>(isolate, receiver, object, *filter,
8678                                           accumulator);
8679  MAYBE_RETURN(success, Nothing<bool>());
8680  return Just(true);
8681}
8682
8683
8684// Helper function for JSReceiver::GetKeys() below. Can be called recursively.
8685// Returns |true| or |nothing|.
8686static Maybe<bool> GetKeys_Internal(Isolate* isolate,
8687                                    Handle<JSReceiver> receiver,
8688                                    Handle<JSReceiver> object,
8689                                    JSReceiver::KeyCollectionType type,
8690                                    PropertyFilter filter,
8691                                    KeyAccumulator* accumulator) {
8692  PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY
8693                                          ? PrototypeIterator::END_AT_NON_HIDDEN
8694                                          : PrototypeIterator::END_AT_NULL;
8695  for (PrototypeIterator iter(isolate, object,
8696                              PrototypeIterator::START_AT_RECEIVER);
8697       !iter.IsAtEnd(end); iter.Advance()) {
8698    Handle<JSReceiver> current =
8699        PrototypeIterator::GetCurrent<JSReceiver>(iter);
8700    Maybe<bool> result = Just(false);  // Dummy initialization.
8701    if (current->IsJSProxy()) {
8702      if (type == JSReceiver::OWN_ONLY) {
8703        result = JSProxy::OwnPropertyKeys(isolate, receiver,
8704                                          Handle<JSProxy>::cast(current),
8705                                          filter, accumulator);
8706      } else {
8707        DCHECK(type == JSReceiver::INCLUDE_PROTOS);
8708        result = JSProxy::Enumerate(
8709            isolate, receiver, Handle<JSProxy>::cast(current), accumulator);
8710      }
8711    } else {
8712      DCHECK(current->IsJSObject());
8713      result = GetKeysFromJSObject(isolate, receiver,
8714                                   Handle<JSObject>::cast(current), &filter,
8715                                   type, accumulator);
8716    }
8717    MAYBE_RETURN(result, Nothing<bool>());
8718    if (!result.FromJust()) break;  // |false| means "stop iterating".
8719  }
8720  return Just(true);
8721}
8722
8723
8724// ES6 9.5.11
8725// Returns false in case of exception.
8726// static
8727Maybe<bool> JSProxy::Enumerate(Isolate* isolate, Handle<JSReceiver> receiver,
8728                               Handle<JSProxy> proxy,
8729                               KeyAccumulator* accumulator) {
8730  STACK_CHECK(Nothing<bool>());
8731  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
8732  Handle<Object> handler(proxy->handler(), isolate);
8733  // 2. If handler is null, throw a TypeError exception.
8734  // 3. Assert: Type(handler) is Object.
8735  if (proxy->IsRevoked()) {
8736    isolate->Throw(*isolate->factory()->NewTypeError(
8737        MessageTemplate::kProxyRevoked,
8738        isolate->factory()->enumerate_string()));
8739    return Nothing<bool>();
8740  }
8741  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
8742  Handle<JSReceiver> target(proxy->target(), isolate);
8743  // 5. Let trap be ? GetMethod(handler, "enumerate").
8744  Handle<Object> trap;
8745  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8746      isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
8747                                       isolate->factory()->enumerate_string()),
8748      Nothing<bool>());
8749  // 6. If trap is undefined, then
8750  if (trap->IsUndefined()) {
8751    // 6a. Return target.[[Enumerate]]().
8752    return GetKeys_Internal(isolate, receiver, target, INCLUDE_PROTOS,
8753                            ENUMERABLE_STRINGS, accumulator);
8754  }
8755  // The "proxy_enumerate" helper calls the trap (steps 7 - 9), which returns
8756  // a generator; it then iterates over that generator until it's exhausted
8757  // and returns an array containing the generated values.
8758  Handle<Object> trap_result_array;
8759  Handle<Object> args[] = {trap, handler, target};
8760  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8761      isolate, trap_result_array,
8762      Execution::Call(isolate, isolate->proxy_enumerate(),
8763                      isolate->factory()->undefined_value(), arraysize(args),
8764                      args),
8765      Nothing<bool>());
8766  accumulator->NextPrototype();
8767  accumulator->AddKeysFromProxy(Handle<JSObject>::cast(trap_result_array));
8768  return Just(true);
8769}
8770
8771
8772// ES6 9.5.12
8773// Returns |true| on success, |nothing| in case of exception.
8774// static
8775Maybe<bool> JSProxy::OwnPropertyKeys(Isolate* isolate,
8776                                     Handle<JSReceiver> receiver,
8777                                     Handle<JSProxy> proxy,
8778                                     PropertyFilter filter,
8779                                     KeyAccumulator* accumulator) {
8780  STACK_CHECK(Nothing<bool>());
8781  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
8782  Handle<Object> handler(proxy->handler(), isolate);
8783  // 2. If handler is null, throw a TypeError exception.
8784  // 3. Assert: Type(handler) is Object.
8785  if (proxy->IsRevoked()) {
8786    isolate->Throw(*isolate->factory()->NewTypeError(
8787        MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string()));
8788    return Nothing<bool>();
8789  }
8790  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
8791  Handle<JSReceiver> target(proxy->target(), isolate);
8792  // 5. Let trap be ? GetMethod(handler, "ownKeys").
8793  Handle<Object> trap;
8794  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8795      isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
8796                                       isolate->factory()->ownKeys_string()),
8797      Nothing<bool>());
8798  // 6. If trap is undefined, then
8799  if (trap->IsUndefined()) {
8800    // 6a. Return target.[[OwnPropertyKeys]]().
8801    return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter,
8802                            accumulator);
8803  }
8804  // 7. Let trapResultArray be Call(trap, handler, «target»).
8805  Handle<Object> trap_result_array;
8806  Handle<Object> args[] = {target};
8807  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8808      isolate, trap_result_array,
8809      Execution::Call(isolate, trap, handler, arraysize(args), args),
8810      Nothing<bool>());
8811  // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray,
8812  //    «String, Symbol»).
8813  Handle<FixedArray> trap_result;
8814  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8815      isolate, trap_result,
8816      Object::CreateListFromArrayLike(isolate, trap_result_array,
8817                                      ElementTypes::kStringAndSymbol),
8818      Nothing<bool>());
8819  // 9. Let extensibleTarget be ? IsExtensible(target).
8820  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
8821  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
8822  bool extensible_target = maybe_extensible.FromJust();
8823  // 10. Let targetKeys be ? target.[[OwnPropertyKeys]]().
8824  Handle<FixedArray> target_keys;
8825  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_keys,
8826                                   JSReceiver::OwnPropertyKeys(target),
8827                                   Nothing<bool>());
8828  // 11. (Assert)
8829  // 12. Let targetConfigurableKeys be an empty List.
8830  // To save memory, we're re-using target_keys and will modify it in-place.
8831  Handle<FixedArray> target_configurable_keys = target_keys;
8832  // 13. Let targetNonconfigurableKeys be an empty List.
8833  Handle<FixedArray> target_nonconfigurable_keys =
8834      isolate->factory()->NewFixedArray(target_keys->length());
8835  int nonconfigurable_keys_length = 0;
8836  // 14. Repeat, for each element key of targetKeys:
8837  for (int i = 0; i < target_keys->length(); ++i) {
8838    // 14a. Let desc be ? target.[[GetOwnProperty]](key).
8839    PropertyDescriptor desc;
8840    Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
8841        isolate, target, handle(target_keys->get(i), isolate), &desc);
8842    MAYBE_RETURN(found, Nothing<bool>());
8843    // 14b. If desc is not undefined and desc.[[Configurable]] is false, then
8844    if (found.FromJust() && !desc.configurable()) {
8845      // 14b i. Append key as an element of targetNonconfigurableKeys.
8846      target_nonconfigurable_keys->set(nonconfigurable_keys_length,
8847                                       target_keys->get(i));
8848      nonconfigurable_keys_length++;
8849      // The key was moved, null it out in the original list.
8850      target_keys->set(i, Smi::FromInt(0));
8851    } else {
8852      // 14c. Else,
8853      // 14c i. Append key as an element of targetConfigurableKeys.
8854      // (No-op, just keep it in |target_keys|.)
8855    }
8856  }
8857  accumulator->NextPrototype();  // Prepare for accumulating keys.
8858  // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty,
8859  //     then:
8860  if (extensible_target && nonconfigurable_keys_length == 0) {
8861    // 15a. Return trapResult.
8862    return accumulator->AddKeysFromProxy(proxy, trap_result);
8863  }
8864  // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult.
8865  Zone set_zone;
8866  const int kPresent = 1;
8867  const int kGone = 0;
8868  IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone);
8869  int unchecked_result_keys_size = trap_result->length();
8870  for (int i = 0; i < trap_result->length(); ++i) {
8871    DCHECK(trap_result->get(i)->IsUniqueName());
8872    unchecked_result_keys.Set(trap_result->get(i), kPresent);
8873  }
8874  // 17. Repeat, for each key that is an element of targetNonconfigurableKeys:
8875  for (int i = 0; i < nonconfigurable_keys_length; ++i) {
8876    Object* key = target_nonconfigurable_keys->get(i);
8877    // 17a. If key is not an element of uncheckedResultKeys, throw a
8878    //      TypeError exception.
8879    int* found = unchecked_result_keys.Find(key);
8880    if (found == nullptr || *found == kGone) {
8881      isolate->Throw(*isolate->factory()->NewTypeError(
8882          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate)));
8883      return Nothing<bool>();
8884    }
8885    // 17b. Remove key from uncheckedResultKeys.
8886    *found = kGone;
8887    unchecked_result_keys_size--;
8888  }
8889  // 18. If extensibleTarget is true, return trapResult.
8890  if (extensible_target) {
8891    return accumulator->AddKeysFromProxy(proxy, trap_result);
8892  }
8893  // 19. Repeat, for each key that is an element of targetConfigurableKeys:
8894  for (int i = 0; i < target_configurable_keys->length(); ++i) {
8895    Object* key = target_configurable_keys->get(i);
8896    if (key->IsSmi()) continue;  // Zapped entry, was nonconfigurable.
8897    // 19a. If key is not an element of uncheckedResultKeys, throw a
8898    //      TypeError exception.
8899    int* found = unchecked_result_keys.Find(key);
8900    if (found == nullptr || *found == kGone) {
8901      isolate->Throw(*isolate->factory()->NewTypeError(
8902          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate)));
8903      return Nothing<bool>();
8904    }
8905    // 19b. Remove key from uncheckedResultKeys.
8906    *found = kGone;
8907    unchecked_result_keys_size--;
8908  }
8909  // 20. If uncheckedResultKeys is not empty, throw a TypeError exception.
8910  if (unchecked_result_keys_size != 0) {
8911    DCHECK_GT(unchecked_result_keys_size, 0);
8912    isolate->Throw(*isolate->factory()->NewTypeError(
8913        MessageTemplate::kProxyOwnKeysNonExtensible));
8914    return Nothing<bool>();
8915  }
8916  // 21. Return trapResult.
8917  return accumulator->AddKeysFromProxy(proxy, trap_result);
8918}
8919
8920
8921MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
8922                                            KeyCollectionType type,
8923                                            PropertyFilter filter,
8924                                            GetKeysConversion keys_conversion) {
8925  USE(ContainsOnlyValidKeys);
8926  Isolate* isolate = object->GetIsolate();
8927  KeyAccumulator accumulator(isolate, filter);
8928  MAYBE_RETURN(
8929      GetKeys_Internal(isolate, object, object, type, filter, &accumulator),
8930      MaybeHandle<FixedArray>());
8931  Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion);
8932  DCHECK(ContainsOnlyValidKeys(keys));
8933  return keys;
8934}
8935
8936
8937bool Map::DictionaryElementsInPrototypeChainOnly() {
8938  if (IsDictionaryElementsKind(elements_kind())) {
8939    return false;
8940  }
8941
8942  for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
8943    // Be conservative, don't walk into proxies.
8944    if (iter.GetCurrent()->IsJSProxy()) return true;
8945    // String wrappers have non-configurable, non-writable elements.
8946    if (iter.GetCurrent()->IsStringWrapper()) return true;
8947    JSObject* current = iter.GetCurrent<JSObject>();
8948
8949    if (current->HasDictionaryElements() &&
8950        current->element_dictionary()->requires_slow_elements()) {
8951      return true;
8952    }
8953
8954    if (current->HasSlowArgumentsElements()) {
8955      FixedArray* parameter_map = FixedArray::cast(current->elements());
8956      Object* arguments = parameter_map->get(1);
8957      if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
8958        return true;
8959      }
8960    }
8961  }
8962
8963  return false;
8964}
8965
8966
8967MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
8968                                             Handle<Name> name,
8969                                             Handle<Object> getter,
8970                                             Handle<Object> setter,
8971                                             PropertyAttributes attributes) {
8972  Isolate* isolate = object->GetIsolate();
8973
8974  LookupIterator it = LookupIterator::PropertyOrElement(
8975      isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
8976  return DefineAccessor(&it, getter, setter, attributes);
8977}
8978
8979
8980MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
8981                                             Handle<Object> getter,
8982                                             Handle<Object> setter,
8983                                             PropertyAttributes attributes) {
8984  Isolate* isolate = it->isolate();
8985
8986  if (it->state() == LookupIterator::ACCESS_CHECK) {
8987    if (!it->HasAccess()) {
8988      isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
8989      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
8990      return isolate->factory()->undefined_value();
8991    }
8992    it->Next();
8993  }
8994
8995  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
8996  // Ignore accessors on typed arrays.
8997  if (it->IsElement() && object->HasFixedTypedArrayElements()) {
8998    return it->factory()->undefined_value();
8999  }
9000
9001  Handle<Object> old_value = isolate->factory()->the_hole_value();
9002  bool is_observed = object->map()->is_observed() &&
9003                     !isolate->IsInternallyUsedPropertyName(it->GetName());
9004  bool preexists = false;
9005  if (is_observed) {
9006    CHECK(GetPropertyAttributes(it).IsJust());
9007    preexists = it->IsFound();
9008    if (preexists && (it->state() == LookupIterator::DATA ||
9009                      it->GetAccessors()->IsAccessorInfo())) {
9010      old_value = GetProperty(it).ToHandleChecked();
9011    }
9012  }
9013
9014  DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull());
9015  DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull());
9016  // At least one of the accessors needs to be a new value.
9017  DCHECK(!getter->IsNull() || !setter->IsNull());
9018  if (!getter->IsNull()) {
9019    it->TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
9020  }
9021  if (!setter->IsNull()) {
9022    it->TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
9023  }
9024
9025  if (is_observed) {
9026    // Make sure the top context isn't changed.
9027    AssertNoContextChange ncc(isolate);
9028    const char* type = preexists ? "reconfigure" : "add";
9029    RETURN_ON_EXCEPTION(
9030        isolate, EnqueueChangeRecord(object, type, it->GetName(), old_value),
9031        Object);
9032  }
9033
9034  return isolate->factory()->undefined_value();
9035}
9036
9037
9038MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
9039                                          Handle<AccessorInfo> info) {
9040  Isolate* isolate = object->GetIsolate();
9041  Handle<Name> name(Name::cast(info->name()), isolate);
9042
9043  LookupIterator it = LookupIterator::PropertyOrElement(
9044      isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
9045
9046  // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
9047  // the FailedAccessCheckCallbackFunction doesn't throw an exception.
9048  //
9049  // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
9050  // remove reliance on default return values.
9051  if (it.state() == LookupIterator::ACCESS_CHECK) {
9052    if (!it.HasAccess()) {
9053      isolate->ReportFailedAccessCheck(object);
9054      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9055      return it.factory()->undefined_value();
9056    }
9057    it.Next();
9058  }
9059
9060  // Ignore accessors on typed arrays.
9061  if (it.IsElement() && object->HasFixedTypedArrayElements()) {
9062    return it.factory()->undefined_value();
9063  }
9064
9065  CHECK(GetPropertyAttributes(&it).IsJust());
9066
9067  // ES5 forbids turning a property into an accessor if it's not
9068  // configurable. See 8.6.1 (Table 5).
9069  if (it.IsFound() && !it.IsConfigurable()) {
9070    return it.factory()->undefined_value();
9071  }
9072
9073  it.TransitionToAccessorPair(info, info->property_attributes());
9074
9075  return object;
9076}
9077
9078
9079MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
9080                                          Handle<Name> name,
9081                                          AccessorComponent component) {
9082  Isolate* isolate = object->GetIsolate();
9083
9084  // Make sure that the top context does not change when doing callbacks or
9085  // interceptor calls.
9086  AssertNoContextChange ncc(isolate);
9087
9088  LookupIterator it = LookupIterator::PropertyOrElement(
9089      isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
9090
9091  for (; it.IsFound(); it.Next()) {
9092    switch (it.state()) {
9093      case LookupIterator::INTERCEPTOR:
9094      case LookupIterator::NOT_FOUND:
9095      case LookupIterator::TRANSITION:
9096        UNREACHABLE();
9097
9098      case LookupIterator::ACCESS_CHECK:
9099        if (it.HasAccess()) continue;
9100        isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
9101        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
9102        return isolate->factory()->undefined_value();
9103
9104      case LookupIterator::JSPROXY:
9105        return isolate->factory()->undefined_value();
9106
9107      case LookupIterator::INTEGER_INDEXED_EXOTIC:
9108        return isolate->factory()->undefined_value();
9109      case LookupIterator::DATA:
9110        continue;
9111      case LookupIterator::ACCESSOR: {
9112        Handle<Object> maybe_pair = it.GetAccessors();
9113        if (maybe_pair->IsAccessorPair()) {
9114          return handle(
9115              AccessorPair::cast(*maybe_pair)->GetComponent(component),
9116              isolate);
9117        }
9118      }
9119    }
9120  }
9121
9122  return isolate->factory()->undefined_value();
9123}
9124
9125
9126Object* JSObject::SlowReverseLookup(Object* value) {
9127  if (HasFastProperties()) {
9128    int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
9129    DescriptorArray* descs = map()->instance_descriptors();
9130    bool value_is_number = value->IsNumber();
9131    for (int i = 0; i < number_of_own_descriptors; i++) {
9132      if (descs->GetType(i) == DATA) {
9133        FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
9134        if (IsUnboxedDoubleField(field_index)) {
9135          if (value_is_number) {
9136            double property = RawFastDoublePropertyAt(field_index);
9137            if (property == value->Number()) {
9138              return descs->GetKey(i);
9139            }
9140          }
9141        } else {
9142          Object* property = RawFastPropertyAt(field_index);
9143          if (field_index.is_double()) {
9144            DCHECK(property->IsMutableHeapNumber());
9145            if (value_is_number && property->Number() == value->Number()) {
9146              return descs->GetKey(i);
9147            }
9148          } else if (property == value) {
9149            return descs->GetKey(i);
9150          }
9151        }
9152      } else if (descs->GetType(i) == DATA_CONSTANT) {
9153        if (descs->GetConstant(i) == value) {
9154          return descs->GetKey(i);
9155        }
9156      }
9157    }
9158    return GetHeap()->undefined_value();
9159  } else if (IsJSGlobalObject()) {
9160    return global_dictionary()->SlowReverseLookup(value);
9161  } else {
9162    return property_dictionary()->SlowReverseLookup(value);
9163  }
9164}
9165
9166
9167Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
9168  Isolate* isolate = map->GetIsolate();
9169  Handle<Map> result =
9170      isolate->factory()->NewMap(map->instance_type(), instance_size);
9171  Handle<Object> prototype(map->prototype(), isolate);
9172  Map::SetPrototype(result, prototype);
9173  result->set_constructor_or_backpointer(map->GetConstructor());
9174  result->set_bit_field(map->bit_field());
9175  result->set_bit_field2(map->bit_field2());
9176  int new_bit_field3 = map->bit_field3();
9177  new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
9178  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
9179  new_bit_field3 = EnumLengthBits::update(new_bit_field3,
9180                                          kInvalidEnumCacheSentinel);
9181  new_bit_field3 = Deprecated::update(new_bit_field3, false);
9182  if (!map->is_dictionary_map()) {
9183    new_bit_field3 = IsUnstable::update(new_bit_field3, false);
9184  }
9185  new_bit_field3 =
9186      ConstructionCounter::update(new_bit_field3, kNoSlackTracking);
9187  result->set_bit_field3(new_bit_field3);
9188  return result;
9189}
9190
9191
9192Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
9193                           const char* reason) {
9194  DCHECK(!fast_map->is_dictionary_map());
9195
9196  Isolate* isolate = fast_map->GetIsolate();
9197  Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
9198                             isolate);
9199  bool use_cache = !fast_map->is_prototype_map() && !maybe_cache->IsUndefined();
9200  Handle<NormalizedMapCache> cache;
9201  if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
9202
9203  Handle<Map> new_map;
9204  if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
9205#ifdef VERIFY_HEAP
9206    if (FLAG_verify_heap) new_map->DictionaryMapVerify();
9207#endif
9208#ifdef ENABLE_SLOW_DCHECKS
9209    if (FLAG_enable_slow_asserts) {
9210      // The cached map should match newly created normalized map bit-by-bit,
9211      // except for the code cache, which can contain some ics which can be
9212      // applied to the shared map, dependent code and weak cell cache.
9213      Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
9214
9215      if (new_map->is_prototype_map()) {
9216        // For prototype maps, the PrototypeInfo is not copied.
9217        DCHECK(memcmp(fresh->address(), new_map->address(),
9218                      kTransitionsOrPrototypeInfoOffset) == 0);
9219        DCHECK(fresh->raw_transitions() == Smi::FromInt(0));
9220        STATIC_ASSERT(kDescriptorsOffset ==
9221                      kTransitionsOrPrototypeInfoOffset + kPointerSize);
9222        DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
9223                      HeapObject::RawField(*new_map, kDescriptorsOffset),
9224                      kCodeCacheOffset - kDescriptorsOffset) == 0);
9225      } else {
9226        DCHECK(memcmp(fresh->address(), new_map->address(),
9227                      Map::kCodeCacheOffset) == 0);
9228      }
9229      STATIC_ASSERT(Map::kDependentCodeOffset ==
9230                    Map::kCodeCacheOffset + kPointerSize);
9231      STATIC_ASSERT(Map::kWeakCellCacheOffset ==
9232                    Map::kDependentCodeOffset + kPointerSize);
9233      int offset = Map::kWeakCellCacheOffset + kPointerSize;
9234      DCHECK(memcmp(fresh->address() + offset,
9235                    new_map->address() + offset,
9236                    Map::kSize - offset) == 0);
9237    }
9238#endif
9239  } else {
9240    new_map = Map::CopyNormalized(fast_map, mode);
9241    if (use_cache) {
9242      cache->Set(fast_map, new_map);
9243      isolate->counters()->normalized_maps()->Increment();
9244    }
9245#if TRACE_MAPS
9246    if (FLAG_trace_maps) {
9247      PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
9248             reinterpret_cast<void*>(*fast_map),
9249             reinterpret_cast<void*>(*new_map), reason);
9250    }
9251#endif
9252  }
9253  fast_map->NotifyLeafMapLayoutChange();
9254  return new_map;
9255}
9256
9257
9258Handle<Map> Map::CopyNormalized(Handle<Map> map,
9259                                PropertyNormalizationMode mode) {
9260  int new_instance_size = map->instance_size();
9261  if (mode == CLEAR_INOBJECT_PROPERTIES) {
9262    new_instance_size -= map->GetInObjectProperties() * kPointerSize;
9263  }
9264
9265  Handle<Map> result = RawCopy(map, new_instance_size);
9266
9267  if (mode != CLEAR_INOBJECT_PROPERTIES) {
9268    result->SetInObjectProperties(map->GetInObjectProperties());
9269  }
9270
9271  result->set_dictionary_map(true);
9272  result->set_migration_target(false);
9273
9274#ifdef VERIFY_HEAP
9275  if (FLAG_verify_heap) result->DictionaryMapVerify();
9276#endif
9277
9278  return result;
9279}
9280
9281
9282Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
9283                                int in_object_properties,
9284                                int unused_property_fields) {
9285#ifdef DEBUG
9286  Isolate* isolate = map->GetIsolate();
9287  // Strict and strong function maps have Function as a constructor but the
9288  // Function's initial map is a sloppy function map. Same holds for
9289  // GeneratorFunction and its initial map.
9290  Object* constructor = map->GetConstructor();
9291  DCHECK(constructor->IsJSFunction());
9292  DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
9293         *map == *isolate->strict_function_map() ||
9294         *map == *isolate->strong_function_map() ||
9295         *map == *isolate->strict_generator_function_map() ||
9296         *map == *isolate->strong_generator_function_map());
9297#endif
9298  // Initial maps must always own their descriptors and it's descriptor array
9299  // does not contain descriptors that do not belong to the map.
9300  DCHECK(map->owns_descriptors());
9301  DCHECK_EQ(map->NumberOfOwnDescriptors(),
9302            map->instance_descriptors()->number_of_descriptors());
9303
9304  Handle<Map> result = RawCopy(map, instance_size);
9305
9306  // Please note instance_type and instance_size are set when allocated.
9307  result->SetInObjectProperties(in_object_properties);
9308  result->set_unused_property_fields(unused_property_fields);
9309
9310  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9311  if (number_of_own_descriptors > 0) {
9312    // The copy will use the same descriptors array.
9313    result->UpdateDescriptors(map->instance_descriptors(),
9314                              map->GetLayoutDescriptor());
9315    result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
9316
9317    DCHECK_EQ(result->NumberOfFields(),
9318              in_object_properties - unused_property_fields);
9319  }
9320
9321  return result;
9322}
9323
9324
9325Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
9326  Handle<Map> result = RawCopy(map, map->instance_size());
9327
9328  // Please note instance_type and instance_size are set when allocated.
9329  if (map->IsJSObjectMap()) {
9330    result->SetInObjectProperties(map->GetInObjectProperties());
9331    result->set_unused_property_fields(map->unused_property_fields());
9332  }
9333  result->ClearCodeCache(map->GetHeap());
9334  map->NotifyLeafMapLayoutChange();
9335  return result;
9336}
9337
9338
9339Handle<Map> Map::ShareDescriptor(Handle<Map> map,
9340                                 Handle<DescriptorArray> descriptors,
9341                                 Descriptor* descriptor) {
9342  // Sanity check. This path is only to be taken if the map owns its descriptor
9343  // array, implying that its NumberOfOwnDescriptors equals the number of
9344  // descriptors in the descriptor array.
9345  DCHECK_EQ(map->NumberOfOwnDescriptors(),
9346            map->instance_descriptors()->number_of_descriptors());
9347
9348  Handle<Map> result = CopyDropDescriptors(map);
9349  Handle<Name> name = descriptor->GetKey();
9350
9351  // Ensure there's space for the new descriptor in the shared descriptor array.
9352  if (descriptors->NumberOfSlackDescriptors() == 0) {
9353    int old_size = descriptors->number_of_descriptors();
9354    if (old_size == 0) {
9355      descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
9356    } else {
9357      int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
9358      EnsureDescriptorSlack(map, slack);
9359      descriptors = handle(map->instance_descriptors());
9360    }
9361  }
9362
9363  Handle<LayoutDescriptor> layout_descriptor =
9364      FLAG_unbox_double_fields
9365          ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
9366          : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
9367
9368  {
9369    DisallowHeapAllocation no_gc;
9370    descriptors->Append(descriptor);
9371    result->InitializeDescriptors(*descriptors, *layout_descriptor);
9372  }
9373
9374  DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
9375  ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
9376
9377  return result;
9378}
9379
9380
9381#if TRACE_MAPS
9382
9383// static
9384void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
9385  if (FLAG_trace_maps) {
9386    PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
9387           reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
9388    name->NameShortPrint();
9389    PrintF(" ]\n");
9390  }
9391}
9392
9393
9394// static
9395void Map::TraceAllTransitions(Map* map) {
9396  Object* transitions = map->raw_transitions();
9397  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
9398  for (int i = -0; i < num_transitions; ++i) {
9399    Map* target = TransitionArray::GetTarget(transitions, i);
9400    Name* key = TransitionArray::GetKey(transitions, i);
9401    Map::TraceTransition("Transition", map, target, key);
9402    Map::TraceAllTransitions(target);
9403  }
9404}
9405
9406#endif  // TRACE_MAPS
9407
9408
9409void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
9410                            Handle<Name> name, SimpleTransitionFlag flag) {
9411  if (!parent->GetBackPointer()->IsUndefined()) {
9412    parent->set_owns_descriptors(false);
9413  } else {
9414    // |parent| is initial map and it must keep the ownership, there must be no
9415    // descriptors in the descriptors array that do not belong to the map.
9416    DCHECK(parent->owns_descriptors());
9417    DCHECK_EQ(parent->NumberOfOwnDescriptors(),
9418              parent->instance_descriptors()->number_of_descriptors());
9419  }
9420  if (parent->is_prototype_map()) {
9421    DCHECK(child->is_prototype_map());
9422#if TRACE_MAPS
9423    Map::TraceTransition("NoTransition", *parent, *child, *name);
9424#endif
9425  } else {
9426    TransitionArray::Insert(parent, name, child, flag);
9427#if TRACE_MAPS
9428    Map::TraceTransition("Transition", *parent, *child, *name);
9429#endif
9430  }
9431}
9432
9433
9434Handle<Map> Map::CopyReplaceDescriptors(
9435    Handle<Map> map, Handle<DescriptorArray> descriptors,
9436    Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
9437    MaybeHandle<Name> maybe_name, const char* reason,
9438    SimpleTransitionFlag simple_flag) {
9439  DCHECK(descriptors->IsSortedNoDuplicates());
9440
9441  Handle<Map> result = CopyDropDescriptors(map);
9442
9443  if (!map->is_prototype_map()) {
9444    if (flag == INSERT_TRANSITION &&
9445        TransitionArray::CanHaveMoreTransitions(map)) {
9446      result->InitializeDescriptors(*descriptors, *layout_descriptor);
9447
9448      Handle<Name> name;
9449      CHECK(maybe_name.ToHandle(&name));
9450      ConnectTransition(map, result, name, simple_flag);
9451    } else {
9452      int length = descriptors->number_of_descriptors();
9453      for (int i = 0; i < length; i++) {
9454        descriptors->SetRepresentation(i, Representation::Tagged());
9455        if (descriptors->GetDetails(i).type() == DATA) {
9456          descriptors->SetValue(i, HeapType::Any());
9457        }
9458      }
9459      result->InitializeDescriptors(*descriptors,
9460                                    LayoutDescriptor::FastPointerLayout());
9461    }
9462  } else {
9463    result->InitializeDescriptors(*descriptors, *layout_descriptor);
9464  }
9465#if TRACE_MAPS
9466  if (FLAG_trace_maps &&
9467      // Mirror conditions above that did not call ConnectTransition().
9468      (map->is_prototype_map() ||
9469       !(flag == INSERT_TRANSITION &&
9470         TransitionArray::CanHaveMoreTransitions(map)))) {
9471    PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
9472           reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
9473           reason);
9474  }
9475#endif
9476
9477  return result;
9478}
9479
9480
9481// Creates transition tree starting from |split_map| and adding all descriptors
9482// starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
9483// The way how it is done is tricky because of GC and special descriptors
9484// marking logic.
9485Handle<Map> Map::AddMissingTransitions(
9486    Handle<Map> split_map, Handle<DescriptorArray> descriptors,
9487    Handle<LayoutDescriptor> full_layout_descriptor) {
9488  DCHECK(descriptors->IsSortedNoDuplicates());
9489  int split_nof = split_map->NumberOfOwnDescriptors();
9490  int nof_descriptors = descriptors->number_of_descriptors();
9491  DCHECK_LT(split_nof, nof_descriptors);
9492
9493  // Start with creating last map which will own full descriptors array.
9494  // This is necessary to guarantee that GC will mark the whole descriptor
9495  // array if any of the allocations happening below fail.
9496  // Number of unused properties is temporarily incorrect and the layout
9497  // descriptor could unnecessarily be in slow mode but we will fix after
9498  // all the other intermediate maps are created.
9499  Handle<Map> last_map = CopyDropDescriptors(split_map);
9500  last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
9501  last_map->set_unused_property_fields(0);
9502
9503  // During creation of intermediate maps we violate descriptors sharing
9504  // invariant since the last map is not yet connected to the transition tree
9505  // we create here. But it is safe because GC never trims map's descriptors
9506  // if there are no dead transitions from that map and this is exactly the
9507  // case for all the intermediate maps we create here.
9508  Handle<Map> map = split_map;
9509  for (int i = split_nof; i < nof_descriptors - 1; ++i) {
9510    Handle<Map> new_map = CopyDropDescriptors(map);
9511    InstallDescriptors(map, new_map, i, descriptors, full_layout_descriptor);
9512    map = new_map;
9513  }
9514  map->NotifyLeafMapLayoutChange();
9515  InstallDescriptors(map, last_map, nof_descriptors - 1, descriptors,
9516                     full_layout_descriptor);
9517  return last_map;
9518}
9519
9520
9521// Since this method is used to rewrite an existing transition tree, it can
9522// always insert transitions without checking.
9523void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
9524                             int new_descriptor,
9525                             Handle<DescriptorArray> descriptors,
9526                             Handle<LayoutDescriptor> full_layout_descriptor) {
9527  DCHECK(descriptors->IsSortedNoDuplicates());
9528
9529  child->set_instance_descriptors(*descriptors);
9530  child->SetNumberOfOwnDescriptors(new_descriptor + 1);
9531
9532  int unused_property_fields = parent->unused_property_fields();
9533  PropertyDetails details = descriptors->GetDetails(new_descriptor);
9534  if (details.location() == kField) {
9535    unused_property_fields = parent->unused_property_fields() - 1;
9536    if (unused_property_fields < 0) {
9537      unused_property_fields += JSObject::kFieldsAdded;
9538    }
9539  }
9540  child->set_unused_property_fields(unused_property_fields);
9541
9542  if (FLAG_unbox_double_fields) {
9543    Handle<LayoutDescriptor> layout_descriptor =
9544        LayoutDescriptor::AppendIfFastOrUseFull(parent, details,
9545                                                full_layout_descriptor);
9546    child->set_layout_descriptor(*layout_descriptor);
9547#ifdef VERIFY_HEAP
9548    // TODO(ishell): remove these checks from VERIFY_HEAP mode.
9549    if (FLAG_verify_heap) {
9550      CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9551    }
9552#else
9553    SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9554#endif
9555    child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child));
9556  }
9557
9558  Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
9559  ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
9560}
9561
9562
9563Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
9564                                    TransitionFlag flag) {
9565  Map* maybe_elements_transition_map = NULL;
9566  if (flag == INSERT_TRANSITION) {
9567    maybe_elements_transition_map = map->ElementsTransitionMap();
9568    DCHECK(maybe_elements_transition_map == NULL ||
9569           (maybe_elements_transition_map->elements_kind() ==
9570                DICTIONARY_ELEMENTS &&
9571            kind == DICTIONARY_ELEMENTS));
9572    DCHECK(!IsFastElementsKind(kind) ||
9573           IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
9574    DCHECK(kind != map->elements_kind());
9575  }
9576
9577  bool insert_transition = flag == INSERT_TRANSITION &&
9578                           TransitionArray::CanHaveMoreTransitions(map) &&
9579                           maybe_elements_transition_map == NULL;
9580
9581  if (insert_transition) {
9582    Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
9583    new_map->set_elements_kind(kind);
9584
9585    Isolate* isolate = map->GetIsolate();
9586    Handle<Name> name = isolate->factory()->elements_transition_symbol();
9587    ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
9588    return new_map;
9589  }
9590
9591  // Create a new free-floating map only if we are not allowed to store it.
9592  Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
9593  new_map->set_elements_kind(kind);
9594  return new_map;
9595}
9596
9597
9598Handle<Map> Map::AsLanguageMode(Handle<Map> initial_map,
9599                                LanguageMode language_mode, FunctionKind kind) {
9600  DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
9601  // Initial map for sloppy mode function is stored in the function
9602  // constructor. Initial maps for strict and strong modes are cached as
9603  // special transitions using |strict_function_transition_symbol| and
9604  // |strong_function_transition_symbol| respectively as a key.
9605  if (language_mode == SLOPPY) return initial_map;
9606  Isolate* isolate = initial_map->GetIsolate();
9607  Factory* factory = isolate->factory();
9608  Handle<Symbol> transition_symbol;
9609
9610  int map_index = Context::FunctionMapIndex(language_mode, kind);
9611  Handle<Map> function_map(
9612      Map::cast(isolate->native_context()->get(map_index)));
9613
9614  STATIC_ASSERT(LANGUAGE_END == 3);
9615  switch (language_mode) {
9616    case STRICT:
9617      transition_symbol = factory->strict_function_transition_symbol();
9618      break;
9619    case STRONG:
9620      transition_symbol = factory->strong_function_transition_symbol();
9621      break;
9622    default:
9623      UNREACHABLE();
9624      break;
9625  }
9626  Map* maybe_transition =
9627      TransitionArray::SearchSpecial(*initial_map, *transition_symbol);
9628  if (maybe_transition != NULL) {
9629    return handle(maybe_transition, isolate);
9630  }
9631  initial_map->NotifyLeafMapLayoutChange();
9632
9633  // Create new map taking descriptors from the |function_map| and all
9634  // the other details from the |initial_map|.
9635  Handle<Map> map =
9636      Map::CopyInitialMap(function_map, initial_map->instance_size(),
9637                          initial_map->GetInObjectProperties(),
9638                          initial_map->unused_property_fields());
9639  map->SetConstructor(initial_map->GetConstructor());
9640  map->set_prototype(initial_map->prototype());
9641
9642  if (TransitionArray::CanHaveMoreTransitions(initial_map)) {
9643    Map::ConnectTransition(initial_map, map, transition_symbol,
9644                           SPECIAL_TRANSITION);
9645  }
9646  return map;
9647}
9648
9649
9650Handle<Map> Map::CopyForObserved(Handle<Map> map) {
9651  DCHECK(!map->is_observed());
9652
9653  Isolate* isolate = map->GetIsolate();
9654
9655  bool insert_transition =
9656      TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
9657
9658  if (insert_transition) {
9659    Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
9660    new_map->set_is_observed();
9661
9662    Handle<Name> name = isolate->factory()->observed_symbol();
9663    ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
9664    return new_map;
9665  }
9666
9667  // Create a new free-floating map only if we are not allowed to store it.
9668  Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
9669  new_map->set_is_observed();
9670  return new_map;
9671}
9672
9673
9674Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
9675  DCHECK(!map->is_prototype_map());
9676  Handle<Map> new_map = CopyDropDescriptors(map);
9677
9678  if (map->owns_descriptors()) {
9679    // In case the map owned its own descriptors, share the descriptors and
9680    // transfer ownership to the new map.
9681    // The properties did not change, so reuse descriptors.
9682    new_map->InitializeDescriptors(map->instance_descriptors(),
9683                                   map->GetLayoutDescriptor());
9684  } else {
9685    // In case the map did not own its own descriptors, a split is forced by
9686    // copying the map; creating a new descriptor array cell.
9687    Handle<DescriptorArray> descriptors(map->instance_descriptors());
9688    int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9689    Handle<DescriptorArray> new_descriptors =
9690        DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
9691    Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9692                                                   map->GetIsolate());
9693    new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
9694  }
9695
9696#if TRACE_MAPS
9697  if (FLAG_trace_maps) {
9698    PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
9699           reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
9700           reason);
9701  }
9702#endif
9703
9704  return new_map;
9705}
9706
9707
9708Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
9709  Handle<DescriptorArray> descriptors(map->instance_descriptors());
9710  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
9711  Handle<DescriptorArray> new_descriptors =
9712      DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
9713  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9714                                                 map->GetIsolate());
9715  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
9716                                OMIT_TRANSITION, MaybeHandle<Name>(), reason,
9717                                SPECIAL_TRANSITION);
9718}
9719
9720
9721Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
9722  Handle<Map> copy =
9723      Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
9724
9725  // Check that we do not overflow the instance size when adding the extra
9726  // inobject properties. If the instance size overflows, we allocate as many
9727  // properties as we can as inobject properties.
9728  int max_extra_properties =
9729      (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
9730
9731  if (inobject_properties > max_extra_properties) {
9732    inobject_properties = max_extra_properties;
9733  }
9734
9735  int new_instance_size =
9736      JSObject::kHeaderSize + kPointerSize * inobject_properties;
9737
9738  // Adjust the map with the extra inobject properties.
9739  copy->SetInObjectProperties(inobject_properties);
9740  copy->set_unused_property_fields(inobject_properties);
9741  copy->set_instance_size(new_instance_size);
9742  copy->set_visitor_id(Heap::GetStaticVisitorIdForMap(*copy));
9743  return copy;
9744}
9745
9746
9747Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
9748                                          PropertyAttributes attrs_to_add,
9749                                          Handle<Symbol> transition_marker,
9750                                          const char* reason) {
9751  int num_descriptors = map->NumberOfOwnDescriptors();
9752  Isolate* isolate = map->GetIsolate();
9753  Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
9754      handle(map->instance_descriptors(), isolate), num_descriptors,
9755      attrs_to_add);
9756  Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
9757                                                 isolate);
9758  Handle<Map> new_map = CopyReplaceDescriptors(
9759      map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
9760      transition_marker, reason, SPECIAL_TRANSITION);
9761  new_map->set_is_extensible(false);
9762  if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
9763    new_map->set_elements_kind(DICTIONARY_ELEMENTS);
9764  }
9765  return new_map;
9766}
9767
9768
9769bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
9770  PropertyDetails details = GetDetails(descriptor);
9771  switch (details.type()) {
9772    case DATA:
9773      return value->FitsRepresentation(details.representation()) &&
9774             GetFieldType(descriptor)->NowContains(value);
9775
9776    case DATA_CONSTANT:
9777      DCHECK(GetConstant(descriptor) != value ||
9778             value->FitsRepresentation(details.representation()));
9779      return GetConstant(descriptor) == value;
9780
9781    case ACCESSOR:
9782    case ACCESSOR_CONSTANT:
9783      return false;
9784  }
9785
9786  UNREACHABLE();
9787  return false;
9788}
9789
9790
9791// static
9792Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
9793                                        Handle<Object> value) {
9794  // Dictionaries can store any property value.
9795  if (map->is_dictionary_map()) return map;
9796
9797  // Migrate to the newest map before storing the property.
9798  map = Update(map);
9799
9800  Handle<DescriptorArray> descriptors(map->instance_descriptors());
9801
9802  if (descriptors->CanHoldValue(descriptor, *value)) return map;
9803
9804  Isolate* isolate = map->GetIsolate();
9805  PropertyAttributes attributes =
9806      descriptors->GetDetails(descriptor).attributes();
9807  Representation representation = value->OptimalRepresentation();
9808  Handle<HeapType> type = value->OptimalType(isolate, representation);
9809
9810  return ReconfigureProperty(map, descriptor, kData, attributes, representation,
9811                             type, FORCE_FIELD);
9812}
9813
9814
9815Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
9816                                          Handle<Object> value,
9817                                          PropertyAttributes attributes,
9818                                          StoreFromKeyed store_mode) {
9819  // Dictionary maps can always have additional data properties.
9820  if (map->is_dictionary_map()) return map;
9821
9822  // Migrate to the newest map before storing the property.
9823  map = Update(map);
9824
9825  Map* maybe_transition =
9826      TransitionArray::SearchTransition(*map, kData, *name, attributes);
9827  if (maybe_transition != NULL) {
9828    Handle<Map> transition(maybe_transition);
9829    int descriptor = transition->LastAdded();
9830
9831    DCHECK_EQ(attributes, transition->instance_descriptors()
9832                              ->GetDetails(descriptor)
9833                              .attributes());
9834
9835    return Map::PrepareForDataProperty(transition, descriptor, value);
9836  }
9837
9838  TransitionFlag flag = INSERT_TRANSITION;
9839  MaybeHandle<Map> maybe_map;
9840  if (value->IsJSFunction()) {
9841    maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
9842  } else if (!map->TooManyFastProperties(store_mode)) {
9843    Isolate* isolate = name->GetIsolate();
9844    Representation representation = value->OptimalRepresentation();
9845    Handle<HeapType> type = value->OptimalType(isolate, representation);
9846    maybe_map =
9847        Map::CopyWithField(map, name, type, attributes, representation, flag);
9848  }
9849
9850  Handle<Map> result;
9851  if (!maybe_map.ToHandle(&result)) {
9852#if TRACE_MAPS
9853    if (FLAG_trace_maps) {
9854      Vector<char> name_buffer = Vector<char>::New(100);
9855      name->NameShortPrint(name_buffer);
9856      Vector<char> buffer = Vector<char>::New(128);
9857      SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
9858      return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
9859    }
9860#endif
9861    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
9862                          "TooManyFastProperties");
9863  }
9864
9865  return result;
9866}
9867
9868
9869Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
9870                                             PropertyKind kind,
9871                                             PropertyAttributes attributes) {
9872  // Dictionaries have to be reconfigured in-place.
9873  DCHECK(!map->is_dictionary_map());
9874
9875  if (!map->GetBackPointer()->IsMap()) {
9876    // There is no benefit from reconstructing transition tree for maps without
9877    // back pointers.
9878    return CopyGeneralizeAllRepresentations(
9879        map, descriptor, FORCE_FIELD, kind, attributes,
9880        "GenAll_AttributesMismatchProtoMap");
9881  }
9882
9883  if (FLAG_trace_generalization) {
9884    map->PrintReconfiguration(stdout, descriptor, kind, attributes);
9885  }
9886
9887  Isolate* isolate = map->GetIsolate();
9888  Handle<Map> new_map = ReconfigureProperty(
9889      map, descriptor, kind, attributes, Representation::None(),
9890      HeapType::None(isolate), FORCE_FIELD);
9891  return new_map;
9892}
9893
9894
9895Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
9896                                              Handle<Name> name,
9897                                              AccessorComponent component,
9898                                              Handle<Object> accessor,
9899                                              PropertyAttributes attributes) {
9900  Isolate* isolate = name->GetIsolate();
9901
9902  // Dictionary maps can always have additional data properties.
9903  if (map->is_dictionary_map()) return map;
9904
9905  // Migrate to the newest map before transitioning to the new property.
9906  map = Update(map);
9907
9908  PropertyNormalizationMode mode = map->is_prototype_map()
9909                                       ? KEEP_INOBJECT_PROPERTIES
9910                                       : CLEAR_INOBJECT_PROPERTIES;
9911
9912  Map* maybe_transition =
9913      TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
9914  if (maybe_transition != NULL) {
9915    Handle<Map> transition(maybe_transition, isolate);
9916    DescriptorArray* descriptors = transition->instance_descriptors();
9917    int descriptor = transition->LastAdded();
9918    DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
9919
9920    DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
9921    DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
9922
9923    Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
9924    if (!maybe_pair->IsAccessorPair()) {
9925      return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
9926    }
9927
9928    Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
9929    if (pair->get(component) != *accessor) {
9930      return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
9931    }
9932
9933    return transition;
9934  }
9935
9936  Handle<AccessorPair> pair;
9937  DescriptorArray* old_descriptors = map->instance_descriptors();
9938  int descriptor = old_descriptors->SearchWithCache(*name, *map);
9939  if (descriptor != DescriptorArray::kNotFound) {
9940    if (descriptor != map->LastAdded()) {
9941      return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
9942    }
9943    PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
9944    if (old_details.type() != ACCESSOR_CONSTANT) {
9945      return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
9946    }
9947
9948    if (old_details.attributes() != attributes) {
9949      return Map::Normalize(map, mode, "AccessorsWithAttributes");
9950    }
9951
9952    Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
9953    if (!maybe_pair->IsAccessorPair()) {
9954      return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
9955    }
9956
9957    Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
9958    if (current == *accessor) return map;
9959
9960    if (!current->IsTheHole()) {
9961      return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
9962    }
9963
9964    pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
9965  } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
9966             map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
9967    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
9968  } else {
9969    pair = isolate->factory()->NewAccessorPair();
9970  }
9971
9972  pair->set(component, *accessor);
9973  TransitionFlag flag = INSERT_TRANSITION;
9974  AccessorConstantDescriptor new_desc(name, pair, attributes);
9975  return Map::CopyInsertDescriptor(map, &new_desc, flag);
9976}
9977
9978
9979Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
9980                                   Descriptor* descriptor,
9981                                   TransitionFlag flag) {
9982  Handle<DescriptorArray> descriptors(map->instance_descriptors());
9983
9984  // Ensure the key is unique.
9985  descriptor->KeyToUniqueName();
9986
9987  // Share descriptors only if map owns descriptors and it not an initial map.
9988  if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
9989      !map->GetBackPointer()->IsUndefined() &&
9990      TransitionArray::CanHaveMoreTransitions(map)) {
9991    return ShareDescriptor(map, descriptors, descriptor);
9992  }
9993
9994  int nof = map->NumberOfOwnDescriptors();
9995  Handle<DescriptorArray> new_descriptors =
9996      DescriptorArray::CopyUpTo(descriptors, nof, 1);
9997  new_descriptors->Append(descriptor);
9998
9999  Handle<LayoutDescriptor> new_layout_descriptor =
10000      FLAG_unbox_double_fields
10001          ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
10002          : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
10003
10004  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
10005                                flag, descriptor->GetKey(), "CopyAddDescriptor",
10006                                SIMPLE_PROPERTY_TRANSITION);
10007}
10008
10009
10010Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
10011                                      Descriptor* descriptor,
10012                                      TransitionFlag flag) {
10013  Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
10014
10015  // Ensure the key is unique.
10016  descriptor->KeyToUniqueName();
10017
10018  // We replace the key if it is already present.
10019  int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
10020  if (index != DescriptorArray::kNotFound) {
10021    return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
10022  }
10023  return CopyAddDescriptor(map, descriptor, flag);
10024}
10025
10026
10027Handle<DescriptorArray> DescriptorArray::CopyUpTo(
10028    Handle<DescriptorArray> desc,
10029    int enumeration_index,
10030    int slack) {
10031  return DescriptorArray::CopyUpToAddAttributes(
10032      desc, enumeration_index, NONE, slack);
10033}
10034
10035
10036Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
10037    Handle<DescriptorArray> desc,
10038    int enumeration_index,
10039    PropertyAttributes attributes,
10040    int slack) {
10041  if (enumeration_index + slack == 0) {
10042    return desc->GetIsolate()->factory()->empty_descriptor_array();
10043  }
10044
10045  int size = enumeration_index;
10046
10047  Handle<DescriptorArray> descriptors =
10048      DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
10049
10050  if (attributes != NONE) {
10051    for (int i = 0; i < size; ++i) {
10052      Object* value = desc->GetValue(i);
10053      Name* key = desc->GetKey(i);
10054      PropertyDetails details = desc->GetDetails(i);
10055      // Bulk attribute changes never affect private properties.
10056      if (!key->IsPrivate()) {
10057        int mask = DONT_DELETE | DONT_ENUM;
10058        // READ_ONLY is an invalid attribute for JS setters/getters.
10059        if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
10060          mask |= READ_ONLY;
10061        }
10062        details = details.CopyAddAttributes(
10063            static_cast<PropertyAttributes>(attributes & mask));
10064      }
10065      Descriptor inner_desc(
10066          handle(key), handle(value, desc->GetIsolate()), details);
10067      descriptors->SetDescriptor(i, &inner_desc);
10068    }
10069  } else {
10070    for (int i = 0; i < size; ++i) {
10071      descriptors->CopyFrom(i, *desc);
10072    }
10073  }
10074
10075  if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
10076
10077  return descriptors;
10078}
10079
10080
10081bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
10082  for (int i = 0; i < nof_descriptors; i++) {
10083    if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
10084      return false;
10085    }
10086    PropertyDetails details = GetDetails(i);
10087    PropertyDetails other_details = desc->GetDetails(i);
10088    if (details.type() != other_details.type() ||
10089        !details.representation().Equals(other_details.representation())) {
10090      return false;
10091    }
10092  }
10093  return true;
10094}
10095
10096
10097Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
10098                                       Handle<DescriptorArray> descriptors,
10099                                       Descriptor* descriptor,
10100                                       int insertion_index,
10101                                       TransitionFlag flag) {
10102  // Ensure the key is unique.
10103  descriptor->KeyToUniqueName();
10104
10105  Handle<Name> key = descriptor->GetKey();
10106  DCHECK(*key == descriptors->GetKey(insertion_index));
10107
10108  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
10109      descriptors, map->NumberOfOwnDescriptors());
10110
10111  new_descriptors->Replace(insertion_index, descriptor);
10112  Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
10113      map, new_descriptors, new_descriptors->number_of_descriptors());
10114
10115  SimpleTransitionFlag simple_flag =
10116      (insertion_index == descriptors->number_of_descriptors() - 1)
10117          ? SIMPLE_PROPERTY_TRANSITION
10118          : PROPERTY_TRANSITION;
10119  return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
10120                                flag, key, "CopyReplaceDescriptor",
10121                                simple_flag);
10122}
10123
10124
10125void Map::UpdateCodeCache(Handle<Map> map,
10126                          Handle<Name> name,
10127                          Handle<Code> code) {
10128  Isolate* isolate = map->GetIsolate();
10129  HandleScope scope(isolate);
10130  // Allocate the code cache if not present.
10131  if (map->code_cache()->IsFixedArray()) {
10132    Handle<Object> result = isolate->factory()->NewCodeCache();
10133    map->set_code_cache(*result);
10134  }
10135
10136  // Update the code cache.
10137  Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
10138  CodeCache::Update(code_cache, name, code);
10139}
10140
10141
10142Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
10143  // Do a lookup if a code cache exists.
10144  if (!code_cache()->IsFixedArray()) {
10145    return CodeCache::cast(code_cache())->Lookup(name, flags);
10146  } else {
10147    return GetHeap()->undefined_value();
10148  }
10149}
10150
10151
10152int Map::IndexInCodeCache(Object* name, Code* code) {
10153  // Get the internal index if a code cache exists.
10154  if (!code_cache()->IsFixedArray()) {
10155    return CodeCache::cast(code_cache())->GetIndex(name, code);
10156  }
10157  return -1;
10158}
10159
10160
10161void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
10162  // No GC is supposed to happen between a call to IndexInCodeCache and
10163  // RemoveFromCodeCache so the code cache must be there.
10164  DCHECK(!code_cache()->IsFixedArray());
10165  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
10166}
10167
10168
10169void CodeCache::Update(
10170    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10171  // The number of monomorphic stubs for normal load/store/call IC's can grow to
10172  // a large number and therefore they need to go into a hash table. They are
10173  // used to load global properties from cells.
10174  if (code->type() == Code::NORMAL) {
10175    // Make sure that a hash table is allocated for the normal load code cache.
10176    if (code_cache->normal_type_cache()->IsUndefined()) {
10177      Handle<Object> result =
10178          CodeCacheHashTable::New(code_cache->GetIsolate(),
10179                                  CodeCacheHashTable::kInitialSize);
10180      code_cache->set_normal_type_cache(*result);
10181    }
10182    UpdateNormalTypeCache(code_cache, name, code);
10183  } else {
10184    DCHECK(code_cache->default_cache()->IsFixedArray());
10185    UpdateDefaultCache(code_cache, name, code);
10186  }
10187}
10188
10189
10190void CodeCache::UpdateDefaultCache(
10191    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10192  // When updating the default code cache we disregard the type encoded in the
10193  // flags. This allows call constant stubs to overwrite call field
10194  // stubs, etc.
10195  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
10196
10197  // First check whether we can update existing code cache without
10198  // extending it.
10199  Handle<FixedArray> cache = handle(code_cache->default_cache());
10200  int length = cache->length();
10201  {
10202    DisallowHeapAllocation no_alloc;
10203    int deleted_index = -1;
10204    for (int i = 0; i < length; i += kCodeCacheEntrySize) {
10205      Object* key = cache->get(i);
10206      if (key->IsNull()) {
10207        if (deleted_index < 0) deleted_index = i;
10208        continue;
10209      }
10210      if (key->IsUndefined()) {
10211        if (deleted_index >= 0) i = deleted_index;
10212        cache->set(i + kCodeCacheEntryNameOffset, *name);
10213        cache->set(i + kCodeCacheEntryCodeOffset, *code);
10214        return;
10215      }
10216      if (name->Equals(Name::cast(key))) {
10217        Code::Flags found =
10218            Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
10219        if (Code::RemoveTypeFromFlags(found) == flags) {
10220          cache->set(i + kCodeCacheEntryCodeOffset, *code);
10221          return;
10222        }
10223      }
10224    }
10225
10226    // Reached the end of the code cache.  If there were deleted
10227    // elements, reuse the space for the first of them.
10228    if (deleted_index >= 0) {
10229      cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
10230      cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
10231      return;
10232    }
10233  }
10234
10235  // Extend the code cache with some new entries (at least one). Must be a
10236  // multiple of the entry size.
10237  Isolate* isolate = cache->GetIsolate();
10238  int new_length = length + (length >> 1) + kCodeCacheEntrySize;
10239  new_length = new_length - new_length % kCodeCacheEntrySize;
10240  DCHECK((new_length % kCodeCacheEntrySize) == 0);
10241  cache = isolate->factory()->CopyFixedArrayAndGrow(cache, new_length - length);
10242
10243  // Add the (name, code) pair to the new cache.
10244  cache->set(length + kCodeCacheEntryNameOffset, *name);
10245  cache->set(length + kCodeCacheEntryCodeOffset, *code);
10246  code_cache->set_default_cache(*cache);
10247}
10248
10249
10250void CodeCache::UpdateNormalTypeCache(
10251    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10252  // Adding a new entry can cause a new cache to be allocated.
10253  Handle<CodeCacheHashTable> cache(
10254      CodeCacheHashTable::cast(code_cache->normal_type_cache()));
10255  Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
10256  code_cache->set_normal_type_cache(*new_cache);
10257}
10258
10259
10260Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
10261  Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
10262  if (result->IsCode()) {
10263    if (Code::cast(result)->flags() == flags) return result;
10264    return GetHeap()->undefined_value();
10265  }
10266  return LookupNormalTypeCache(name, flags);
10267}
10268
10269
10270Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
10271  FixedArray* cache = default_cache();
10272  int length = cache->length();
10273  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
10274    Object* key = cache->get(i + kCodeCacheEntryNameOffset);
10275    // Skip deleted elements.
10276    if (key->IsNull()) continue;
10277    if (key->IsUndefined()) return key;
10278    if (name->Equals(Name::cast(key))) {
10279      Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
10280      if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
10281        return code;
10282      }
10283    }
10284  }
10285  return GetHeap()->undefined_value();
10286}
10287
10288
10289Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
10290  if (!normal_type_cache()->IsUndefined()) {
10291    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10292    return cache->Lookup(name, flags);
10293  } else {
10294    return GetHeap()->undefined_value();
10295  }
10296}
10297
10298
10299int CodeCache::GetIndex(Object* name, Code* code) {
10300  if (code->type() == Code::NORMAL) {
10301    if (normal_type_cache()->IsUndefined()) return -1;
10302    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10303    return cache->GetIndex(Name::cast(name), code->flags());
10304  }
10305
10306  FixedArray* array = default_cache();
10307  int len = array->length();
10308  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
10309    if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
10310  }
10311  return -1;
10312}
10313
10314
10315void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
10316  if (code->type() == Code::NORMAL) {
10317    DCHECK(!normal_type_cache()->IsUndefined());
10318    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10319    DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
10320    cache->RemoveByIndex(index);
10321  } else {
10322    FixedArray* array = default_cache();
10323    DCHECK(array->length() >= index && array->get(index)->IsCode());
10324    // Use null instead of undefined for deleted elements to distinguish
10325    // deleted elements from unused elements.  This distinction is used
10326    // when looking up in the cache and when updating the cache.
10327    DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
10328    array->set_null(index - 1);  // Name.
10329    array->set_null(index);  // Code.
10330  }
10331}
10332
10333
10334// The key in the code cache hash table consists of the property name and the
10335// code object. The actual match is on the name and the code flags. If a key
10336// is created using the flags and not a code object it can only be used for
10337// lookup not to create a new entry.
10338class CodeCacheHashTableKey : public HashTableKey {
10339 public:
10340  CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
10341      : name_(name), flags_(flags), code_() { }
10342
10343  CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
10344      : name_(name), flags_(code->flags()), code_(code) { }
10345
10346  bool IsMatch(Object* other) override {
10347    if (!other->IsFixedArray()) return false;
10348    FixedArray* pair = FixedArray::cast(other);
10349    Name* name = Name::cast(pair->get(0));
10350    Code::Flags flags = Code::cast(pair->get(1))->flags();
10351    if (flags != flags_) {
10352      return false;
10353    }
10354    return name_->Equals(name);
10355  }
10356
10357  static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
10358    return name->Hash() ^ flags;
10359  }
10360
10361  uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
10362
10363  uint32_t HashForObject(Object* obj) override {
10364    FixedArray* pair = FixedArray::cast(obj);
10365    Name* name = Name::cast(pair->get(0));
10366    Code* code = Code::cast(pair->get(1));
10367    return NameFlagsHashHelper(name, code->flags());
10368  }
10369
10370  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
10371    Handle<Code> code = code_.ToHandleChecked();
10372    Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
10373    pair->set(0, *name_);
10374    pair->set(1, *code);
10375    return pair;
10376  }
10377
10378 private:
10379  Handle<Name> name_;
10380  Code::Flags flags_;
10381  // TODO(jkummerow): We should be able to get by without this.
10382  MaybeHandle<Code> code_;
10383};
10384
10385
10386Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
10387  DisallowHeapAllocation no_alloc;
10388  CodeCacheHashTableKey key(handle(name), flags);
10389  int entry = FindEntry(&key);
10390  if (entry == kNotFound) return GetHeap()->undefined_value();
10391  return get(EntryToIndex(entry) + 1);
10392}
10393
10394
10395Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
10396    Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
10397  CodeCacheHashTableKey key(name, code);
10398
10399  Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
10400
10401  int entry = new_cache->FindInsertionEntry(key.Hash());
10402  Handle<Object> k = key.AsHandle(cache->GetIsolate());
10403
10404  new_cache->set(EntryToIndex(entry), *k);
10405  new_cache->set(EntryToIndex(entry) + 1, *code);
10406  new_cache->ElementAdded();
10407  return new_cache;
10408}
10409
10410
10411int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
10412  DisallowHeapAllocation no_alloc;
10413  CodeCacheHashTableKey key(handle(name), flags);
10414  int entry = FindEntry(&key);
10415  return (entry == kNotFound) ? -1 : entry;
10416}
10417
10418
10419void CodeCacheHashTable::RemoveByIndex(int index) {
10420  DCHECK(index >= 0);
10421  Heap* heap = GetHeap();
10422  set(EntryToIndex(index), heap->the_hole_value());
10423  set(EntryToIndex(index) + 1, heap->the_hole_value());
10424  ElementRemoved();
10425}
10426
10427
10428void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
10429                                  MapHandleList* maps,
10430                                  Code::Flags flags,
10431                                  Handle<Code> code) {
10432  Isolate* isolate = code_cache->GetIsolate();
10433  if (code_cache->cache()->IsUndefined()) {
10434    Handle<PolymorphicCodeCacheHashTable> result =
10435        PolymorphicCodeCacheHashTable::New(
10436            isolate,
10437            PolymorphicCodeCacheHashTable::kInitialSize);
10438    code_cache->set_cache(*result);
10439  } else {
10440    // This entry shouldn't be contained in the cache yet.
10441    DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
10442               ->Lookup(maps, flags)->IsUndefined());
10443  }
10444  Handle<PolymorphicCodeCacheHashTable> hash_table =
10445      handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
10446  Handle<PolymorphicCodeCacheHashTable> new_cache =
10447      PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
10448  code_cache->set_cache(*new_cache);
10449}
10450
10451
10452Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
10453                                            Code::Flags flags) {
10454  if (!cache()->IsUndefined()) {
10455    PolymorphicCodeCacheHashTable* hash_table =
10456        PolymorphicCodeCacheHashTable::cast(cache());
10457    return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
10458  } else {
10459    return GetIsolate()->factory()->undefined_value();
10460  }
10461}
10462
10463
10464// Despite their name, object of this class are not stored in the actual
10465// hash table; instead they're temporarily used for lookups. It is therefore
10466// safe to have a weak (non-owning) pointer to a MapList as a member field.
10467class PolymorphicCodeCacheHashTableKey : public HashTableKey {
10468 public:
10469  // Callers must ensure that |maps| outlives the newly constructed object.
10470  PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
10471      : maps_(maps),
10472        code_flags_(code_flags) {}
10473
10474  bool IsMatch(Object* other) override {
10475    MapHandleList other_maps(kDefaultListAllocationSize);
10476    int other_flags;
10477    FromObject(other, &other_flags, &other_maps);
10478    if (code_flags_ != other_flags) return false;
10479    if (maps_->length() != other_maps.length()) return false;
10480    // Compare just the hashes first because it's faster.
10481    int this_hash = MapsHashHelper(maps_, code_flags_);
10482    int other_hash = MapsHashHelper(&other_maps, other_flags);
10483    if (this_hash != other_hash) return false;
10484
10485    // Full comparison: for each map in maps_, look for an equivalent map in
10486    // other_maps. This implementation is slow, but probably good enough for
10487    // now because the lists are short (<= 4 elements currently).
10488    for (int i = 0; i < maps_->length(); ++i) {
10489      bool match_found = false;
10490      for (int j = 0; j < other_maps.length(); ++j) {
10491        if (*(maps_->at(i)) == *(other_maps.at(j))) {
10492          match_found = true;
10493          break;
10494        }
10495      }
10496      if (!match_found) return false;
10497    }
10498    return true;
10499  }
10500
10501  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
10502    uint32_t hash = code_flags;
10503    for (int i = 0; i < maps->length(); ++i) {
10504      hash ^= maps->at(i)->Hash();
10505    }
10506    return hash;
10507  }
10508
10509  uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
10510
10511  uint32_t HashForObject(Object* obj) override {
10512    MapHandleList other_maps(kDefaultListAllocationSize);
10513    int other_flags;
10514    FromObject(obj, &other_flags, &other_maps);
10515    return MapsHashHelper(&other_maps, other_flags);
10516  }
10517
10518  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
10519    // The maps in |maps_| must be copied to a newly allocated FixedArray,
10520    // both because the referenced MapList is short-lived, and because C++
10521    // objects can't be stored in the heap anyway.
10522    Handle<FixedArray> list =
10523        isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
10524    list->set(0, Smi::FromInt(code_flags_));
10525    for (int i = 0; i < maps_->length(); ++i) {
10526      list->set(i + 1, *maps_->at(i));
10527    }
10528    return list;
10529  }
10530
10531 private:
10532  static MapHandleList* FromObject(Object* obj,
10533                                   int* code_flags,
10534                                   MapHandleList* maps) {
10535    FixedArray* list = FixedArray::cast(obj);
10536    maps->Rewind(0);
10537    *code_flags = Smi::cast(list->get(0))->value();
10538    for (int i = 1; i < list->length(); ++i) {
10539      maps->Add(Handle<Map>(Map::cast(list->get(i))));
10540    }
10541    return maps;
10542  }
10543
10544  MapHandleList* maps_;  // weak.
10545  int code_flags_;
10546  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
10547};
10548
10549
10550Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
10551                                              int code_kind) {
10552  DisallowHeapAllocation no_alloc;
10553  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
10554  int entry = FindEntry(&key);
10555  if (entry == kNotFound) return GetHeap()->undefined_value();
10556  return get(EntryToIndex(entry) + 1);
10557}
10558
10559
10560Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
10561      Handle<PolymorphicCodeCacheHashTable> hash_table,
10562      MapHandleList* maps,
10563      int code_kind,
10564      Handle<Code> code) {
10565  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
10566  Handle<PolymorphicCodeCacheHashTable> cache =
10567      EnsureCapacity(hash_table, 1, &key);
10568  int entry = cache->FindInsertionEntry(key.Hash());
10569
10570  Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
10571  cache->set(EntryToIndex(entry), *obj);
10572  cache->set(EntryToIndex(entry) + 1, *code);
10573  cache->ElementAdded();
10574  return cache;
10575}
10576
10577
10578void FixedArray::Shrink(int new_length) {
10579  DCHECK(0 <= new_length && new_length <= length());
10580  if (new_length < length()) {
10581    GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
10582        this, length() - new_length);
10583  }
10584}
10585
10586
10587void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
10588  DisallowHeapAllocation no_gc;
10589  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
10590  for (int index = 0; index < len; index++) {
10591    dest->set(dest_pos+index, get(pos+index), mode);
10592  }
10593}
10594
10595
10596#ifdef DEBUG
10597bool FixedArray::IsEqualTo(FixedArray* other) {
10598  if (length() != other->length()) return false;
10599  for (int i = 0 ; i < length(); ++i) {
10600    if (get(i) != other->get(i)) return false;
10601  }
10602  return true;
10603}
10604#endif
10605
10606
10607// static
10608void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
10609                         Handle<HeapObject> value) {
10610  DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
10611  Handle<WeakCell> cell =
10612      value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
10613                     : array->GetIsolate()->factory()->NewWeakCell(value);
10614  Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
10615  if (FLAG_trace_weak_arrays) {
10616    PrintF("[WeakFixedArray: storing at index %d ]\n", index);
10617  }
10618  array->set_last_used_index(index);
10619}
10620
10621
10622// static
10623Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array,
10624                                           Handle<HeapObject> value,
10625                                           int* assigned_index) {
10626  Handle<WeakFixedArray> array =
10627      (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
10628          ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
10629          : Handle<WeakFixedArray>::cast(maybe_array);
10630  // Try to store the new entry if there's room. Optimize for consecutive
10631  // accesses.
10632  int first_index = array->last_used_index();
10633  int length = array->Length();
10634  if (length > 0) {
10635    for (int i = first_index;;) {
10636      if (array->IsEmptySlot((i))) {
10637        WeakFixedArray::Set(array, i, value);
10638        if (assigned_index != NULL) *assigned_index = i;
10639        return array;
10640      }
10641      if (FLAG_trace_weak_arrays) {
10642        PrintF("[WeakFixedArray: searching for free slot]\n");
10643      }
10644      i = (i + 1) % length;
10645      if (i == first_index) break;
10646    }
10647  }
10648
10649  // No usable slot found, grow the array.
10650  int new_length = length == 0 ? 1 : length + (length >> 1) + 4;
10651  Handle<WeakFixedArray> new_array =
10652      Allocate(array->GetIsolate(), new_length, array);
10653  if (FLAG_trace_weak_arrays) {
10654    PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
10655  }
10656  WeakFixedArray::Set(new_array, length, value);
10657  if (assigned_index != NULL) *assigned_index = length;
10658  return new_array;
10659}
10660
10661
10662template <class CompactionCallback>
10663void WeakFixedArray::Compact() {
10664  FixedArray* array = FixedArray::cast(this);
10665  int new_length = kFirstIndex;
10666  for (int i = kFirstIndex; i < array->length(); i++) {
10667    Object* element = array->get(i);
10668    if (element->IsSmi()) continue;
10669    if (WeakCell::cast(element)->cleared()) continue;
10670    Object* value = WeakCell::cast(element)->value();
10671    CompactionCallback::Callback(value, i - kFirstIndex,
10672                                 new_length - kFirstIndex);
10673    array->set(new_length++, element);
10674  }
10675  array->Shrink(new_length);
10676  set_last_used_index(0);
10677}
10678
10679
10680void WeakFixedArray::Iterator::Reset(Object* maybe_array) {
10681  if (maybe_array->IsWeakFixedArray()) {
10682    list_ = WeakFixedArray::cast(maybe_array);
10683    index_ = 0;
10684#ifdef DEBUG
10685    last_used_index_ = list_->last_used_index();
10686#endif  // DEBUG
10687  }
10688}
10689
10690
10691void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value,
10692                                                             int old_index,
10693                                                             int new_index) {
10694  DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
10695  Map* map = Map::cast(value);
10696  DCHECK(map->prototype_info()->IsPrototypeInfo());
10697  PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
10698  DCHECK_EQ(old_index, proto_info->registry_slot());
10699  proto_info->set_registry_slot(new_index);
10700}
10701
10702
10703template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>();
10704template void
10705WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>();
10706
10707
10708bool WeakFixedArray::Remove(Handle<HeapObject> value) {
10709  if (Length() == 0) return false;
10710  // Optimize for the most recently added element to be removed again.
10711  int first_index = last_used_index();
10712  for (int i = first_index;;) {
10713    if (Get(i) == *value) {
10714      Clear(i);
10715      // Users of WeakFixedArray should make sure that there are no duplicates.
10716      return true;
10717    }
10718    i = (i + 1) % Length();
10719    if (i == first_index) return false;
10720  }
10721  UNREACHABLE();
10722}
10723
10724
10725// static
10726Handle<WeakFixedArray> WeakFixedArray::Allocate(
10727    Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
10728  DCHECK(0 <= size);
10729  Handle<FixedArray> result =
10730      isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
10731  int index = 0;
10732  if (!initialize_from.is_null()) {
10733    DCHECK(initialize_from->Length() <= size);
10734    Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
10735    // Copy the entries without compacting, since the PrototypeInfo relies on
10736    // the index of the entries not to change.
10737    while (index < raw_source->length()) {
10738      result->set(index, raw_source->get(index));
10739      index++;
10740    }
10741  }
10742  while (index < result->length()) {
10743    result->set(index, Smi::FromInt(0));
10744    index++;
10745  }
10746  return Handle<WeakFixedArray>::cast(result);
10747}
10748
10749
10750Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
10751                                 AddMode mode) {
10752  int length = array->Length();
10753  array = EnsureSpace(array, length + 1);
10754  if (mode == kReloadLengthAfterAllocation) {
10755    DCHECK(array->Length() <= length);
10756    length = array->Length();
10757  }
10758  array->Set(length, *obj);
10759  array->SetLength(length + 1);
10760  return array;
10761}
10762
10763
10764Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
10765                                 Handle<Object> obj2, AddMode mode) {
10766  int length = array->Length();
10767  array = EnsureSpace(array, length + 2);
10768  if (mode == kReloadLengthAfterAllocation) {
10769    length = array->Length();
10770  }
10771  array->Set(length, *obj1);
10772  array->Set(length + 1, *obj2);
10773  array->SetLength(length + 2);
10774  return array;
10775}
10776
10777
10778bool ArrayList::IsFull() {
10779  int capacity = length();
10780  return kFirstIndex + Length() == capacity;
10781}
10782
10783
10784Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
10785  int capacity = array->length();
10786  bool empty = (capacity == 0);
10787  if (capacity < kFirstIndex + length) {
10788    Isolate* isolate = array->GetIsolate();
10789    int new_capacity = kFirstIndex + length;
10790    new_capacity = new_capacity + Max(new_capacity / 2, 2);
10791    int grow_by = new_capacity - capacity;
10792    array = Handle<ArrayList>::cast(
10793        isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
10794    if (empty) array->SetLength(0);
10795  }
10796  return array;
10797}
10798
10799
10800Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
10801                                                  int number_of_descriptors,
10802                                                  int slack) {
10803  DCHECK(0 <= number_of_descriptors);
10804  Factory* factory = isolate->factory();
10805  // Do not use DescriptorArray::cast on incomplete object.
10806  int size = number_of_descriptors + slack;
10807  if (size == 0) return factory->empty_descriptor_array();
10808  // Allocate the array of keys.
10809  Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size), TENURED);
10810
10811  result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
10812  result->set(kEnumCacheIndex, Smi::FromInt(0));
10813  return Handle<DescriptorArray>::cast(result);
10814}
10815
10816
10817void DescriptorArray::ClearEnumCache() {
10818  set(kEnumCacheIndex, Smi::FromInt(0));
10819}
10820
10821
10822void DescriptorArray::Replace(int index, Descriptor* descriptor) {
10823  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
10824  Set(index, descriptor);
10825}
10826
10827
10828// static
10829void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
10830                                   Isolate* isolate,
10831                                   Handle<FixedArray> new_cache,
10832                                   Handle<FixedArray> new_index_cache) {
10833  DCHECK(!descriptors->IsEmpty());
10834  FixedArray* bridge_storage;
10835  bool needs_new_enum_cache = !descriptors->HasEnumCache();
10836  if (needs_new_enum_cache) {
10837    bridge_storage = *isolate->factory()->NewFixedArray(
10838        DescriptorArray::kEnumCacheBridgeLength);
10839  } else {
10840    bridge_storage = FixedArray::cast(descriptors->get(kEnumCacheIndex));
10841  }
10842  bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
10843  bridge_storage->set(kEnumCacheBridgeIndicesCacheIndex,
10844                      new_index_cache.is_null() ? Object::cast(Smi::FromInt(0))
10845                                                : *new_index_cache);
10846  if (needs_new_enum_cache) {
10847    descriptors->set(kEnumCacheIndex, bridge_storage);
10848  }
10849}
10850
10851
10852void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
10853  Object* value = src->GetValue(index);
10854  PropertyDetails details = src->GetDetails(index);
10855  Descriptor desc(handle(src->GetKey(index)),
10856                  handle(value, src->GetIsolate()),
10857                  details);
10858  SetDescriptor(index, &desc);
10859}
10860
10861
10862void DescriptorArray::Sort() {
10863  // In-place heap sort.
10864  int len = number_of_descriptors();
10865  // Reset sorting since the descriptor array might contain invalid pointers.
10866  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
10867  // Bottom-up max-heap construction.
10868  // Index of the last node with children
10869  const int max_parent_index = (len / 2) - 1;
10870  for (int i = max_parent_index; i >= 0; --i) {
10871    int parent_index = i;
10872    const uint32_t parent_hash = GetSortedKey(i)->Hash();
10873    while (parent_index <= max_parent_index) {
10874      int child_index = 2 * parent_index + 1;
10875      uint32_t child_hash = GetSortedKey(child_index)->Hash();
10876      if (child_index + 1 < len) {
10877        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10878        if (right_child_hash > child_hash) {
10879          child_index++;
10880          child_hash = right_child_hash;
10881        }
10882      }
10883      if (child_hash <= parent_hash) break;
10884      SwapSortedKeys(parent_index, child_index);
10885      // Now element at child_index could be < its children.
10886      parent_index = child_index;  // parent_hash remains correct.
10887    }
10888  }
10889
10890  // Extract elements and create sorted array.
10891  for (int i = len - 1; i > 0; --i) {
10892    // Put max element at the back of the array.
10893    SwapSortedKeys(0, i);
10894    // Shift down the new top element.
10895    int parent_index = 0;
10896    const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
10897    const int max_parent_index = (i / 2) - 1;
10898    while (parent_index <= max_parent_index) {
10899      int child_index = parent_index * 2 + 1;
10900      uint32_t child_hash = GetSortedKey(child_index)->Hash();
10901      if (child_index + 1 < i) {
10902        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
10903        if (right_child_hash > child_hash) {
10904          child_index++;
10905          child_hash = right_child_hash;
10906        }
10907      }
10908      if (child_hash <= parent_hash) break;
10909      SwapSortedKeys(parent_index, child_index);
10910      parent_index = child_index;
10911    }
10912  }
10913  DCHECK(IsSortedNoDuplicates());
10914}
10915
10916
10917Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
10918  Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
10919  copy->set_getter(pair->getter());
10920  copy->set_setter(pair->setter());
10921  return copy;
10922}
10923
10924
10925Object* AccessorPair::GetComponent(AccessorComponent component) {
10926  Object* accessor = get(component);
10927  return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
10928}
10929
10930
10931Handle<DeoptimizationInputData> DeoptimizationInputData::New(
10932    Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
10933  return Handle<DeoptimizationInputData>::cast(
10934      isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
10935                                        pretenure));
10936}
10937
10938
10939Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
10940    Isolate* isolate,
10941    int number_of_deopt_points,
10942    PretenureFlag pretenure) {
10943  Handle<FixedArray> result;
10944  if (number_of_deopt_points == 0) {
10945    result = isolate->factory()->empty_fixed_array();
10946  } else {
10947    result = isolate->factory()->NewFixedArray(
10948        LengthOfFixedArray(number_of_deopt_points), pretenure);
10949  }
10950  return Handle<DeoptimizationOutputData>::cast(result);
10951}
10952
10953
10954// static
10955Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate,
10956                                         Handle<TypeFeedbackVector> vector,
10957                                         int number_of_literals,
10958                                         PretenureFlag pretenure) {
10959  Handle<FixedArray> literals = isolate->factory()->NewFixedArray(
10960      number_of_literals + kFirstLiteralIndex, pretenure);
10961  Handle<LiteralsArray> casted_literals = Handle<LiteralsArray>::cast(literals);
10962  casted_literals->set_feedback_vector(*vector);
10963  return casted_literals;
10964}
10965
10966
10967int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out,
10968                              CatchPrediction* prediction_out) {
10969  int innermost_handler = -1, innermost_start = -1;
10970  for (int i = 0; i < length(); i += kRangeEntrySize) {
10971    int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
10972    int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
10973    int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
10974    int handler_offset = HandlerOffsetField::decode(handler_field);
10975    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
10976    int stack_depth = Smi::cast(get(i + kRangeDepthIndex))->value();
10977    if (pc_offset > start_offset && pc_offset <= end_offset) {
10978      DCHECK_NE(start_offset, innermost_start);
10979      if (start_offset < innermost_start) continue;
10980      innermost_handler = handler_offset;
10981      innermost_start = start_offset;
10982      *stack_depth_out = stack_depth;
10983      if (prediction_out) *prediction_out = prediction;
10984    }
10985  }
10986  return innermost_handler;
10987}
10988
10989
10990// TODO(turbofan): Make sure table is sorted and use binary search.
10991int HandlerTable::LookupReturn(int pc_offset, CatchPrediction* prediction_out) {
10992  for (int i = 0; i < length(); i += kReturnEntrySize) {
10993    int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
10994    int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
10995    if (pc_offset == return_offset) {
10996      if (prediction_out) {
10997        *prediction_out = HandlerPredictionField::decode(handler_field);
10998      }
10999      return HandlerOffsetField::decode(handler_field);
11000    }
11001  }
11002  return -1;
11003}
11004
11005
11006#ifdef DEBUG
11007bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
11008  if (IsEmpty()) return other->IsEmpty();
11009  if (other->IsEmpty()) return false;
11010  if (length() != other->length()) return false;
11011  for (int i = 0; i < length(); ++i) {
11012    if (get(i) != other->get(i)) return false;
11013  }
11014  return true;
11015}
11016#endif
11017
11018
11019bool String::LooksValid() {
11020  if (!GetIsolate()->heap()->Contains(this)) return false;
11021  return true;
11022}
11023
11024
11025// static
11026MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
11027  if (name->IsString()) return Handle<String>::cast(name);
11028  // ES6 section 9.2.11 SetFunctionName, step 4.
11029  Isolate* const isolate = name->GetIsolate();
11030  Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
11031  if (description->IsUndefined()) return isolate->factory()->empty_string();
11032  IncrementalStringBuilder builder(isolate);
11033  builder.AppendCharacter('[');
11034  builder.AppendString(Handle<String>::cast(description));
11035  builder.AppendCharacter(']');
11036  return builder.Finish();
11037}
11038
11039
11040namespace {
11041
11042bool AreDigits(const uint8_t* s, int from, int to) {
11043  for (int i = from; i < to; i++) {
11044    if (s[i] < '0' || s[i] > '9') return false;
11045  }
11046
11047  return true;
11048}
11049
11050
11051int ParseDecimalInteger(const uint8_t* s, int from, int to) {
11052  DCHECK(to - from < 10);  // Overflow is not possible.
11053  DCHECK(from < to);
11054  int d = s[from] - '0';
11055
11056  for (int i = from + 1; i < to; i++) {
11057    d = 10 * d + (s[i] - '0');
11058  }
11059
11060  return d;
11061}
11062
11063}  // namespace
11064
11065
11066// static
11067Handle<Object> String::ToNumber(Handle<String> subject) {
11068  Isolate* const isolate = subject->GetIsolate();
11069
11070  // Flatten {subject} string first.
11071  subject = String::Flatten(subject);
11072
11073  // Fast array index case.
11074  uint32_t index;
11075  if (subject->AsArrayIndex(&index)) {
11076    return isolate->factory()->NewNumberFromUint(index);
11077  }
11078
11079  // Fast case: short integer or some sorts of junk values.
11080  if (subject->IsSeqOneByteString()) {
11081    int len = subject->length();
11082    if (len == 0) return handle(Smi::FromInt(0), isolate);
11083
11084    DisallowHeapAllocation no_gc;
11085    uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
11086    bool minus = (data[0] == '-');
11087    int start_pos = (minus ? 1 : 0);
11088
11089    if (start_pos == len) {
11090      return isolate->factory()->nan_value();
11091    } else if (data[start_pos] > '9') {
11092      // Fast check for a junk value. A valid string may start from a
11093      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
11094      // or the 'I' character ('Infinity'). All of that have codes not greater
11095      // than '9' except 'I' and &nbsp;.
11096      if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
11097        return isolate->factory()->nan_value();
11098      }
11099    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
11100      // The maximal/minimal smi has 10 digits. If the string has less digits
11101      // we know it will fit into the smi-data type.
11102      int d = ParseDecimalInteger(data, start_pos, len);
11103      if (minus) {
11104        if (d == 0) return isolate->factory()->minus_zero_value();
11105        d = -d;
11106      } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
11107                 (len == 1 || data[0] != '0')) {
11108        // String hash is not calculated yet but all the data are present.
11109        // Update the hash field to speed up sequential convertions.
11110        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
11111#ifdef DEBUG
11112        subject->Hash();  // Force hash calculation.
11113        DCHECK_EQ(static_cast<int>(subject->hash_field()),
11114                  static_cast<int>(hash));
11115#endif
11116        subject->set_hash_field(hash);
11117      }
11118      return handle(Smi::FromInt(d), isolate);
11119    }
11120  }
11121
11122  // Slower case.
11123  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
11124  return isolate->factory()->NewNumber(
11125      StringToDouble(isolate->unicode_cache(), subject, flags));
11126}
11127
11128
11129String::FlatContent String::GetFlatContent() {
11130  DCHECK(!AllowHeapAllocation::IsAllowed());
11131  int length = this->length();
11132  StringShape shape(this);
11133  String* string = this;
11134  int offset = 0;
11135  if (shape.representation_tag() == kConsStringTag) {
11136    ConsString* cons = ConsString::cast(string);
11137    if (cons->second()->length() != 0) {
11138      return FlatContent();
11139    }
11140    string = cons->first();
11141    shape = StringShape(string);
11142  }
11143  if (shape.representation_tag() == kSlicedStringTag) {
11144    SlicedString* slice = SlicedString::cast(string);
11145    offset = slice->offset();
11146    string = slice->parent();
11147    shape = StringShape(string);
11148    DCHECK(shape.representation_tag() != kConsStringTag &&
11149           shape.representation_tag() != kSlicedStringTag);
11150  }
11151  if (shape.encoding_tag() == kOneByteStringTag) {
11152    const uint8_t* start;
11153    if (shape.representation_tag() == kSeqStringTag) {
11154      start = SeqOneByteString::cast(string)->GetChars();
11155    } else {
11156      start = ExternalOneByteString::cast(string)->GetChars();
11157    }
11158    return FlatContent(start + offset, length);
11159  } else {
11160    DCHECK(shape.encoding_tag() == kTwoByteStringTag);
11161    const uc16* start;
11162    if (shape.representation_tag() == kSeqStringTag) {
11163      start = SeqTwoByteString::cast(string)->GetChars();
11164    } else {
11165      start = ExternalTwoByteString::cast(string)->GetChars();
11166    }
11167    return FlatContent(start + offset, length);
11168  }
11169}
11170
11171
11172base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
11173                                                RobustnessFlag robust_flag,
11174                                                int offset, int length,
11175                                                int* length_return) {
11176  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
11177    return base::SmartArrayPointer<char>(NULL);
11178  }
11179  // Negative length means the to the end of the string.
11180  if (length < 0) length = kMaxInt - offset;
11181
11182  // Compute the size of the UTF-8 string. Start at the specified offset.
11183  StringCharacterStream stream(this, offset);
11184  int character_position = offset;
11185  int utf8_bytes = 0;
11186  int last = unibrow::Utf16::kNoPreviousCharacter;
11187  while (stream.HasMore() && character_position++ < offset + length) {
11188    uint16_t character = stream.GetNext();
11189    utf8_bytes += unibrow::Utf8::Length(character, last);
11190    last = character;
11191  }
11192
11193  if (length_return) {
11194    *length_return = utf8_bytes;
11195  }
11196
11197  char* result = NewArray<char>(utf8_bytes + 1);
11198
11199  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
11200  stream.Reset(this, offset);
11201  character_position = offset;
11202  int utf8_byte_position = 0;
11203  last = unibrow::Utf16::kNoPreviousCharacter;
11204  while (stream.HasMore() && character_position++ < offset + length) {
11205    uint16_t character = stream.GetNext();
11206    if (allow_nulls == DISALLOW_NULLS && character == 0) {
11207      character = ' ';
11208    }
11209    utf8_byte_position +=
11210        unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
11211    last = character;
11212  }
11213  result[utf8_byte_position] = 0;
11214  return base::SmartArrayPointer<char>(result);
11215}
11216
11217
11218base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
11219                                                RobustnessFlag robust_flag,
11220                                                int* length_return) {
11221  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
11222}
11223
11224
11225const uc16* String::GetTwoByteData(unsigned start) {
11226  DCHECK(!IsOneByteRepresentationUnderneath());
11227  switch (StringShape(this).representation_tag()) {
11228    case kSeqStringTag:
11229      return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
11230    case kExternalStringTag:
11231      return ExternalTwoByteString::cast(this)->
11232        ExternalTwoByteStringGetData(start);
11233    case kSlicedStringTag: {
11234      SlicedString* slice = SlicedString::cast(this);
11235      return slice->parent()->GetTwoByteData(start + slice->offset());
11236    }
11237    case kConsStringTag:
11238      UNREACHABLE();
11239      return NULL;
11240  }
11241  UNREACHABLE();
11242  return NULL;
11243}
11244
11245
11246base::SmartArrayPointer<uc16> String::ToWideCString(
11247    RobustnessFlag robust_flag) {
11248  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
11249    return base::SmartArrayPointer<uc16>();
11250  }
11251  StringCharacterStream stream(this);
11252
11253  uc16* result = NewArray<uc16>(length() + 1);
11254
11255  int i = 0;
11256  while (stream.HasMore()) {
11257    uint16_t character = stream.GetNext();
11258    result[i++] = character;
11259  }
11260  result[i] = 0;
11261  return base::SmartArrayPointer<uc16>(result);
11262}
11263
11264
11265const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
11266  return reinterpret_cast<uc16*>(
11267      reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
11268}
11269
11270
11271void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
11272  Relocatable* current = isolate->relocatable_top();
11273  while (current != NULL) {
11274    current->PostGarbageCollection();
11275    current = current->prev_;
11276  }
11277}
11278
11279
11280// Reserve space for statics needing saving and restoring.
11281int Relocatable::ArchiveSpacePerThread() {
11282  return sizeof(Relocatable*);  // NOLINT
11283}
11284
11285
11286// Archive statics that are thread-local.
11287char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
11288  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
11289  isolate->set_relocatable_top(NULL);
11290  return to + ArchiveSpacePerThread();
11291}
11292
11293
11294// Restore statics that are thread-local.
11295char* Relocatable::RestoreState(Isolate* isolate, char* from) {
11296  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
11297  return from + ArchiveSpacePerThread();
11298}
11299
11300
11301char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
11302  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
11303  Iterate(v, top);
11304  return thread_storage + ArchiveSpacePerThread();
11305}
11306
11307
11308void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
11309  Iterate(v, isolate->relocatable_top());
11310}
11311
11312
11313void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
11314  Relocatable* current = top;
11315  while (current != NULL) {
11316    current->IterateInstance(v);
11317    current = current->prev_;
11318  }
11319}
11320
11321
11322FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
11323    : Relocatable(isolate),
11324      str_(str.location()),
11325      length_(str->length()) {
11326  PostGarbageCollection();
11327}
11328
11329
11330FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
11331    : Relocatable(isolate),
11332      str_(0),
11333      is_one_byte_(true),
11334      length_(input.length()),
11335      start_(input.start()) {}
11336
11337
11338void FlatStringReader::PostGarbageCollection() {
11339  if (str_ == NULL) return;
11340  Handle<String> str(str_);
11341  DCHECK(str->IsFlat());
11342  DisallowHeapAllocation no_gc;
11343  // This does not actually prevent the vector from being relocated later.
11344  String::FlatContent content = str->GetFlatContent();
11345  DCHECK(content.IsFlat());
11346  is_one_byte_ = content.IsOneByte();
11347  if (is_one_byte_) {
11348    start_ = content.ToOneByteVector().start();
11349  } else {
11350    start_ = content.ToUC16Vector().start();
11351  }
11352}
11353
11354
11355void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
11356  DCHECK(cons_string != NULL);
11357  root_ = cons_string;
11358  consumed_ = offset;
11359  // Force stack blown condition to trigger restart.
11360  depth_ = 1;
11361  maximum_depth_ = kStackSize + depth_;
11362  DCHECK(StackBlown());
11363}
11364
11365
11366String* ConsStringIterator::Continue(int* offset_out) {
11367  DCHECK(depth_ != 0);
11368  DCHECK_EQ(0, *offset_out);
11369  bool blew_stack = StackBlown();
11370  String* string = NULL;
11371  // Get the next leaf if there is one.
11372  if (!blew_stack) string = NextLeaf(&blew_stack);
11373  // Restart search from root.
11374  if (blew_stack) {
11375    DCHECK(string == NULL);
11376    string = Search(offset_out);
11377  }
11378  // Ensure future calls return null immediately.
11379  if (string == NULL) Reset(NULL);
11380  return string;
11381}
11382
11383
11384String* ConsStringIterator::Search(int* offset_out) {
11385  ConsString* cons_string = root_;
11386  // Reset the stack, pushing the root string.
11387  depth_ = 1;
11388  maximum_depth_ = 1;
11389  frames_[0] = cons_string;
11390  const int consumed = consumed_;
11391  int offset = 0;
11392  while (true) {
11393    // Loop until the string is found which contains the target offset.
11394    String* string = cons_string->first();
11395    int length = string->length();
11396    int32_t type;
11397    if (consumed < offset + length) {
11398      // Target offset is in the left branch.
11399      // Keep going if we're still in a ConString.
11400      type = string->map()->instance_type();
11401      if ((type & kStringRepresentationMask) == kConsStringTag) {
11402        cons_string = ConsString::cast(string);
11403        PushLeft(cons_string);
11404        continue;
11405      }
11406      // Tell the stack we're done descending.
11407      AdjustMaximumDepth();
11408    } else {
11409      // Descend right.
11410      // Update progress through the string.
11411      offset += length;
11412      // Keep going if we're still in a ConString.
11413      string = cons_string->second();
11414      type = string->map()->instance_type();
11415      if ((type & kStringRepresentationMask) == kConsStringTag) {
11416        cons_string = ConsString::cast(string);
11417        PushRight(cons_string);
11418        continue;
11419      }
11420      // Need this to be updated for the current string.
11421      length = string->length();
11422      // Account for the possibility of an empty right leaf.
11423      // This happens only if we have asked for an offset outside the string.
11424      if (length == 0) {
11425        // Reset so future operations will return null immediately.
11426        Reset(NULL);
11427        return NULL;
11428      }
11429      // Tell the stack we're done descending.
11430      AdjustMaximumDepth();
11431      // Pop stack so next iteration is in correct place.
11432      Pop();
11433    }
11434    DCHECK(length != 0);
11435    // Adjust return values and exit.
11436    consumed_ = offset + length;
11437    *offset_out = consumed - offset;
11438    return string;
11439  }
11440  UNREACHABLE();
11441  return NULL;
11442}
11443
11444
11445String* ConsStringIterator::NextLeaf(bool* blew_stack) {
11446  while (true) {
11447    // Tree traversal complete.
11448    if (depth_ == 0) {
11449      *blew_stack = false;
11450      return NULL;
11451    }
11452    // We've lost track of higher nodes.
11453    if (StackBlown()) {
11454      *blew_stack = true;
11455      return NULL;
11456    }
11457    // Go right.
11458    ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
11459    String* string = cons_string->second();
11460    int32_t type = string->map()->instance_type();
11461    if ((type & kStringRepresentationMask) != kConsStringTag) {
11462      // Pop stack so next iteration is in correct place.
11463      Pop();
11464      int length = string->length();
11465      // Could be a flattened ConsString.
11466      if (length == 0) continue;
11467      consumed_ += length;
11468      return string;
11469    }
11470    cons_string = ConsString::cast(string);
11471    PushRight(cons_string);
11472    // Need to traverse all the way left.
11473    while (true) {
11474      // Continue left.
11475      string = cons_string->first();
11476      type = string->map()->instance_type();
11477      if ((type & kStringRepresentationMask) != kConsStringTag) {
11478        AdjustMaximumDepth();
11479        int length = string->length();
11480        DCHECK(length != 0);
11481        consumed_ += length;
11482        return string;
11483      }
11484      cons_string = ConsString::cast(string);
11485      PushLeft(cons_string);
11486    }
11487  }
11488  UNREACHABLE();
11489  return NULL;
11490}
11491
11492
11493uint16_t ConsString::ConsStringGet(int index) {
11494  DCHECK(index >= 0 && index < this->length());
11495
11496  // Check for a flattened cons string
11497  if (second()->length() == 0) {
11498    String* left = first();
11499    return left->Get(index);
11500  }
11501
11502  String* string = String::cast(this);
11503
11504  while (true) {
11505    if (StringShape(string).IsCons()) {
11506      ConsString* cons_string = ConsString::cast(string);
11507      String* left = cons_string->first();
11508      if (left->length() > index) {
11509        string = left;
11510      } else {
11511        index -= left->length();
11512        string = cons_string->second();
11513      }
11514    } else {
11515      return string->Get(index);
11516    }
11517  }
11518
11519  UNREACHABLE();
11520  return 0;
11521}
11522
11523
11524uint16_t SlicedString::SlicedStringGet(int index) {
11525  return parent()->Get(offset() + index);
11526}
11527
11528
11529template <typename sinkchar>
11530void String::WriteToFlat(String* src,
11531                         sinkchar* sink,
11532                         int f,
11533                         int t) {
11534  String* source = src;
11535  int from = f;
11536  int to = t;
11537  while (true) {
11538    DCHECK(0 <= from && from <= to && to <= source->length());
11539    switch (StringShape(source).full_representation_tag()) {
11540      case kOneByteStringTag | kExternalStringTag: {
11541        CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
11542                  to - from);
11543        return;
11544      }
11545      case kTwoByteStringTag | kExternalStringTag: {
11546        const uc16* data =
11547            ExternalTwoByteString::cast(source)->GetChars();
11548        CopyChars(sink,
11549                  data + from,
11550                  to - from);
11551        return;
11552      }
11553      case kOneByteStringTag | kSeqStringTag: {
11554        CopyChars(sink,
11555                  SeqOneByteString::cast(source)->GetChars() + from,
11556                  to - from);
11557        return;
11558      }
11559      case kTwoByteStringTag | kSeqStringTag: {
11560        CopyChars(sink,
11561                  SeqTwoByteString::cast(source)->GetChars() + from,
11562                  to - from);
11563        return;
11564      }
11565      case kOneByteStringTag | kConsStringTag:
11566      case kTwoByteStringTag | kConsStringTag: {
11567        ConsString* cons_string = ConsString::cast(source);
11568        String* first = cons_string->first();
11569        int boundary = first->length();
11570        if (to - boundary >= boundary - from) {
11571          // Right hand side is longer.  Recurse over left.
11572          if (from < boundary) {
11573            WriteToFlat(first, sink, from, boundary);
11574            sink += boundary - from;
11575            from = 0;
11576          } else {
11577            from -= boundary;
11578          }
11579          to -= boundary;
11580          source = cons_string->second();
11581        } else {
11582          // Left hand side is longer.  Recurse over right.
11583          if (to > boundary) {
11584            String* second = cons_string->second();
11585            // When repeatedly appending to a string, we get a cons string that
11586            // is unbalanced to the left, a list, essentially.  We inline the
11587            // common case of sequential one-byte right child.
11588            if (to - boundary == 1) {
11589              sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
11590            } else if (second->IsSeqOneByteString()) {
11591              CopyChars(sink + boundary - from,
11592                        SeqOneByteString::cast(second)->GetChars(),
11593                        to - boundary);
11594            } else {
11595              WriteToFlat(second,
11596                          sink + boundary - from,
11597                          0,
11598                          to - boundary);
11599            }
11600            to = boundary;
11601          }
11602          source = first;
11603        }
11604        break;
11605      }
11606      case kOneByteStringTag | kSlicedStringTag:
11607      case kTwoByteStringTag | kSlicedStringTag: {
11608        SlicedString* slice = SlicedString::cast(source);
11609        unsigned offset = slice->offset();
11610        WriteToFlat(slice->parent(), sink, from + offset, to + offset);
11611        return;
11612      }
11613    }
11614  }
11615}
11616
11617
11618
11619template <typename SourceChar>
11620static void CalculateLineEndsImpl(Isolate* isolate,
11621                                  List<int>* line_ends,
11622                                  Vector<const SourceChar> src,
11623                                  bool include_ending_line) {
11624  const int src_len = src.length();
11625  UnicodeCache* cache = isolate->unicode_cache();
11626  for (int i = 0; i < src_len - 1; i++) {
11627    SourceChar current = src[i];
11628    SourceChar next = src[i + 1];
11629    if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
11630  }
11631
11632  if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
11633    line_ends->Add(src_len - 1);
11634  }
11635  if (include_ending_line) {
11636    // Include one character beyond the end of script. The rewriter uses that
11637    // position for the implicit return statement.
11638    line_ends->Add(src_len);
11639  }
11640}
11641
11642
11643Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
11644                                             bool include_ending_line) {
11645  src = Flatten(src);
11646  // Rough estimate of line count based on a roughly estimated average
11647  // length of (unpacked) code.
11648  int line_count_estimate = src->length() >> 4;
11649  List<int> line_ends(line_count_estimate);
11650  Isolate* isolate = src->GetIsolate();
11651  { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
11652    // Dispatch on type of strings.
11653    String::FlatContent content = src->GetFlatContent();
11654    DCHECK(content.IsFlat());
11655    if (content.IsOneByte()) {
11656      CalculateLineEndsImpl(isolate,
11657                            &line_ends,
11658                            content.ToOneByteVector(),
11659                            include_ending_line);
11660    } else {
11661      CalculateLineEndsImpl(isolate,
11662                            &line_ends,
11663                            content.ToUC16Vector(),
11664                            include_ending_line);
11665    }
11666  }
11667  int line_count = line_ends.length();
11668  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
11669  for (int i = 0; i < line_count; i++) {
11670    array->set(i, Smi::FromInt(line_ends[i]));
11671  }
11672  return array;
11673}
11674
11675
11676// Compares the contents of two strings by reading and comparing
11677// int-sized blocks of characters.
11678template <typename Char>
11679static inline bool CompareRawStringContents(const Char* const a,
11680                                            const Char* const b,
11681                                            int length) {
11682  return CompareChars(a, b, length) == 0;
11683}
11684
11685
11686template<typename Chars1, typename Chars2>
11687class RawStringComparator : public AllStatic {
11688 public:
11689  static inline bool compare(const Chars1* a, const Chars2* b, int len) {
11690    DCHECK(sizeof(Chars1) != sizeof(Chars2));
11691    for (int i = 0; i < len; i++) {
11692      if (a[i] != b[i]) {
11693        return false;
11694      }
11695    }
11696    return true;
11697  }
11698};
11699
11700
11701template<>
11702class RawStringComparator<uint16_t, uint16_t> {
11703 public:
11704  static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
11705    return CompareRawStringContents(a, b, len);
11706  }
11707};
11708
11709
11710template<>
11711class RawStringComparator<uint8_t, uint8_t> {
11712 public:
11713  static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
11714    return CompareRawStringContents(a, b, len);
11715  }
11716};
11717
11718
11719class StringComparator {
11720  class State {
11721   public:
11722    State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
11723
11724    void Init(String* string) {
11725      ConsString* cons_string = String::VisitFlat(this, string);
11726      iter_.Reset(cons_string);
11727      if (cons_string != NULL) {
11728        int offset;
11729        string = iter_.Next(&offset);
11730        String::VisitFlat(this, string, offset);
11731      }
11732    }
11733
11734    inline void VisitOneByteString(const uint8_t* chars, int length) {
11735      is_one_byte_ = true;
11736      buffer8_ = chars;
11737      length_ = length;
11738    }
11739
11740    inline void VisitTwoByteString(const uint16_t* chars, int length) {
11741      is_one_byte_ = false;
11742      buffer16_ = chars;
11743      length_ = length;
11744    }
11745
11746    void Advance(int consumed) {
11747      DCHECK(consumed <= length_);
11748      // Still in buffer.
11749      if (length_ != consumed) {
11750        if (is_one_byte_) {
11751          buffer8_ += consumed;
11752        } else {
11753          buffer16_ += consumed;
11754        }
11755        length_ -= consumed;
11756        return;
11757      }
11758      // Advance state.
11759      int offset;
11760      String* next = iter_.Next(&offset);
11761      DCHECK_EQ(0, offset);
11762      DCHECK(next != NULL);
11763      String::VisitFlat(this, next);
11764    }
11765
11766    ConsStringIterator iter_;
11767    bool is_one_byte_;
11768    int length_;
11769    union {
11770      const uint8_t* buffer8_;
11771      const uint16_t* buffer16_;
11772    };
11773
11774   private:
11775    DISALLOW_COPY_AND_ASSIGN(State);
11776  };
11777
11778 public:
11779  inline StringComparator() {}
11780
11781  template<typename Chars1, typename Chars2>
11782  static inline bool Equals(State* state_1, State* state_2, int to_check) {
11783    const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
11784    const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
11785    return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
11786  }
11787
11788  bool Equals(String* string_1, String* string_2) {
11789    int length = string_1->length();
11790    state_1_.Init(string_1);
11791    state_2_.Init(string_2);
11792    while (true) {
11793      int to_check = Min(state_1_.length_, state_2_.length_);
11794      DCHECK(to_check > 0 && to_check <= length);
11795      bool is_equal;
11796      if (state_1_.is_one_byte_) {
11797        if (state_2_.is_one_byte_) {
11798          is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
11799        } else {
11800          is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
11801        }
11802      } else {
11803        if (state_2_.is_one_byte_) {
11804          is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
11805        } else {
11806          is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
11807        }
11808      }
11809      // Looping done.
11810      if (!is_equal) return false;
11811      length -= to_check;
11812      // Exit condition. Strings are equal.
11813      if (length == 0) return true;
11814      state_1_.Advance(to_check);
11815      state_2_.Advance(to_check);
11816    }
11817  }
11818
11819 private:
11820  State state_1_;
11821  State state_2_;
11822
11823  DISALLOW_COPY_AND_ASSIGN(StringComparator);
11824};
11825
11826
11827bool String::SlowEquals(String* other) {
11828  DisallowHeapAllocation no_gc;
11829  // Fast check: negative check with lengths.
11830  int len = length();
11831  if (len != other->length()) return false;
11832  if (len == 0) return true;
11833
11834  // Fast check: if hash code is computed for both strings
11835  // a fast negative check can be performed.
11836  if (HasHashCode() && other->HasHashCode()) {
11837#ifdef ENABLE_SLOW_DCHECKS
11838    if (FLAG_enable_slow_asserts) {
11839      if (Hash() != other->Hash()) {
11840        bool found_difference = false;
11841        for (int i = 0; i < len; i++) {
11842          if (Get(i) != other->Get(i)) {
11843            found_difference = true;
11844            break;
11845          }
11846        }
11847        DCHECK(found_difference);
11848      }
11849    }
11850#endif
11851    if (Hash() != other->Hash()) return false;
11852  }
11853
11854  // We know the strings are both non-empty. Compare the first chars
11855  // before we try to flatten the strings.
11856  if (this->Get(0) != other->Get(0)) return false;
11857
11858  if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
11859    const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
11860    const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
11861    return CompareRawStringContents(str1, str2, len);
11862  }
11863
11864  StringComparator comparator;
11865  return comparator.Equals(this, other);
11866}
11867
11868
11869bool String::SlowEquals(Handle<String> one, Handle<String> two) {
11870  // Fast check: negative check with lengths.
11871  int one_length = one->length();
11872  if (one_length != two->length()) return false;
11873  if (one_length == 0) return true;
11874
11875  // Fast check: if hash code is computed for both strings
11876  // a fast negative check can be performed.
11877  if (one->HasHashCode() && two->HasHashCode()) {
11878#ifdef ENABLE_SLOW_DCHECKS
11879    if (FLAG_enable_slow_asserts) {
11880      if (one->Hash() != two->Hash()) {
11881        bool found_difference = false;
11882        for (int i = 0; i < one_length; i++) {
11883          if (one->Get(i) != two->Get(i)) {
11884            found_difference = true;
11885            break;
11886          }
11887        }
11888        DCHECK(found_difference);
11889      }
11890    }
11891#endif
11892    if (one->Hash() != two->Hash()) return false;
11893  }
11894
11895  // We know the strings are both non-empty. Compare the first chars
11896  // before we try to flatten the strings.
11897  if (one->Get(0) != two->Get(0)) return false;
11898
11899  one = String::Flatten(one);
11900  two = String::Flatten(two);
11901
11902  DisallowHeapAllocation no_gc;
11903  String::FlatContent flat1 = one->GetFlatContent();
11904  String::FlatContent flat2 = two->GetFlatContent();
11905
11906  if (flat1.IsOneByte() && flat2.IsOneByte()) {
11907      return CompareRawStringContents(flat1.ToOneByteVector().start(),
11908                                      flat2.ToOneByteVector().start(),
11909                                      one_length);
11910  } else {
11911    for (int i = 0; i < one_length; i++) {
11912      if (flat1.Get(i) != flat2.Get(i)) return false;
11913    }
11914    return true;
11915  }
11916}
11917
11918
11919// static
11920ComparisonResult String::Compare(Handle<String> x, Handle<String> y) {
11921  // A few fast case tests before we flatten.
11922  if (x.is_identical_to(y)) {
11923    return ComparisonResult::kEqual;
11924  } else if (y->length() == 0) {
11925    return x->length() == 0 ? ComparisonResult::kEqual
11926                            : ComparisonResult::kGreaterThan;
11927  } else if (x->length() == 0) {
11928    return ComparisonResult::kLessThan;
11929  }
11930
11931  int const d = x->Get(0) - y->Get(0);
11932  if (d < 0) {
11933    return ComparisonResult::kLessThan;
11934  } else if (d > 0) {
11935    return ComparisonResult::kGreaterThan;
11936  }
11937
11938  // Slow case.
11939  x = String::Flatten(x);
11940  y = String::Flatten(y);
11941
11942  DisallowHeapAllocation no_gc;
11943  ComparisonResult result = ComparisonResult::kEqual;
11944  int prefix_length = x->length();
11945  if (y->length() < prefix_length) {
11946    prefix_length = y->length();
11947    result = ComparisonResult::kGreaterThan;
11948  } else if (y->length() > prefix_length) {
11949    result = ComparisonResult::kLessThan;
11950  }
11951  int r;
11952  String::FlatContent x_content = x->GetFlatContent();
11953  String::FlatContent y_content = y->GetFlatContent();
11954  if (x_content.IsOneByte()) {
11955    Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
11956    if (y_content.IsOneByte()) {
11957      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11958      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11959    } else {
11960      Vector<const uc16> y_chars = y_content.ToUC16Vector();
11961      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11962    }
11963  } else {
11964    Vector<const uc16> x_chars = x_content.ToUC16Vector();
11965    if (y_content.IsOneByte()) {
11966      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
11967      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11968    } else {
11969      Vector<const uc16> y_chars = y_content.ToUC16Vector();
11970      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
11971    }
11972  }
11973  if (r < 0) {
11974    result = ComparisonResult::kLessThan;
11975  } else if (r > 0) {
11976    result = ComparisonResult::kGreaterThan;
11977  }
11978  return result;
11979}
11980
11981
11982bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
11983  int slen = length();
11984  // Can't check exact length equality, but we can check bounds.
11985  int str_len = str.length();
11986  if (!allow_prefix_match &&
11987      (str_len < slen ||
11988          str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
11989    return false;
11990  }
11991  int i;
11992  size_t remaining_in_str = static_cast<size_t>(str_len);
11993  const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
11994  for (i = 0; i < slen && remaining_in_str > 0; i++) {
11995    size_t cursor = 0;
11996    uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
11997    DCHECK(cursor > 0 && cursor <= remaining_in_str);
11998    if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
11999      if (i > slen - 1) return false;
12000      if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
12001      if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
12002    } else {
12003      if (Get(i) != r) return false;
12004    }
12005    utf8_data += cursor;
12006    remaining_in_str -= cursor;
12007  }
12008  return (allow_prefix_match || i == slen) && remaining_in_str == 0;
12009}
12010
12011
12012bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
12013  int slen = length();
12014  if (str.length() != slen) return false;
12015  DisallowHeapAllocation no_gc;
12016  FlatContent content = GetFlatContent();
12017  if (content.IsOneByte()) {
12018    return CompareChars(content.ToOneByteVector().start(),
12019                        str.start(), slen) == 0;
12020  }
12021  for (int i = 0; i < slen; i++) {
12022    if (Get(i) != static_cast<uint16_t>(str[i])) return false;
12023  }
12024  return true;
12025}
12026
12027
12028bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
12029  int slen = length();
12030  if (str.length() != slen) return false;
12031  DisallowHeapAllocation no_gc;
12032  FlatContent content = GetFlatContent();
12033  if (content.IsTwoByte()) {
12034    return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
12035  }
12036  for (int i = 0; i < slen; i++) {
12037    if (Get(i) != str[i]) return false;
12038  }
12039  return true;
12040}
12041
12042
12043uint32_t String::ComputeAndSetHash() {
12044  // Should only be called if hash code has not yet been computed.
12045  DCHECK(!HasHashCode());
12046
12047  // Store the hash code in the object.
12048  uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
12049  set_hash_field(field);
12050
12051  // Check the hash code is there.
12052  DCHECK(HasHashCode());
12053  uint32_t result = field >> kHashShift;
12054  DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
12055  return result;
12056}
12057
12058
12059bool String::ComputeArrayIndex(uint32_t* index) {
12060  int length = this->length();
12061  if (length == 0 || length > kMaxArrayIndexSize) return false;
12062  StringCharacterStream stream(this);
12063  return StringToArrayIndex(&stream, index);
12064}
12065
12066
12067bool String::SlowAsArrayIndex(uint32_t* index) {
12068  if (length() <= kMaxCachedArrayIndexLength) {
12069    Hash();  // force computation of hash code
12070    uint32_t field = hash_field();
12071    if ((field & kIsNotArrayIndexMask) != 0) return false;
12072    // Isolate the array index form the full hash field.
12073    *index = ArrayIndexValueBits::decode(field);
12074    return true;
12075  } else {
12076    return ComputeArrayIndex(index);
12077  }
12078}
12079
12080
12081Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
12082  int new_size, old_size;
12083  int old_length = string->length();
12084  if (old_length <= new_length) return string;
12085
12086  if (string->IsSeqOneByteString()) {
12087    old_size = SeqOneByteString::SizeFor(old_length);
12088    new_size = SeqOneByteString::SizeFor(new_length);
12089  } else {
12090    DCHECK(string->IsSeqTwoByteString());
12091    old_size = SeqTwoByteString::SizeFor(old_length);
12092    new_size = SeqTwoByteString::SizeFor(new_length);
12093  }
12094
12095  int delta = old_size - new_size;
12096
12097  Address start_of_string = string->address();
12098  DCHECK_OBJECT_ALIGNED(start_of_string);
12099  DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
12100
12101  Heap* heap = string->GetHeap();
12102  // Sizes are pointer size aligned, so that we can use filler objects
12103  // that are a multiple of pointer size.
12104  heap->CreateFillerObjectAt(start_of_string + new_size, delta);
12105  heap->AdjustLiveBytes(*string, -delta, Heap::CONCURRENT_TO_SWEEPER);
12106
12107  // We are storing the new length using release store after creating a filler
12108  // for the left-over space to avoid races with the sweeper thread.
12109  string->synchronized_set_length(new_length);
12110
12111  if (new_length == 0) return heap->isolate()->factory()->empty_string();
12112  return string;
12113}
12114
12115
12116uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
12117  // For array indexes mix the length into the hash as an array index could
12118  // be zero.
12119  DCHECK(length > 0);
12120  DCHECK(length <= String::kMaxArrayIndexSize);
12121  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
12122         (1 << String::kArrayIndexValueBits));
12123
12124  value <<= String::ArrayIndexValueBits::kShift;
12125  value |= length << String::ArrayIndexLengthBits::kShift;
12126
12127  DCHECK((value & String::kIsNotArrayIndexMask) == 0);
12128  DCHECK((length > String::kMaxCachedArrayIndexLength) ||
12129         (value & String::kContainsCachedArrayIndexMask) == 0);
12130  return value;
12131}
12132
12133
12134uint32_t StringHasher::GetHashField() {
12135  if (length_ <= String::kMaxHashCalcLength) {
12136    if (is_array_index_) {
12137      return MakeArrayIndexHash(array_index_, length_);
12138    }
12139    return (GetHashCore(raw_running_hash_) << String::kHashShift) |
12140           String::kIsNotArrayIndexMask;
12141  } else {
12142    return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
12143  }
12144}
12145
12146
12147uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
12148                                       uint32_t seed,
12149                                       int* utf16_length_out) {
12150  int vector_length = chars.length();
12151  // Handle some edge cases
12152  if (vector_length <= 1) {
12153    DCHECK(vector_length == 0 ||
12154           static_cast<uint8_t>(chars.start()[0]) <=
12155               unibrow::Utf8::kMaxOneByteChar);
12156    *utf16_length_out = vector_length;
12157    return HashSequentialString(chars.start(), vector_length, seed);
12158  }
12159  // Start with a fake length which won't affect computation.
12160  // It will be updated later.
12161  StringHasher hasher(String::kMaxArrayIndexSize, seed);
12162  size_t remaining = static_cast<size_t>(vector_length);
12163  const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
12164  int utf16_length = 0;
12165  bool is_index = true;
12166  DCHECK(hasher.is_array_index_);
12167  while (remaining > 0) {
12168    size_t consumed = 0;
12169    uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
12170    DCHECK(consumed > 0 && consumed <= remaining);
12171    stream += consumed;
12172    remaining -= consumed;
12173    bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
12174    utf16_length += is_two_characters ? 2 : 1;
12175    // No need to keep hashing. But we do need to calculate utf16_length.
12176    if (utf16_length > String::kMaxHashCalcLength) continue;
12177    if (is_two_characters) {
12178      uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
12179      uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
12180      hasher.AddCharacter(c1);
12181      hasher.AddCharacter(c2);
12182      if (is_index) is_index = hasher.UpdateIndex(c1);
12183      if (is_index) is_index = hasher.UpdateIndex(c2);
12184    } else {
12185      hasher.AddCharacter(c);
12186      if (is_index) is_index = hasher.UpdateIndex(c);
12187    }
12188  }
12189  *utf16_length_out = static_cast<int>(utf16_length);
12190  // Must set length here so that hash computation is correct.
12191  hasher.length_ = utf16_length;
12192  return hasher.GetHashField();
12193}
12194
12195
12196void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
12197  // Run small ConsStrings through ConsStringIterator.
12198  if (cons_string->length() < 64) {
12199    ConsStringIterator iter(cons_string);
12200    int offset;
12201    String* string;
12202    while (nullptr != (string = iter.Next(&offset))) {
12203      DCHECK_EQ(0, offset);
12204      String::VisitFlat(this, string, 0);
12205    }
12206    return;
12207  }
12208  // Slow case.
12209  const int max_length = String::kMaxHashCalcLength;
12210  int length = std::min(cons_string->length(), max_length);
12211  if (cons_string->HasOnlyOneByteChars()) {
12212    uint8_t* buffer = new uint8_t[length];
12213    String::WriteToFlat(cons_string, buffer, 0, length);
12214    AddCharacters(buffer, length);
12215    delete[] buffer;
12216  } else {
12217    uint16_t* buffer = new uint16_t[length];
12218    String::WriteToFlat(cons_string, buffer, 0, length);
12219    AddCharacters(buffer, length);
12220    delete[] buffer;
12221  }
12222}
12223
12224
12225void String::PrintOn(FILE* file) {
12226  int length = this->length();
12227  for (int i = 0; i < length; i++) {
12228    PrintF(file, "%c", Get(i));
12229  }
12230}
12231
12232
12233int Map::Hash() {
12234  // For performance reasons we only hash the 3 most variable fields of a map:
12235  // constructor, prototype and bit_field2. For predictability reasons we
12236  // use objects' offsets in respective pages for hashing instead of raw
12237  // addresses.
12238
12239  // Shift away the tag.
12240  int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
12241
12242  // XOR-ing the prototype and constructor directly yields too many zero bits
12243  // when the two pointers are close (which is fairly common).
12244  // To avoid this we shift the prototype bits relatively to the constructor.
12245  hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
12246
12247  return hash ^ (hash >> 16) ^ bit_field2();
12248}
12249
12250
12251namespace {
12252
12253bool CheckEquivalent(Map* first, Map* second) {
12254  return first->GetConstructor() == second->GetConstructor() &&
12255         first->prototype() == second->prototype() &&
12256         first->instance_type() == second->instance_type() &&
12257         first->bit_field() == second->bit_field() &&
12258         first->is_extensible() == second->is_extensible() &&
12259         first->is_strong() == second->is_strong() &&
12260         first->is_hidden_prototype() == second->is_hidden_prototype();
12261}
12262
12263}  // namespace
12264
12265
12266bool Map::EquivalentToForTransition(Map* other) {
12267  if (!CheckEquivalent(this, other)) return false;
12268  if (instance_type() == JS_FUNCTION_TYPE) {
12269    // JSFunctions require more checks to ensure that sloppy function is
12270    // not equvalent to strict function.
12271    int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
12272    return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
12273                                               nof);
12274  }
12275  return true;
12276}
12277
12278
12279bool Map::EquivalentToForNormalization(Map* other,
12280                                       PropertyNormalizationMode mode) {
12281  int properties =
12282      mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
12283  return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
12284         GetInObjectProperties() == properties;
12285}
12286
12287
12288bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
12289  DisallowHeapAllocation no_gc;
12290  if (shared() == candidate) return true;
12291  if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
12292  DeoptimizationInputData* const data =
12293      DeoptimizationInputData::cast(code()->deoptimization_data());
12294  if (data->length() == 0) return false;
12295  FixedArray* const literals = data->LiteralArray();
12296  int const inlined_count = data->InlinedFunctionCount()->value();
12297  for (int i = 0; i < inlined_count; ++i) {
12298    if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
12299      return true;
12300    }
12301  }
12302  return false;
12303}
12304
12305
12306void JSFunction::MarkForOptimization() {
12307  Isolate* isolate = GetIsolate();
12308  // Do not optimize if function contains break points.
12309  if (shared()->HasDebugInfo()) return;
12310  DCHECK(!IsOptimized());
12311  DCHECK(shared()->allows_lazy_compilation() ||
12312         !shared()->optimization_disabled());
12313  DCHECK(!shared()->HasDebugInfo());
12314  set_code_no_write_barrier(
12315      isolate->builtins()->builtin(Builtins::kCompileOptimized));
12316  // No write barrier required, since the builtin is part of the root set.
12317}
12318
12319
12320void JSFunction::AttemptConcurrentOptimization() {
12321  Isolate* isolate = GetIsolate();
12322  if (!isolate->concurrent_recompilation_enabled() ||
12323      isolate->bootstrapper()->IsActive()) {
12324    MarkForOptimization();
12325    return;
12326  }
12327  if (isolate->concurrent_osr_enabled() &&
12328      isolate->optimizing_compile_dispatcher()->IsQueuedForOSR(this)) {
12329    // Do not attempt regular recompilation if we already queued this for OSR.
12330    // TODO(yangguo): This is necessary so that we don't install optimized
12331    // code on a function that is already optimized, since OSR and regular
12332    // recompilation race.  This goes away as soon as OSR becomes one-shot.
12333    return;
12334  }
12335  DCHECK(!IsInOptimizationQueue());
12336  DCHECK(!IsOptimized());
12337  DCHECK(shared()->allows_lazy_compilation() ||
12338         !shared()->optimization_disabled());
12339  DCHECK(isolate->concurrent_recompilation_enabled());
12340  if (FLAG_trace_concurrent_recompilation) {
12341    PrintF("  ** Marking ");
12342    ShortPrint();
12343    PrintF(" for concurrent recompilation.\n");
12344  }
12345  set_code_no_write_barrier(
12346      isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
12347  // No write barrier required, since the builtin is part of the root set.
12348}
12349
12350
12351void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
12352    Handle<SharedFunctionInfo> shared, Handle<Code> code) {
12353  Isolate* isolate = shared->GetIsolate();
12354  if (isolate->serializer_enabled()) return;
12355  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
12356  // Empty code maps are unsupported.
12357  if (!shared->OptimizedCodeMapIsCleared()) {
12358    Handle<WeakCell> cell = isolate->factory()->NewWeakCell(code);
12359    // A collection may have occured and cleared the optimized code map in the
12360    // allocation above.
12361    if (!shared->OptimizedCodeMapIsCleared()) {
12362      shared->optimized_code_map()->set(kSharedCodeIndex, *cell);
12363    }
12364  }
12365}
12366
12367
12368void SharedFunctionInfo::AddToOptimizedCodeMapInternal(
12369    Handle<SharedFunctionInfo> shared, Handle<Context> native_context,
12370    Handle<HeapObject> code, Handle<LiteralsArray> literals,
12371    BailoutId osr_ast_id) {
12372  Isolate* isolate = shared->GetIsolate();
12373  if (isolate->serializer_enabled()) return;
12374  DCHECK(*code == isolate->heap()->undefined_value() ||
12375         !shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code);
12376  DCHECK(*code == isolate->heap()->undefined_value() ||
12377         Code::cast(*code)->kind() == Code::OPTIMIZED_FUNCTION);
12378  DCHECK(native_context->IsNativeContext());
12379  STATIC_ASSERT(kEntryLength == 4);
12380  Handle<FixedArray> new_code_map;
12381  int entry;
12382
12383  if (shared->OptimizedCodeMapIsCleared()) {
12384    new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED);
12385    new_code_map->set(kSharedCodeIndex, *isolate->factory()->empty_weak_cell(),
12386                      SKIP_WRITE_BARRIER);
12387    entry = kEntriesStart;
12388  } else {
12389    Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate);
12390    entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id);
12391    if (entry > kSharedCodeIndex) {
12392      // Found an existing context-specific entry. If the user provided valid
12393      // code, it must not contain any code.
12394      DCHECK(code->IsUndefined() ||
12395             WeakCell::cast(old_code_map->get(entry + kCachedCodeOffset))
12396                 ->cleared());
12397
12398      // Just set the code and literals to the entry.
12399      if (!code->IsUndefined()) {
12400        Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code);
12401        old_code_map->set(entry + kCachedCodeOffset, *code_cell);
12402      }
12403      Handle<WeakCell> literals_cell =
12404          isolate->factory()->NewWeakCell(literals);
12405      old_code_map->set(entry + kLiteralsOffset, *literals_cell);
12406      return;
12407    }
12408
12409    // Can we reuse an entry?
12410    DCHECK(entry < kEntriesStart);
12411    int length = old_code_map->length();
12412    for (int i = kEntriesStart; i < length; i += kEntryLength) {
12413      if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) {
12414        new_code_map = old_code_map;
12415        entry = i;
12416        break;
12417      }
12418    }
12419
12420    if (entry < kEntriesStart) {
12421      // Copy old optimized code map and append one new entry.
12422      new_code_map = isolate->factory()->CopyFixedArrayAndGrow(
12423          old_code_map, kEntryLength, TENURED);
12424      // TODO(mstarzinger): Temporary workaround. The allocation above might
12425      // have flushed the optimized code map and the copy we created is full of
12426      // holes. For now we just give up on adding the entry and pretend it got
12427      // flushed.
12428      if (shared->OptimizedCodeMapIsCleared()) return;
12429      entry = old_code_map->length();
12430    }
12431  }
12432
12433  Handle<WeakCell> code_cell = code->IsUndefined()
12434                                   ? isolate->factory()->empty_weak_cell()
12435                                   : isolate->factory()->NewWeakCell(code);
12436  Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
12437  WeakCell* context_cell = native_context->self_weak_cell();
12438
12439  new_code_map->set(entry + kContextOffset, context_cell);
12440  new_code_map->set(entry + kCachedCodeOffset, *code_cell);
12441  new_code_map->set(entry + kLiteralsOffset, *literals_cell);
12442  new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt()));
12443
12444#ifdef DEBUG
12445  for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
12446    WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset));
12447    DCHECK(cell->cleared() || cell->value()->IsNativeContext());
12448    cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset));
12449    DCHECK(cell->cleared() ||
12450           (cell->value()->IsCode() &&
12451            Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
12452    cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset));
12453    DCHECK(cell->cleared() || cell->value()->IsFixedArray());
12454    DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
12455  }
12456#endif
12457
12458  FixedArray* old_code_map = shared->optimized_code_map();
12459  if (old_code_map != *new_code_map) {
12460    shared->set_optimized_code_map(*new_code_map);
12461  }
12462}
12463
12464
12465void SharedFunctionInfo::ClearOptimizedCodeMap() {
12466  FixedArray* cleared_map = GetHeap()->cleared_optimized_code_map();
12467  set_optimized_code_map(cleared_map, SKIP_WRITE_BARRIER);
12468}
12469
12470
12471void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
12472                                                   const char* reason) {
12473  DisallowHeapAllocation no_gc;
12474  if (OptimizedCodeMapIsCleared()) return;
12475
12476  Heap* heap = GetHeap();
12477  FixedArray* code_map = optimized_code_map();
12478  int dst = kEntriesStart;
12479  int length = code_map->length();
12480  for (int src = kEntriesStart; src < length; src += kEntryLength) {
12481    DCHECK(WeakCell::cast(code_map->get(src))->cleared() ||
12482           WeakCell::cast(code_map->get(src))->value()->IsNativeContext());
12483    if (WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() ==
12484        optimized_code) {
12485      BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
12486      if (FLAG_trace_opt) {
12487        PrintF("[evicting entry from optimizing code map (%s) for ", reason);
12488        ShortPrint();
12489        if (osr.IsNone()) {
12490          PrintF("]\n");
12491        } else {
12492          PrintF(" (osr ast id %d)]\n", osr.ToInt());
12493        }
12494      }
12495      if (!osr.IsNone()) {
12496        // Evict the src entry by not copying it to the dst entry.
12497        continue;
12498      }
12499      // In case of non-OSR entry just clear the code in order to proceed
12500      // sharing literals.
12501      code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(),
12502                    SKIP_WRITE_BARRIER);
12503    }
12504
12505    // Keep the src entry by copying it to the dst entry.
12506    if (dst != src) {
12507      code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset));
12508      code_map->set(dst + kCachedCodeOffset,
12509                    code_map->get(src + kCachedCodeOffset));
12510      code_map->set(dst + kLiteralsOffset,
12511                    code_map->get(src + kLiteralsOffset));
12512      code_map->set(dst + kOsrAstIdOffset,
12513                    code_map->get(src + kOsrAstIdOffset));
12514    }
12515    dst += kEntryLength;
12516  }
12517  if (WeakCell::cast(code_map->get(kSharedCodeIndex))->value() ==
12518      optimized_code) {
12519    // Evict context-independent code as well.
12520    code_map->set(kSharedCodeIndex, heap->empty_weak_cell(),
12521                  SKIP_WRITE_BARRIER);
12522    if (FLAG_trace_opt) {
12523      PrintF("[evicting entry from optimizing code map (%s) for ", reason);
12524      ShortPrint();
12525      PrintF(" (context-independent code)]\n");
12526    }
12527  }
12528  if (dst != length) {
12529    // Always trim even when array is cleared because of heap verifier.
12530    heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
12531                                                           length - dst);
12532    if (code_map->length() == kEntriesStart &&
12533        WeakCell::cast(code_map->get(kSharedCodeIndex))->cleared()) {
12534      ClearOptimizedCodeMap();
12535    }
12536  }
12537}
12538
12539
12540void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
12541  FixedArray* code_map = optimized_code_map();
12542  DCHECK(shrink_by % kEntryLength == 0);
12543  DCHECK(shrink_by <= code_map->length() - kEntriesStart);
12544  // Always trim even when array is cleared because of heap verifier.
12545  GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
12546                                                              shrink_by);
12547  if (code_map->length() == kEntriesStart &&
12548      WeakCell::cast(code_map->get(kSharedCodeIndex))->cleared()) {
12549    ClearOptimizedCodeMap();
12550  }
12551}
12552
12553
12554static void GetMinInobjectSlack(Map* map, void* data) {
12555  int slack = map->unused_property_fields();
12556  if (*reinterpret_cast<int*>(data) > slack) {
12557    *reinterpret_cast<int*>(data) = slack;
12558  }
12559}
12560
12561
12562static void ShrinkInstanceSize(Map* map, void* data) {
12563  int slack = *reinterpret_cast<int*>(data);
12564  map->SetInObjectProperties(map->GetInObjectProperties() - slack);
12565  map->set_unused_property_fields(map->unused_property_fields() - slack);
12566  map->set_instance_size(map->instance_size() - slack * kPointerSize);
12567
12568  // Visitor id might depend on the instance size, recalculate it.
12569  map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map));
12570}
12571
12572
12573void Map::CompleteInobjectSlackTracking() {
12574  // Has to be an initial map.
12575  DCHECK(GetBackPointer()->IsUndefined());
12576
12577  set_construction_counter(kNoSlackTracking);
12578
12579  int slack = unused_property_fields();
12580  TransitionArray::TraverseTransitionTree(this, &GetMinInobjectSlack, &slack);
12581  if (slack != 0) {
12582    // Resize the initial map and all maps in its transition tree.
12583    TransitionArray::TraverseTransitionTree(this, &ShrinkInstanceSize, &slack);
12584  }
12585}
12586
12587
12588static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
12589  DisallowHeapAllocation no_gc;
12590  if (!object->HasFastProperties()) return false;
12591  Map* map = object->map();
12592  if (map->is_prototype_map()) return false;
12593  DescriptorArray* descriptors = map->instance_descriptors();
12594  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
12595    PropertyDetails details = descriptors->GetDetails(i);
12596    if (details.location() == kDescriptor) continue;
12597    if (details.representation().IsHeapObject() ||
12598        details.representation().IsTagged()) {
12599      FieldIndex index = FieldIndex::ForDescriptor(map, i);
12600      if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
12601    }
12602  }
12603  return false;
12604}
12605
12606
12607// static
12608void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
12609                                   PrototypeOptimizationMode mode) {
12610  if (object->IsJSGlobalObject()) return;
12611  if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
12612    // First normalize to ensure all JSFunctions are DATA_CONSTANT.
12613    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
12614                                  "NormalizeAsPrototype");
12615  }
12616  Handle<Map> previous_map(object->map());
12617  if (!object->HasFastProperties()) {
12618    JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
12619  }
12620  if (!object->map()->is_prototype_map()) {
12621    if (object->map() == *previous_map) {
12622      Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
12623      JSObject::MigrateToMap(object, new_map);
12624    }
12625    object->map()->set_is_prototype_map(true);
12626
12627    // Replace the pointer to the exact constructor with the Object function
12628    // from the same context if undetectable from JS. This is to avoid keeping
12629    // memory alive unnecessarily.
12630    Object* maybe_constructor = object->map()->GetConstructor();
12631    if (maybe_constructor->IsJSFunction()) {
12632      JSFunction* constructor = JSFunction::cast(maybe_constructor);
12633      Isolate* isolate = object->GetIsolate();
12634      if (!constructor->shared()->IsApiFunction() &&
12635          object->class_name() == isolate->heap()->Object_string()) {
12636        Context* context = constructor->context()->native_context();
12637        JSFunction* object_function = context->object_function();
12638        object->map()->SetConstructor(object_function);
12639      }
12640    }
12641  }
12642}
12643
12644
12645// static
12646void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
12647  if (!object->map()->is_prototype_map()) return;
12648  OptimizeAsPrototype(object, FAST_PROTOTYPE);
12649}
12650
12651
12652// static
12653void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12654  DCHECK(FLAG_track_prototype_users);
12655  // Contract: In line with InvalidatePrototypeChains()'s requirements,
12656  // leaf maps don't need to register as users, only prototypes do.
12657  DCHECK(user->is_prototype_map());
12658
12659  Handle<Map> current_user = user;
12660  Handle<PrototypeInfo> current_user_info =
12661      Map::GetOrCreatePrototypeInfo(user, isolate);
12662  for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
12663    // Walk up the prototype chain as far as links haven't been registered yet.
12664    if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
12665      break;
12666    }
12667    Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
12668    // Proxies on the prototype chain are not supported. They make it
12669    // impossible to make any assumptions about the prototype chain anyway.
12670    if (maybe_proto->IsJSProxy()) return;
12671    Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
12672    Handle<PrototypeInfo> proto_info =
12673        Map::GetOrCreatePrototypeInfo(proto, isolate);
12674    Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
12675    int slot = 0;
12676    Handle<WeakFixedArray> new_array =
12677        WeakFixedArray::Add(maybe_registry, current_user, &slot);
12678    current_user_info->set_registry_slot(slot);
12679    if (!maybe_registry.is_identical_to(new_array)) {
12680      proto_info->set_prototype_users(*new_array);
12681    }
12682    if (FLAG_trace_prototype_users) {
12683      PrintF("Registering %p as a user of prototype %p (map=%p).\n",
12684             reinterpret_cast<void*>(*current_user),
12685             reinterpret_cast<void*>(*proto),
12686             reinterpret_cast<void*>(proto->map()));
12687    }
12688
12689    current_user = handle(proto->map(), isolate);
12690    current_user_info = proto_info;
12691  }
12692}
12693
12694
12695// Can be called regardless of whether |user| was actually registered with
12696// |prototype|. Returns true when there was a registration.
12697// static
12698bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12699  DCHECK(user->is_prototype_map());
12700  // If it doesn't have a PrototypeInfo, it was never registered.
12701  if (!user->prototype_info()->IsPrototypeInfo()) return false;
12702  // If it had no prototype before, see if it had users that might expect
12703  // registration.
12704  if (!user->prototype()->IsJSObject()) {
12705    Object* users =
12706        PrototypeInfo::cast(user->prototype_info())->prototype_users();
12707    return users->IsWeakFixedArray();
12708  }
12709  Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
12710  Handle<PrototypeInfo> user_info =
12711      Map::GetOrCreatePrototypeInfo(user, isolate);
12712  int slot = user_info->registry_slot();
12713  if (slot == PrototypeInfo::UNREGISTERED) return false;
12714  DCHECK(prototype->map()->is_prototype_map());
12715  Object* maybe_proto_info = prototype->map()->prototype_info();
12716  // User knows its registry slot, prototype info and user registry must exist.
12717  DCHECK(maybe_proto_info->IsPrototypeInfo());
12718  Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
12719                                   isolate);
12720  Object* maybe_registry = proto_info->prototype_users();
12721  DCHECK(maybe_registry->IsWeakFixedArray());
12722  DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user);
12723  WeakFixedArray::cast(maybe_registry)->Clear(slot);
12724  if (FLAG_trace_prototype_users) {
12725    PrintF("Unregistering %p as a user of prototype %p.\n",
12726           reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
12727  }
12728  return true;
12729}
12730
12731
12732static void InvalidatePrototypeChainsInternal(Map* map) {
12733  if (!map->is_prototype_map()) return;
12734  if (FLAG_trace_prototype_users) {
12735    PrintF("Invalidating prototype map %p 's cell\n",
12736           reinterpret_cast<void*>(map));
12737  }
12738  Object* maybe_proto_info = map->prototype_info();
12739  if (!maybe_proto_info->IsPrototypeInfo()) return;
12740  PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
12741  Object* maybe_cell = proto_info->validity_cell();
12742  if (maybe_cell->IsCell()) {
12743    // Just set the value; the cell will be replaced lazily.
12744    Cell* cell = Cell::cast(maybe_cell);
12745    cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
12746  }
12747
12748  WeakFixedArray::Iterator iterator(proto_info->prototype_users());
12749  // For now, only maps register themselves as users.
12750  Map* user;
12751  while ((user = iterator.Next<Map>())) {
12752    // Walk the prototype chain (backwards, towards leaf objects) if necessary.
12753    InvalidatePrototypeChainsInternal(user);
12754  }
12755}
12756
12757
12758// static
12759void JSObject::InvalidatePrototypeChains(Map* map) {
12760  if (!FLAG_eliminate_prototype_chain_checks) return;
12761  DisallowHeapAllocation no_gc;
12762  InvalidatePrototypeChainsInternal(map);
12763}
12764
12765
12766// static
12767Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
12768                                                    Isolate* isolate) {
12769  Object* maybe_proto_info = prototype->map()->prototype_info();
12770  if (maybe_proto_info->IsPrototypeInfo()) {
12771    return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12772  }
12773  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12774  prototype->map()->set_prototype_info(*proto_info);
12775  return proto_info;
12776}
12777
12778
12779// static
12780Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
12781                                                    Isolate* isolate) {
12782  Object* maybe_proto_info = prototype_map->prototype_info();
12783  if (maybe_proto_info->IsPrototypeInfo()) {
12784    return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12785  }
12786  Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12787  prototype_map->set_prototype_info(*proto_info);
12788  return proto_info;
12789}
12790
12791
12792// static
12793Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
12794                                                        Isolate* isolate) {
12795  Handle<Object> maybe_prototype(map->prototype(), isolate);
12796  if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
12797  Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
12798  // Ensure the prototype is registered with its own prototypes so its cell
12799  // will be invalidated when necessary.
12800  JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
12801                                      isolate);
12802  Handle<PrototypeInfo> proto_info =
12803      GetOrCreatePrototypeInfo(prototype, isolate);
12804  Object* maybe_cell = proto_info->validity_cell();
12805  // Return existing cell if it's still valid.
12806  if (maybe_cell->IsCell()) {
12807    Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
12808    if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
12809      return cell;
12810    }
12811  }
12812  // Otherwise create a new cell.
12813  Handle<Cell> cell = isolate->factory()->NewCell(
12814      handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
12815  proto_info->set_validity_cell(*cell);
12816  return cell;
12817}
12818
12819
12820// static
12821void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
12822                       PrototypeOptimizationMode proto_mode) {
12823  if (prototype->IsJSObject()) {
12824    Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
12825    JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
12826  }
12827  WriteBarrierMode wb_mode =
12828      prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
12829  map->set_prototype(*prototype, wb_mode);
12830}
12831
12832
12833Handle<Object> CacheInitialJSArrayMaps(
12834    Handle<Context> native_context, Handle<Map> initial_map) {
12835  // Replace all of the cached initial array maps in the native context with
12836  // the appropriate transitioned elements kind maps.
12837  Strength strength =
12838      initial_map->is_strong() ? Strength::STRONG : Strength::WEAK;
12839  Handle<Map> current_map = initial_map;
12840  ElementsKind kind = current_map->elements_kind();
12841  DCHECK_EQ(GetInitialFastElementsKind(), kind);
12842  native_context->set(Context::ArrayMapIndex(kind, strength), *current_map);
12843  for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
12844       i < kFastElementsKindCount; ++i) {
12845    Handle<Map> new_map;
12846    ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
12847    if (Map* maybe_elements_transition = current_map->ElementsTransitionMap()) {
12848      new_map = handle(maybe_elements_transition);
12849    } else {
12850      new_map = Map::CopyAsElementsKind(
12851          current_map, next_kind, INSERT_TRANSITION);
12852    }
12853    DCHECK_EQ(next_kind, new_map->elements_kind());
12854    native_context->set(Context::ArrayMapIndex(next_kind, strength), *new_map);
12855    current_map = new_map;
12856  }
12857  return initial_map;
12858}
12859
12860
12861void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
12862                                      Handle<Object> value) {
12863  Isolate* isolate = function->GetIsolate();
12864
12865  DCHECK(value->IsJSReceiver());
12866
12867  // Now some logic for the maps of the objects that are created by using this
12868  // function as a constructor.
12869  if (function->has_initial_map()) {
12870    // If the function has allocated the initial map replace it with a
12871    // copy containing the new prototype.  Also complete any in-object
12872    // slack tracking that is in progress at this point because it is
12873    // still tracking the old copy.
12874    function->CompleteInobjectSlackTrackingIfActive();
12875
12876    Handle<Map> initial_map(function->initial_map(), isolate);
12877
12878    if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
12879        initial_map->instance_type() == JS_OBJECT_TYPE) {
12880      // Put the value in the initial map field until an initial map is needed.
12881      // At that point, a new initial map is created and the prototype is put
12882      // into the initial map where it belongs.
12883      function->set_prototype_or_initial_map(*value);
12884    } else {
12885      Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
12886      if (function->map()->is_strong()) {
12887        new_map->set_is_strong();
12888      }
12889      JSFunction::SetInitialMap(function, new_map, value);
12890
12891      // If the function is used as the global Array function, cache the
12892      // updated initial maps (and transitioned versions) in the native context.
12893      Handle<Context> native_context(function->context()->native_context(),
12894                                     isolate);
12895      Handle<Object> array_function(
12896          native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
12897      if (array_function->IsJSFunction() &&
12898          *function == JSFunction::cast(*array_function)) {
12899        CacheInitialJSArrayMaps(native_context, new_map);
12900        Handle<Map> new_strong_map = Map::Copy(new_map, "SetInstancePrototype");
12901        new_strong_map->set_is_strong();
12902        CacheInitialJSArrayMaps(native_context, new_strong_map);
12903      }
12904    }
12905
12906    // Deoptimize all code that embeds the previous initial map.
12907    initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
12908        isolate, DependentCode::kInitialMapChangedGroup);
12909  } else {
12910    // Put the value in the initial map field until an initial map is
12911    // needed.  At that point, a new initial map is created and the
12912    // prototype is put into the initial map where it belongs.
12913    function->set_prototype_or_initial_map(*value);
12914    if (value->IsJSObject()) {
12915      // Optimize as prototype to detach it from its transition tree.
12916      JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
12917                                    FAST_PROTOTYPE);
12918    }
12919  }
12920  isolate->heap()->ClearInstanceofCache();
12921}
12922
12923
12924void JSFunction::SetPrototype(Handle<JSFunction> function,
12925                              Handle<Object> value) {
12926  DCHECK(function->IsConstructor());
12927  Handle<Object> construct_prototype = value;
12928
12929  // If the value is not a JSReceiver, store the value in the map's
12930  // constructor field so it can be accessed.  Also, set the prototype
12931  // used for constructing objects to the original object prototype.
12932  // See ECMA-262 13.2.2.
12933  if (!value->IsJSReceiver()) {
12934    // Copy the map so this does not affect unrelated functions.
12935    // Remove map transitions because they point to maps with a
12936    // different prototype.
12937    Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
12938
12939    JSObject::MigrateToMap(function, new_map);
12940    new_map->SetConstructor(*value);
12941    new_map->set_non_instance_prototype(true);
12942    Isolate* isolate = new_map->GetIsolate();
12943    construct_prototype = handle(
12944        function->context()->native_context()->initial_object_prototype(),
12945        isolate);
12946  } else {
12947    function->map()->set_non_instance_prototype(false);
12948  }
12949
12950  return SetInstancePrototype(function, construct_prototype);
12951}
12952
12953
12954bool JSFunction::RemovePrototype() {
12955  Context* native_context = context()->native_context();
12956  Map* no_prototype_map =
12957      is_strict(shared()->language_mode())
12958          ? native_context->strict_function_without_prototype_map()
12959          : native_context->sloppy_function_without_prototype_map();
12960
12961  if (map() == no_prototype_map) return true;
12962
12963#ifdef DEBUG
12964  if (map() != (is_strict(shared()->language_mode())
12965                    ? native_context->strict_function_map()
12966                    : native_context->sloppy_function_map())) {
12967    return false;
12968  }
12969#endif
12970
12971  set_map(no_prototype_map);
12972  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
12973  return true;
12974}
12975
12976
12977void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
12978                               Handle<Object> prototype) {
12979  if (map->prototype() != *prototype) {
12980    Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
12981  }
12982  function->set_prototype_or_initial_map(*map);
12983  map->SetConstructor(*function);
12984#if TRACE_MAPS
12985  if (FLAG_trace_maps) {
12986    PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
12987           reinterpret_cast<void*>(*map), function->shared()->unique_id(),
12988           function->shared()->DebugName()->ToCString().get());
12989  }
12990#endif
12991}
12992
12993
12994#ifdef DEBUG
12995namespace {
12996
12997bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
12998  switch (instance_type) {
12999    case JS_OBJECT_TYPE:
13000    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
13001    case JS_GENERATOR_OBJECT_TYPE:
13002    case JS_MODULE_TYPE:
13003    case JS_VALUE_TYPE:
13004    case JS_DATE_TYPE:
13005    case JS_ARRAY_TYPE:
13006    case JS_MESSAGE_OBJECT_TYPE:
13007    case JS_ARRAY_BUFFER_TYPE:
13008    case JS_TYPED_ARRAY_TYPE:
13009    case JS_DATA_VIEW_TYPE:
13010    case JS_SET_TYPE:
13011    case JS_MAP_TYPE:
13012    case JS_SET_ITERATOR_TYPE:
13013    case JS_MAP_ITERATOR_TYPE:
13014    case JS_ITERATOR_RESULT_TYPE:
13015    case JS_WEAK_MAP_TYPE:
13016    case JS_WEAK_SET_TYPE:
13017    case JS_PROMISE_TYPE:
13018    case JS_REGEXP_TYPE:
13019    case JS_FUNCTION_TYPE:
13020      return true;
13021
13022    case JS_BOUND_FUNCTION_TYPE:
13023    case JS_PROXY_TYPE:
13024    case JS_GLOBAL_PROXY_TYPE:
13025    case JS_GLOBAL_OBJECT_TYPE:
13026    case FIXED_ARRAY_TYPE:
13027    case FIXED_DOUBLE_ARRAY_TYPE:
13028    case ODDBALL_TYPE:
13029    case FOREIGN_TYPE:
13030    case MAP_TYPE:
13031    case CODE_TYPE:
13032    case CELL_TYPE:
13033    case PROPERTY_CELL_TYPE:
13034    case WEAK_CELL_TYPE:
13035    case SYMBOL_TYPE:
13036    case BYTECODE_ARRAY_TYPE:
13037    case HEAP_NUMBER_TYPE:
13038    case MUTABLE_HEAP_NUMBER_TYPE:
13039    case SIMD128_VALUE_TYPE:
13040    case FILLER_TYPE:
13041    case BYTE_ARRAY_TYPE:
13042    case FREE_SPACE_TYPE:
13043    case SHARED_FUNCTION_INFO_TYPE:
13044
13045#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
13046  case FIXED_##TYPE##_ARRAY_TYPE:
13047#undef TYPED_ARRAY_CASE
13048
13049#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
13050      STRUCT_LIST(MAKE_STRUCT_CASE)
13051#undef MAKE_STRUCT_CASE
13052      // We must not end up here for these instance types at all.
13053      UNREACHABLE();
13054    // Fall through.
13055    default:
13056      return false;
13057  }
13058}
13059
13060}  // namespace
13061#endif
13062
13063
13064void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
13065  DCHECK(function->IsConstructor() || function->shared()->is_generator());
13066  if (function->has_initial_map()) return;
13067  Isolate* isolate = function->GetIsolate();
13068
13069  // The constructor should be compiled for the optimization hints to be
13070  // available.
13071  Compiler::Compile(function, CLEAR_EXCEPTION);
13072
13073  // First create a new map with the size and number of in-object properties
13074  // suggested by the function.
13075  InstanceType instance_type;
13076  if (function->shared()->is_generator()) {
13077    instance_type = JS_GENERATOR_OBJECT_TYPE;
13078  } else {
13079    instance_type = JS_OBJECT_TYPE;
13080  }
13081  int instance_size;
13082  int in_object_properties;
13083  function->CalculateInstanceSize(instance_type, 0, &instance_size,
13084                                  &in_object_properties);
13085
13086  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
13087  if (function->map()->is_strong()) {
13088    map->set_is_strong();
13089  }
13090
13091  // Fetch or allocate prototype.
13092  Handle<Object> prototype;
13093  if (function->has_instance_prototype()) {
13094    prototype = handle(function->instance_prototype(), isolate);
13095  } else {
13096    prototype = isolate->factory()->NewFunctionPrototype(function);
13097  }
13098  map->SetInObjectProperties(in_object_properties);
13099  map->set_unused_property_fields(in_object_properties);
13100  DCHECK(map->has_fast_object_elements());
13101
13102  // Finally link initial map and constructor function.
13103  DCHECK(prototype->IsJSReceiver());
13104  JSFunction::SetInitialMap(function, map, prototype);
13105  map->StartInobjectSlackTracking();
13106}
13107
13108
13109// static
13110MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
13111                                           Handle<JSFunction> constructor,
13112                                           Handle<JSReceiver> new_target) {
13113  EnsureHasInitialMap(constructor);
13114
13115  Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
13116  if (*new_target == *constructor) return constructor_initial_map;
13117
13118  // Fast case, new.target is a subclass of constructor. The map is cacheable
13119  // (and may already have been cached). new.target.prototype is guaranteed to
13120  // be a JSReceiver.
13121  if (new_target->IsJSFunction()) {
13122    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
13123
13124    // Check that |function|'s initial map still in sync with the |constructor|,
13125    // otherwise we must create a new initial map for |function|.
13126    if (function->has_initial_map() &&
13127        function->initial_map()->GetConstructor() == *constructor) {
13128      return handle(function->initial_map(), isolate);
13129    }
13130
13131    // Create a new map with the size and number of in-object properties
13132    // suggested by |function|.
13133
13134    // Link initial map and constructor function if the new.target is actually a
13135    // subclass constructor.
13136    if (IsSubclassConstructor(function->shared()->kind())) {
13137      Handle<Object> prototype(function->instance_prototype(), isolate);
13138      InstanceType instance_type = constructor_initial_map->instance_type();
13139      DCHECK(CanSubclassHaveInobjectProperties(instance_type));
13140      int internal_fields =
13141          JSObject::GetInternalFieldCount(*constructor_initial_map);
13142      int pre_allocated = constructor_initial_map->GetInObjectProperties() -
13143                          constructor_initial_map->unused_property_fields();
13144      int instance_size;
13145      int in_object_properties;
13146      function->CalculateInstanceSizeForDerivedClass(
13147          instance_type, internal_fields, &instance_size,
13148          &in_object_properties);
13149
13150      int unused_property_fields = in_object_properties - pre_allocated;
13151      Handle<Map> map =
13152          Map::CopyInitialMap(constructor_initial_map, instance_size,
13153                              in_object_properties, unused_property_fields);
13154      map->set_new_target_is_base(false);
13155
13156      JSFunction::SetInitialMap(function, map, prototype);
13157      map->SetConstructor(*constructor);
13158      map->StartInobjectSlackTracking();
13159      return map;
13160    }
13161  }
13162
13163  // Slow path, new.target is either a proxy or can't cache the map.
13164  // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
13165  // fall back to the intrinsicDefaultProto.
13166  Handle<Object> prototype;
13167  if (new_target->IsJSFunction()) {
13168    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
13169    // Make sure the new.target.prototype is cached.
13170    EnsureHasInitialMap(function);
13171    prototype = handle(function->prototype(), isolate);
13172  } else {
13173    Handle<String> prototype_string = isolate->factory()->prototype_string();
13174    ASSIGN_RETURN_ON_EXCEPTION(
13175        isolate, prototype,
13176        JSReceiver::GetProperty(new_target, prototype_string), Map);
13177    // The above prototype lookup might change the constructor and its
13178    // prototype, hence we have to reload the initial map.
13179    EnsureHasInitialMap(constructor);
13180    constructor_initial_map = handle(constructor->initial_map(), isolate);
13181  }
13182
13183  // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
13184  // correct realm. Rather than directly fetching the .prototype, we fetch the
13185  // constructor that points to the .prototype. This relies on
13186  // constructor.prototype being FROZEN for those constructors.
13187  if (!prototype->IsJSReceiver()) {
13188    Handle<Context> context;
13189    ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
13190                               JSReceiver::GetFunctionRealm(new_target), Map);
13191    DCHECK(context->IsNativeContext());
13192    Handle<Object> maybe_index = JSReceiver::GetDataProperty(
13193        constructor, isolate->factory()->native_context_index_symbol());
13194    int index = maybe_index->IsSmi() ? Smi::cast(*maybe_index)->value()
13195                                     : Context::OBJECT_FUNCTION_INDEX;
13196    Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)));
13197    prototype = handle(realm_constructor->prototype(), isolate);
13198  }
13199
13200  Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
13201  map->set_new_target_is_base(false);
13202  DCHECK(prototype->IsJSReceiver());
13203  if (map->prototype() != *prototype) {
13204    Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
13205  }
13206  map->SetConstructor(*constructor);
13207  return map;
13208}
13209
13210
13211void JSFunction::PrintName(FILE* out) {
13212  base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
13213  PrintF(out, "%s", name.get());
13214}
13215
13216
13217// The filter is a pattern that matches function names in this way:
13218//   "*"      all; the default
13219//   "-"      all but the top-level function
13220//   "-name"  all but the function "name"
13221//   ""       only the top-level function
13222//   "name"   only the function "name"
13223//   "name*"  only functions starting with "name"
13224//   "~"      none; the tilde is not an identifier
13225bool JSFunction::PassesFilter(const char* raw_filter) {
13226  if (*raw_filter == '*') return true;
13227  String* name = shared()->DebugName();
13228  Vector<const char> filter = CStrVector(raw_filter);
13229  if (filter.length() == 0) return name->length() == 0;
13230  if (filter[0] == '-') {
13231    // Negative filter.
13232    if (filter.length() == 1) {
13233      return (name->length() != 0);
13234    } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
13235      return false;
13236    }
13237    if (filter[filter.length() - 1] == '*' &&
13238        name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
13239      return false;
13240    }
13241    return true;
13242
13243  } else if (name->IsUtf8EqualTo(filter)) {
13244    return true;
13245  }
13246  if (filter[filter.length() - 1] == '*' &&
13247      name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
13248    return true;
13249  }
13250  return false;
13251}
13252
13253
13254Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
13255  Isolate* isolate = function->GetIsolate();
13256  Handle<Object> name =
13257      JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
13258  if (name->IsString()) return Handle<String>::cast(name);
13259  return handle(function->shared()->DebugName(), isolate);
13260}
13261
13262
13263Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
13264  Isolate* isolate = function->GetIsolate();
13265  Handle<Object> name = JSReceiver::GetDataProperty(
13266      function, isolate->factory()->display_name_string());
13267  if (name->IsString()) return Handle<String>::cast(name);
13268  return JSFunction::GetName(function);
13269}
13270
13271
13272namespace {
13273
13274char const kNativeCodeSource[] = "function () { [native code] }";
13275
13276
13277Handle<String> NativeCodeFunctionSourceString(
13278    Handle<SharedFunctionInfo> shared_info) {
13279  Isolate* const isolate = shared_info->GetIsolate();
13280  if (shared_info->name()->IsString()) {
13281    IncrementalStringBuilder builder(isolate);
13282    builder.AppendCString("function ");
13283    builder.AppendString(handle(String::cast(shared_info->name()), isolate));
13284    builder.AppendCString("() { [native code] }");
13285    return builder.Finish().ToHandleChecked();
13286  }
13287  return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
13288}
13289
13290}  // namespace
13291
13292
13293// static
13294Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
13295  Isolate* const isolate = function->GetIsolate();
13296  return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
13297}
13298
13299
13300// static
13301Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
13302  Isolate* const isolate = function->GetIsolate();
13303  Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
13304
13305  // Check if {function} should hide its source code.
13306  if (!shared_info->script()->IsScript() ||
13307      Script::cast(shared_info->script())->hide_source()) {
13308    return NativeCodeFunctionSourceString(shared_info);
13309  }
13310
13311  // Check if we should print {function} as a class.
13312  Handle<Object> class_start_position = JSReceiver::GetDataProperty(
13313      function, isolate->factory()->class_start_position_symbol());
13314  if (class_start_position->IsSmi()) {
13315    Handle<Object> class_end_position = JSReceiver::GetDataProperty(
13316        function, isolate->factory()->class_end_position_symbol());
13317    Handle<String> script_source(
13318        String::cast(Script::cast(shared_info->script())->source()), isolate);
13319    return isolate->factory()->NewSubString(
13320        script_source, Handle<Smi>::cast(class_start_position)->value(),
13321        Handle<Smi>::cast(class_end_position)->value());
13322  }
13323
13324  // Check if we have source code for the {function}.
13325  if (!shared_info->HasSourceCode()) {
13326    return NativeCodeFunctionSourceString(shared_info);
13327  }
13328
13329  IncrementalStringBuilder builder(isolate);
13330  if (!shared_info->is_arrow()) {
13331    if (shared_info->is_concise_method()) {
13332      if (shared_info->is_generator()) builder.AppendCharacter('*');
13333    } else {
13334      if (shared_info->is_generator()) {
13335        builder.AppendCString("function* ");
13336      } else {
13337        builder.AppendCString("function ");
13338      }
13339    }
13340    if (shared_info->name_should_print_as_anonymous()) {
13341      builder.AppendCString("anonymous");
13342    } else {
13343      builder.AppendString(handle(String::cast(shared_info->name()), isolate));
13344    }
13345  }
13346  builder.AppendString(Handle<String>::cast(shared_info->GetSourceCode()));
13347  return builder.Finish().ToHandleChecked();
13348}
13349
13350
13351void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
13352                         const char* to_string, Handle<Object> to_number,
13353                         const char* type_of, byte kind) {
13354  Handle<String> internalized_to_string =
13355      isolate->factory()->InternalizeUtf8String(to_string);
13356  Handle<String> internalized_type_of =
13357      isolate->factory()->InternalizeUtf8String(type_of);
13358  oddball->set_to_number(*to_number);
13359  oddball->set_to_string(*internalized_to_string);
13360  oddball->set_type_of(*internalized_type_of);
13361  oddball->set_kind(kind);
13362}
13363
13364
13365void Script::InitLineEnds(Handle<Script> script) {
13366  if (!script->line_ends()->IsUndefined()) return;
13367
13368  Isolate* isolate = script->GetIsolate();
13369
13370  if (!script->source()->IsString()) {
13371    DCHECK(script->source()->IsUndefined());
13372    Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
13373    script->set_line_ends(*empty);
13374    DCHECK(script->line_ends()->IsFixedArray());
13375    return;
13376  }
13377
13378  Handle<String> src(String::cast(script->source()), isolate);
13379
13380  Handle<FixedArray> array = String::CalculateLineEnds(src, true);
13381
13382  if (*array != isolate->heap()->empty_fixed_array()) {
13383    array->set_map(isolate->heap()->fixed_cow_array_map());
13384  }
13385
13386  script->set_line_ends(*array);
13387  DCHECK(script->line_ends()->IsFixedArray());
13388}
13389
13390
13391int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
13392  int line_number = GetLineNumber(script, code_pos);
13393  if (line_number == -1) return -1;
13394
13395  DisallowHeapAllocation no_allocation;
13396  FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
13397  line_number = line_number - script->line_offset();
13398  if (line_number == 0) return code_pos + script->column_offset();
13399  int prev_line_end_pos =
13400      Smi::cast(line_ends_array->get(line_number - 1))->value();
13401  return code_pos - (prev_line_end_pos + 1);
13402}
13403
13404
13405int Script::GetLineNumberWithArray(int code_pos) {
13406  DisallowHeapAllocation no_allocation;
13407  DCHECK(line_ends()->IsFixedArray());
13408  FixedArray* line_ends_array = FixedArray::cast(line_ends());
13409  int line_ends_len = line_ends_array->length();
13410  if (line_ends_len == 0) return -1;
13411
13412  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
13413    return line_offset();
13414  }
13415
13416  int left = 0;
13417  int right = line_ends_len;
13418  while (int half = (right - left) / 2) {
13419    if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
13420      right -= half;
13421    } else {
13422      left += half;
13423    }
13424  }
13425  return right + line_offset();
13426}
13427
13428
13429int Script::GetLineNumber(Handle<Script> script, int code_pos) {
13430  InitLineEnds(script);
13431  return script->GetLineNumberWithArray(code_pos);
13432}
13433
13434
13435int Script::GetLineNumber(int code_pos) {
13436  DisallowHeapAllocation no_allocation;
13437  if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
13438
13439  // Slow mode: we do not have line_ends. We have to iterate through source.
13440  if (!source()->IsString()) return -1;
13441
13442  String* source_string = String::cast(source());
13443  int line = 0;
13444  int len = source_string->length();
13445  for (int pos = 0; pos < len; pos++) {
13446    if (pos == code_pos) break;
13447    if (source_string->Get(pos) == '\n') line++;
13448  }
13449  return line;
13450}
13451
13452
13453Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
13454  Isolate* isolate = script->GetIsolate();
13455  Handle<String> name_or_source_url_key =
13456      isolate->factory()->InternalizeOneByteString(
13457          STATIC_CHAR_VECTOR("nameOrSourceURL"));
13458  Handle<JSObject> script_wrapper = Script::GetWrapper(script);
13459  Handle<Object> property = Object::GetProperty(
13460      script_wrapper, name_or_source_url_key).ToHandleChecked();
13461  DCHECK(property->IsJSFunction());
13462  Handle<Object> result;
13463  // Do not check against pending exception, since this function may be called
13464  // when an exception has already been pending.
13465  if (!Execution::TryCall(isolate, property, script_wrapper, 0, NULL)
13466           .ToHandle(&result)) {
13467    return isolate->factory()->undefined_value();
13468  }
13469  return result;
13470}
13471
13472
13473Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
13474  Isolate* isolate = script->GetIsolate();
13475  if (!script->wrapper()->IsUndefined()) {
13476    DCHECK(script->wrapper()->IsWeakCell());
13477    Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
13478    if (!cell->cleared()) {
13479      // Return a handle for the existing script wrapper from the cache.
13480      return handle(JSObject::cast(cell->value()));
13481    }
13482    // If we found an empty WeakCell, that means the script wrapper was
13483    // GCed.  We are not notified directly of that, so we decrement here
13484    // so that we at least don't count double for any given script.
13485    isolate->counters()->script_wrappers()->Decrement();
13486  }
13487  // Construct a new script wrapper.
13488  isolate->counters()->script_wrappers()->Increment();
13489  Handle<JSFunction> constructor = isolate->script_function();
13490  Handle<JSValue> result =
13491      Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
13492  result->set_value(*script);
13493  Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
13494  script->set_wrapper(*cell);
13495  return result;
13496}
13497
13498
13499MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
13500    FunctionLiteral* fun) {
13501  WeakFixedArray::Iterator iterator(shared_function_infos());
13502  SharedFunctionInfo* shared;
13503  while ((shared = iterator.Next<SharedFunctionInfo>())) {
13504    if (fun->function_token_position() == shared->function_token_position() &&
13505        fun->start_position() == shared->start_position()) {
13506      return Handle<SharedFunctionInfo>(shared);
13507    }
13508  }
13509  return MaybeHandle<SharedFunctionInfo>();
13510}
13511
13512
13513Script::Iterator::Iterator(Isolate* isolate)
13514    : iterator_(isolate->heap()->script_list()) {}
13515
13516
13517Script* Script::Iterator::Next() { return iterator_.Next<Script>(); }
13518
13519
13520SharedFunctionInfo::Iterator::Iterator(Isolate* isolate)
13521    : script_iterator_(isolate),
13522      sfi_iterator_(isolate->heap()->noscript_shared_function_infos()) {}
13523
13524
13525bool SharedFunctionInfo::Iterator::NextScript() {
13526  Script* script = script_iterator_.Next();
13527  if (script == NULL) return false;
13528  sfi_iterator_.Reset(script->shared_function_infos());
13529  return true;
13530}
13531
13532
13533SharedFunctionInfo* SharedFunctionInfo::Iterator::Next() {
13534  do {
13535    SharedFunctionInfo* next = sfi_iterator_.Next<SharedFunctionInfo>();
13536    if (next != NULL) return next;
13537  } while (NextScript());
13538  return NULL;
13539}
13540
13541
13542void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
13543                                   Handle<Object> script_object) {
13544  if (shared->script() == *script_object) return;
13545  Isolate* isolate = shared->GetIsolate();
13546
13547  // Add shared function info to new script's list. If a collection occurs,
13548  // the shared function info may be temporarily in two lists.
13549  // This is okay because the gc-time processing of these lists can tolerate
13550  // duplicates.
13551  Handle<Object> list;
13552  if (script_object->IsScript()) {
13553    Handle<Script> script = Handle<Script>::cast(script_object);
13554    list = handle(script->shared_function_infos(), isolate);
13555  } else {
13556    list = isolate->factory()->noscript_shared_function_infos();
13557  }
13558
13559#ifdef DEBUG
13560  {
13561    WeakFixedArray::Iterator iterator(*list);
13562    SharedFunctionInfo* next;
13563    while ((next = iterator.Next<SharedFunctionInfo>())) {
13564      DCHECK_NE(next, *shared);
13565    }
13566  }
13567#endif  // DEBUG
13568  list = WeakFixedArray::Add(list, shared);
13569
13570  if (script_object->IsScript()) {
13571    Handle<Script> script = Handle<Script>::cast(script_object);
13572    script->set_shared_function_infos(*list);
13573  } else {
13574    isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
13575  }
13576
13577  // Remove shared function info from old script's list.
13578  if (shared->script()->IsScript()) {
13579    Script* old_script = Script::cast(shared->script());
13580    if (old_script->shared_function_infos()->IsWeakFixedArray()) {
13581      WeakFixedArray* list =
13582          WeakFixedArray::cast(old_script->shared_function_infos());
13583      list->Remove(shared);
13584    }
13585  } else {
13586    // Remove shared function info from root array.
13587    Object* list = isolate->heap()->noscript_shared_function_infos();
13588    CHECK(WeakFixedArray::cast(list)->Remove(shared));
13589  }
13590
13591  // Finally set new script.
13592  shared->set_script(*script_object);
13593}
13594
13595
13596String* SharedFunctionInfo::DebugName() {
13597  Object* n = name();
13598  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
13599  return String::cast(n);
13600}
13601
13602
13603bool SharedFunctionInfo::HasSourceCode() const {
13604  return !script()->IsUndefined() &&
13605         !reinterpret_cast<Script*>(script())->source()->IsUndefined();
13606}
13607
13608
13609Handle<Object> SharedFunctionInfo::GetSourceCode() {
13610  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
13611  Handle<String> source(String::cast(Script::cast(script())->source()));
13612  return GetIsolate()->factory()->NewSubString(
13613      source, start_position(), end_position());
13614}
13615
13616
13617bool SharedFunctionInfo::IsInlineable() {
13618  // Check that the function has a script associated with it.
13619  if (!script()->IsScript()) return false;
13620  return !optimization_disabled();
13621}
13622
13623
13624int SharedFunctionInfo::SourceSize() {
13625  return end_position() - start_position();
13626}
13627
13628
13629namespace {
13630
13631void CalculateInstanceSizeHelper(InstanceType instance_type,
13632                                 int requested_internal_fields,
13633                                 int requested_in_object_properties,
13634                                 int* instance_size,
13635                                 int* in_object_properties) {
13636  int header_size = JSObject::GetHeaderSize(instance_type);
13637  DCHECK_LE(requested_internal_fields,
13638            (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2);
13639  *instance_size =
13640      Min(header_size +
13641              ((requested_internal_fields + requested_in_object_properties)
13642               << kPointerSizeLog2),
13643          JSObject::kMaxInstanceSize);
13644  *in_object_properties = ((*instance_size - header_size) >> kPointerSizeLog2) -
13645                          requested_internal_fields;
13646}
13647
13648}  // namespace
13649
13650
13651void JSFunction::CalculateInstanceSize(InstanceType instance_type,
13652                                       int requested_internal_fields,
13653                                       int* instance_size,
13654                                       int* in_object_properties) {
13655  CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
13656                              shared()->expected_nof_properties(),
13657                              instance_size, in_object_properties);
13658}
13659
13660
13661void JSFunction::CalculateInstanceSizeForDerivedClass(
13662    InstanceType instance_type, int requested_internal_fields,
13663    int* instance_size, int* in_object_properties) {
13664  Isolate* isolate = GetIsolate();
13665  int expected_nof_properties = 0;
13666  for (PrototypeIterator iter(isolate, this,
13667                              PrototypeIterator::START_AT_RECEIVER);
13668       !iter.IsAtEnd(); iter.Advance()) {
13669    JSFunction* func = iter.GetCurrent<JSFunction>();
13670    SharedFunctionInfo* shared = func->shared();
13671    expected_nof_properties += shared->expected_nof_properties();
13672    if (!IsSubclassConstructor(shared->kind())) {
13673      break;
13674    }
13675  }
13676  CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
13677                              expected_nof_properties, instance_size,
13678                              in_object_properties);
13679}
13680
13681
13682// Output the source code without any allocation in the heap.
13683std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
13684  const SharedFunctionInfo* s = v.value;
13685  // For some native functions there is no source.
13686  if (!s->HasSourceCode()) return os << "<No Source>";
13687
13688  // Get the source for the script which this function came from.
13689  // Don't use String::cast because we don't want more assertion errors while
13690  // we are already creating a stack dump.
13691  String* script_source =
13692      reinterpret_cast<String*>(Script::cast(s->script())->source());
13693
13694  if (!script_source->LooksValid()) return os << "<Invalid Source>";
13695
13696  if (!s->is_toplevel()) {
13697    os << "function ";
13698    Object* name = s->name();
13699    if (name->IsString() && String::cast(name)->length() > 0) {
13700      String::cast(name)->PrintUC16(os);
13701    }
13702  }
13703
13704  int len = s->end_position() - s->start_position();
13705  if (len <= v.max_length || v.max_length < 0) {
13706    script_source->PrintUC16(os, s->start_position(), s->end_position());
13707    return os;
13708  } else {
13709    script_source->PrintUC16(os, s->start_position(),
13710                             s->start_position() + v.max_length);
13711    return os << "...\n";
13712  }
13713}
13714
13715
13716static bool IsCodeEquivalent(Code* code, Code* recompiled) {
13717  if (code->instruction_size() != recompiled->instruction_size()) return false;
13718  ByteArray* code_relocation = code->relocation_info();
13719  ByteArray* recompiled_relocation = recompiled->relocation_info();
13720  int length = code_relocation->length();
13721  if (length != recompiled_relocation->length()) return false;
13722  int compare = memcmp(code_relocation->GetDataStartAddress(),
13723                       recompiled_relocation->GetDataStartAddress(),
13724                       length);
13725  return compare == 0;
13726}
13727
13728
13729void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
13730  DCHECK(!has_deoptimization_support());
13731  DisallowHeapAllocation no_allocation;
13732  Code* code = this->code();
13733  if (IsCodeEquivalent(code, recompiled)) {
13734    // Copy the deoptimization data from the recompiled code.
13735    code->set_deoptimization_data(recompiled->deoptimization_data());
13736    code->set_has_deoptimization_support(true);
13737  } else {
13738    // TODO(3025757): In case the recompiled isn't equivalent to the
13739    // old code, we have to replace it. We should try to avoid this
13740    // altogether because it flushes valuable type feedback by
13741    // effectively resetting all IC state.
13742    ReplaceCode(recompiled);
13743  }
13744  DCHECK(has_deoptimization_support());
13745}
13746
13747
13748void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
13749  // Disable optimization for the shared function info and mark the
13750  // code as non-optimizable. The marker on the shared function info
13751  // is there because we flush non-optimized code thereby loosing the
13752  // non-optimizable information for the code. When the code is
13753  // regenerated and set on the shared function info it is marked as
13754  // non-optimizable if optimization is disabled for the shared
13755  // function info.
13756  DCHECK(reason != kNoReason);
13757  set_optimization_disabled(true);
13758  set_disable_optimization_reason(reason);
13759  // Code should be the lazy compilation stub or else unoptimized.
13760  DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
13761  PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
13762  if (FLAG_trace_opt) {
13763    PrintF("[disabled optimization for ");
13764    ShortPrint();
13765    PrintF(", reason: %s]\n", GetBailoutReason(reason));
13766  }
13767}
13768
13769
13770void SharedFunctionInfo::InitFromFunctionLiteral(
13771    Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
13772  shared_info->set_length(lit->scope()->default_function_length());
13773  shared_info->set_internal_formal_parameter_count(lit->parameter_count());
13774  shared_info->set_function_token_position(lit->function_token_position());
13775  shared_info->set_start_position(lit->start_position());
13776  shared_info->set_end_position(lit->end_position());
13777  shared_info->set_is_expression(lit->is_expression());
13778  shared_info->set_is_anonymous(lit->is_anonymous());
13779  shared_info->set_inferred_name(*lit->inferred_name());
13780  shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
13781  shared_info->set_allows_lazy_compilation_without_context(
13782      lit->AllowsLazyCompilationWithoutContext());
13783  shared_info->set_language_mode(lit->language_mode());
13784  shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
13785  shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
13786  shared_info->set_ast_node_count(lit->ast_node_count());
13787  shared_info->set_is_function(lit->is_function());
13788  if (lit->dont_optimize_reason() != kNoReason) {
13789    shared_info->DisableOptimization(lit->dont_optimize_reason());
13790  }
13791  shared_info->set_dont_crankshaft(lit->flags() &
13792                                   AstProperties::kDontCrankshaft);
13793  shared_info->set_kind(lit->kind());
13794  if (!IsConstructable(lit->kind(), lit->language_mode())) {
13795    shared_info->set_construct_stub(
13796        *shared_info->GetIsolate()->builtins()->ConstructedNonConstructable());
13797  }
13798  shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
13799  shared_info->set_asm_function(lit->scope()->asm_function());
13800}
13801
13802
13803bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
13804  DCHECK(!id.IsNone());
13805  Code* unoptimized = code();
13806  DeoptimizationOutputData* data =
13807      DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
13808  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
13809  USE(ignore);
13810  return true;  // Return true if there was no DCHECK.
13811}
13812
13813
13814void Map::StartInobjectSlackTracking() {
13815  DCHECK(!IsInobjectSlackTrackingInProgress());
13816
13817  // No tracking during the snapshot construction phase.
13818  Isolate* isolate = GetIsolate();
13819  if (isolate->serializer_enabled()) return;
13820
13821  if (unused_property_fields() == 0) return;
13822
13823  set_construction_counter(Map::kSlackTrackingCounterStart);
13824}
13825
13826
13827void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
13828  code()->ClearInlineCaches();
13829  // If we clear ICs, we need to clear the type feedback vector too, since
13830  // CallICs are synced with a feedback vector slot.
13831  ClearTypeFeedbackInfo();
13832  set_ic_age(new_ic_age);
13833  if (code()->kind() == Code::FUNCTION) {
13834    code()->set_profiler_ticks(0);
13835    if (optimization_disabled() &&
13836        opt_count() >= FLAG_max_opt_count) {
13837      // Re-enable optimizations if they were disabled due to opt_count limit.
13838      set_optimization_disabled(false);
13839    }
13840    set_opt_count(0);
13841    set_deopt_count(0);
13842  }
13843}
13844
13845
13846int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context,
13847                                                    BailoutId osr_ast_id) {
13848  DisallowHeapAllocation no_gc;
13849  DCHECK(native_context->IsNativeContext());
13850  if (!OptimizedCodeMapIsCleared()) {
13851    FixedArray* optimized_code_map = this->optimized_code_map();
13852    int length = optimized_code_map->length();
13853    Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
13854    for (int i = kEntriesStart; i < length; i += kEntryLength) {
13855      if (WeakCell::cast(optimized_code_map->get(i + kContextOffset))
13856                  ->value() == native_context &&
13857          optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
13858        return i;
13859      }
13860    }
13861    Object* shared_code =
13862        WeakCell::cast(optimized_code_map->get(kSharedCodeIndex))->value();
13863    if (shared_code->IsCode() && osr_ast_id.IsNone()) {
13864      return kSharedCodeIndex;
13865    }
13866  }
13867  return -1;
13868}
13869
13870
13871CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
13872    Context* native_context, BailoutId osr_ast_id) {
13873  CodeAndLiterals result = {nullptr, nullptr};
13874  int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id);
13875  if (entry != kNotFound) {
13876    FixedArray* code_map = optimized_code_map();
13877    if (entry == kSharedCodeIndex) {
13878      // We know the weak cell isn't cleared because we made sure of it in
13879      // SearchOptimizedCodeMapEntry and performed no allocations since that
13880      // call.
13881      result = {
13882          Code::cast(WeakCell::cast(code_map->get(kSharedCodeIndex))->value()),
13883          nullptr};
13884    } else {
13885      DCHECK_LE(entry + kEntryLength, code_map->length());
13886      WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
13887      WeakCell* literals_cell =
13888          WeakCell::cast(code_map->get(entry + kLiteralsOffset));
13889
13890      result = {cell->cleared() ? nullptr : Code::cast(cell->value()),
13891                literals_cell->cleared()
13892                    ? nullptr
13893                    : LiteralsArray::cast(literals_cell->value())};
13894    }
13895  }
13896  if (FLAG_trace_opt && !OptimizedCodeMapIsCleared() &&
13897      result.code == nullptr) {
13898    PrintF("[didn't find optimized code in optimized code map for ");
13899    ShortPrint();
13900    PrintF("]\n");
13901  }
13902  return result;
13903}
13904
13905
13906#define DECLARE_TAG(ignore1, name, ignore2) name,
13907const char* const VisitorSynchronization::kTags[
13908    VisitorSynchronization::kNumberOfSyncTags] = {
13909  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
13910};
13911#undef DECLARE_TAG
13912
13913
13914#define DECLARE_TAG(ignore1, ignore2, name) name,
13915const char* const VisitorSynchronization::kTagNames[
13916    VisitorSynchronization::kNumberOfSyncTags] = {
13917  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
13918};
13919#undef DECLARE_TAG
13920
13921
13922void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
13923  DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
13924  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
13925  Object* old_target = target;
13926  VisitPointer(&target);
13927  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
13928}
13929
13930
13931void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
13932  DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
13933  Object* stub = rinfo->code_age_stub();
13934  if (stub) {
13935    VisitPointer(&stub);
13936  }
13937}
13938
13939
13940void ObjectVisitor::VisitCodeEntry(Address entry_address) {
13941  Object* code = Code::GetObjectFromEntryAddress(entry_address);
13942  Object* old_code = code;
13943  VisitPointer(&code);
13944  if (code != old_code) {
13945    Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
13946  }
13947}
13948
13949
13950void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
13951  DCHECK(rinfo->rmode() == RelocInfo::CELL);
13952  Object* cell = rinfo->target_cell();
13953  Object* old_cell = cell;
13954  VisitPointer(&cell);
13955  if (cell != old_cell) {
13956    rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
13957  }
13958}
13959
13960
13961void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
13962  DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
13963         rinfo->IsPatchedDebugBreakSlotSequence());
13964  Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
13965  Object* old_target = target;
13966  VisitPointer(&target);
13967  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
13968}
13969
13970
13971void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
13972  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
13973  Object* p = rinfo->target_object();
13974  VisitPointer(&p);
13975}
13976
13977
13978void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
13979  Address p = rinfo->target_external_reference();
13980  VisitExternalReference(&p);
13981}
13982
13983
13984void Code::InvalidateRelocation() {
13985  InvalidateEmbeddedObjects();
13986  set_relocation_info(GetHeap()->empty_byte_array());
13987}
13988
13989
13990void Code::InvalidateEmbeddedObjects() {
13991  Object* undefined = GetHeap()->undefined_value();
13992  Cell* undefined_cell = GetHeap()->undefined_cell();
13993  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
13994                  RelocInfo::ModeMask(RelocInfo::CELL);
13995  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
13996    RelocInfo::Mode mode = it.rinfo()->rmode();
13997    if (mode == RelocInfo::EMBEDDED_OBJECT) {
13998      it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
13999    } else if (mode == RelocInfo::CELL) {
14000      it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
14001    }
14002  }
14003}
14004
14005
14006void Code::Relocate(intptr_t delta) {
14007  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
14008    it.rinfo()->apply(delta);
14009  }
14010  Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
14011}
14012
14013
14014void Code::CopyFrom(const CodeDesc& desc) {
14015  DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
14016
14017  // copy code
14018  CopyBytes(instruction_start(), desc.buffer,
14019            static_cast<size_t>(desc.instr_size));
14020
14021  // copy reloc info
14022  CopyBytes(relocation_start(),
14023            desc.buffer + desc.buffer_size - desc.reloc_size,
14024            static_cast<size_t>(desc.reloc_size));
14025
14026  // unbox handles and relocate
14027  intptr_t delta = instruction_start() - desc.buffer;
14028  int mode_mask = RelocInfo::kCodeTargetMask |
14029                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
14030                  RelocInfo::ModeMask(RelocInfo::CELL) |
14031                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
14032                  RelocInfo::kApplyMask;
14033  // Needed to find target_object and runtime_entry on X64
14034  Assembler* origin = desc.origin;
14035  AllowDeferredHandleDereference embedding_raw_address;
14036  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
14037    RelocInfo::Mode mode = it.rinfo()->rmode();
14038    if (mode == RelocInfo::EMBEDDED_OBJECT) {
14039      Handle<Object> p = it.rinfo()->target_object_handle(origin);
14040      it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
14041    } else if (mode == RelocInfo::CELL) {
14042      Handle<Cell> cell  = it.rinfo()->target_cell_handle();
14043      it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
14044    } else if (RelocInfo::IsCodeTarget(mode)) {
14045      // rewrite code handles in inline cache targets to direct
14046      // pointers to the first instruction in the code object
14047      Handle<Object> p = it.rinfo()->target_object_handle(origin);
14048      Code* code = Code::cast(*p);
14049      it.rinfo()->set_target_address(code->instruction_start(),
14050                                     SKIP_WRITE_BARRIER,
14051                                     SKIP_ICACHE_FLUSH);
14052    } else if (RelocInfo::IsRuntimeEntry(mode)) {
14053      Address p = it.rinfo()->target_runtime_entry(origin);
14054      it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
14055                                           SKIP_ICACHE_FLUSH);
14056    } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
14057      Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
14058      Code* code = Code::cast(*p);
14059      it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
14060    } else {
14061      it.rinfo()->apply(delta);
14062    }
14063  }
14064  Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
14065}
14066
14067
14068// Locate the source position which is closest to the address in the code. This
14069// is using the source position information embedded in the relocation info.
14070// The position returned is relative to the beginning of the script where the
14071// source for this function is found.
14072int Code::SourcePosition(Address pc) {
14073  int distance = kMaxInt;
14074  int position = RelocInfo::kNoPosition;  // Initially no position found.
14075  // Run through all the relocation info to find the best matching source
14076  // position. All the code needs to be considered as the sequence of the
14077  // instructions in the code does not necessarily follow the same order as the
14078  // source.
14079  RelocIterator it(this, RelocInfo::kPositionMask);
14080  while (!it.done()) {
14081    // Only look at positions after the current pc.
14082    if (it.rinfo()->pc() < pc) {
14083      // Get position and distance.
14084
14085      int dist = static_cast<int>(pc - it.rinfo()->pc());
14086      int pos = static_cast<int>(it.rinfo()->data());
14087      // If this position is closer than the current candidate or if it has the
14088      // same distance as the current candidate and the position is higher then
14089      // this position is the new candidate.
14090      if ((dist < distance) ||
14091          (dist == distance && pos > position)) {
14092        position = pos;
14093        distance = dist;
14094      }
14095    }
14096    it.next();
14097  }
14098  return position;
14099}
14100
14101
14102// Same as Code::SourcePosition above except it only looks for statement
14103// positions.
14104int Code::SourceStatementPosition(Address pc) {
14105  // First find the position as close as possible using all position
14106  // information.
14107  int position = SourcePosition(pc);
14108  // Now find the closest statement position before the position.
14109  int statement_position = 0;
14110  RelocIterator it(this, RelocInfo::kPositionMask);
14111  while (!it.done()) {
14112    if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
14113      int p = static_cast<int>(it.rinfo()->data());
14114      if (statement_position < p && p <= position) {
14115        statement_position = p;
14116      }
14117    }
14118    it.next();
14119  }
14120  return statement_position;
14121}
14122
14123
14124SafepointEntry Code::GetSafepointEntry(Address pc) {
14125  SafepointTable table(this);
14126  return table.FindEntry(pc);
14127}
14128
14129
14130Object* Code::FindNthObject(int n, Map* match_map) {
14131  DCHECK(is_inline_cache_stub());
14132  DisallowHeapAllocation no_allocation;
14133  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14134  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14135    RelocInfo* info = it.rinfo();
14136    Object* object = info->target_object();
14137    if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
14138    if (object->IsHeapObject()) {
14139      if (HeapObject::cast(object)->map() == match_map) {
14140        if (--n == 0) return object;
14141      }
14142    }
14143  }
14144  return NULL;
14145}
14146
14147
14148AllocationSite* Code::FindFirstAllocationSite() {
14149  Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
14150  return (result != NULL) ? AllocationSite::cast(result) : NULL;
14151}
14152
14153
14154Map* Code::FindFirstMap() {
14155  Object* result = FindNthObject(1, GetHeap()->meta_map());
14156  return (result != NULL) ? Map::cast(result) : NULL;
14157}
14158
14159
14160void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
14161  DCHECK(is_inline_cache_stub() || is_handler());
14162  DisallowHeapAllocation no_allocation;
14163  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14164  STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
14165  int current_pattern = 0;
14166  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14167    RelocInfo* info = it.rinfo();
14168    Object* object = info->target_object();
14169    if (object->IsHeapObject()) {
14170      if (object->IsWeakCell()) {
14171        object = HeapObject::cast(WeakCell::cast(object)->value());
14172      }
14173      Map* map = HeapObject::cast(object)->map();
14174      if (map == *pattern.find_[current_pattern]) {
14175        info->set_target_object(*pattern.replace_[current_pattern]);
14176        if (++current_pattern == pattern.count_) return;
14177      }
14178    }
14179  }
14180  UNREACHABLE();
14181}
14182
14183
14184void Code::FindAllMaps(MapHandleList* maps) {
14185  DCHECK(is_inline_cache_stub());
14186  DisallowHeapAllocation no_allocation;
14187  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14188  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14189    RelocInfo* info = it.rinfo();
14190    Object* object = info->target_object();
14191    if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
14192    if (object->IsMap()) maps->Add(handle(Map::cast(object)));
14193  }
14194}
14195
14196
14197Code* Code::FindFirstHandler() {
14198  DCHECK(is_inline_cache_stub());
14199  DisallowHeapAllocation no_allocation;
14200  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14201             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14202  bool skip_next_handler = false;
14203  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14204    RelocInfo* info = it.rinfo();
14205    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
14206      Object* obj = info->target_object();
14207      skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
14208    } else {
14209      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
14210      if (code->kind() == Code::HANDLER) {
14211        if (!skip_next_handler) return code;
14212        skip_next_handler = false;
14213      }
14214    }
14215  }
14216  return NULL;
14217}
14218
14219
14220bool Code::FindHandlers(CodeHandleList* code_list, int length) {
14221  DCHECK(is_inline_cache_stub());
14222  DisallowHeapAllocation no_allocation;
14223  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14224             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14225  bool skip_next_handler = false;
14226  int i = 0;
14227  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14228    if (i == length) return true;
14229    RelocInfo* info = it.rinfo();
14230    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
14231      Object* obj = info->target_object();
14232      skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
14233    } else {
14234      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
14235      // IC stubs with handlers never contain non-handler code objects before
14236      // handler targets.
14237      if (code->kind() != Code::HANDLER) break;
14238      if (!skip_next_handler) {
14239        code_list->Add(Handle<Code>(code));
14240        i++;
14241      }
14242      skip_next_handler = false;
14243    }
14244  }
14245  return i == length;
14246}
14247
14248
14249MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
14250  DCHECK(is_inline_cache_stub());
14251  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14252             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14253  bool return_next = false;
14254  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14255    RelocInfo* info = it.rinfo();
14256    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
14257      Object* object = info->target_object();
14258      if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
14259      if (object == map) return_next = true;
14260    } else if (return_next) {
14261      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
14262      DCHECK(code->kind() == Code::HANDLER);
14263      return handle(code);
14264    }
14265  }
14266  return MaybeHandle<Code>();
14267}
14268
14269
14270Name* Code::FindFirstName() {
14271  DCHECK(is_inline_cache_stub());
14272  DisallowHeapAllocation no_allocation;
14273  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
14274  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14275    RelocInfo* info = it.rinfo();
14276    Object* object = info->target_object();
14277    if (object->IsName()) return Name::cast(object);
14278  }
14279  return NULL;
14280}
14281
14282
14283void Code::ClearInlineCaches() {
14284  ClearInlineCaches(NULL);
14285}
14286
14287
14288void Code::ClearInlineCaches(Code::Kind kind) {
14289  ClearInlineCaches(&kind);
14290}
14291
14292
14293void Code::ClearInlineCaches(Code::Kind* kind) {
14294  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
14295             RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
14296  for (RelocIterator it(this, mask); !it.done(); it.next()) {
14297    RelocInfo* info = it.rinfo();
14298    Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
14299    if (target->is_inline_cache_stub()) {
14300      if (kind == NULL || *kind == target->kind()) {
14301        IC::Clear(this->GetIsolate(), info->pc(),
14302                  info->host()->constant_pool());
14303      }
14304    }
14305  }
14306}
14307
14308
14309void SharedFunctionInfo::ClearTypeFeedbackInfo() {
14310  feedback_vector()->ClearSlots(this);
14311}
14312
14313
14314void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
14315  feedback_vector()->ClearSlotsAtGCTime(this);
14316}
14317
14318
14319BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
14320  DisallowHeapAllocation no_gc;
14321  DCHECK(kind() == FUNCTION);
14322  BackEdgeTable back_edges(this, &no_gc);
14323  for (uint32_t i = 0; i < back_edges.length(); i++) {
14324    if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
14325  }
14326  return BailoutId::None();
14327}
14328
14329
14330uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
14331  DisallowHeapAllocation no_gc;
14332  DCHECK(kind() == FUNCTION);
14333  BackEdgeTable back_edges(this, &no_gc);
14334  for (uint32_t i = 0; i < back_edges.length(); i++) {
14335    if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
14336  }
14337  UNREACHABLE();  // We expect to find the back edge.
14338  return 0;
14339}
14340
14341
14342void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
14343  PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
14344}
14345
14346
14347void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
14348  PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
14349      NO_MARKING_PARITY);
14350}
14351
14352
14353// NextAge defines the Code::Age state transitions during a GC cycle.
14354static Code::Age NextAge(Code::Age age) {
14355  switch (age) {
14356    case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
14357    case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
14358    case Code::kLastCodeAge:  // Clamp at last Code::Age value.
14359      return age;
14360    case Code::kExecutedOnceCodeAge:
14361      // Pre-age code that has only been executed once.
14362      return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
14363    default:
14364      return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
14365  }
14366}
14367
14368
14369// IsOldAge defines the collection criteria for a Code object.
14370static bool IsOldAge(Code::Age age) {
14371  return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
14372}
14373
14374
14375void Code::MakeYoung(Isolate* isolate) {
14376  byte* sequence = FindCodeAgeSequence();
14377  if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
14378}
14379
14380
14381void Code::MarkToBeExecutedOnce(Isolate* isolate) {
14382  byte* sequence = FindCodeAgeSequence();
14383  if (sequence != NULL) {
14384    PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
14385                         NO_MARKING_PARITY);
14386  }
14387}
14388
14389
14390void Code::MakeOlder(MarkingParity current_parity) {
14391  byte* sequence = FindCodeAgeSequence();
14392  if (sequence != NULL) {
14393    Age age;
14394    MarkingParity code_parity;
14395    Isolate* isolate = GetIsolate();
14396    GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
14397    Age next_age = NextAge(age);
14398    if (age != next_age && code_parity != current_parity) {
14399      PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
14400    }
14401  }
14402}
14403
14404
14405bool Code::IsOld() {
14406  return IsOldAge(GetAge());
14407}
14408
14409
14410byte* Code::FindCodeAgeSequence() {
14411  return FLAG_age_code &&
14412      prologue_offset() != Code::kPrologueOffsetNotSet &&
14413      (kind() == OPTIMIZED_FUNCTION ||
14414       (kind() == FUNCTION && !has_debug_break_slots()))
14415      ? instruction_start() + prologue_offset()
14416      : NULL;
14417}
14418
14419
14420Code::Age Code::GetAge() {
14421  byte* sequence = FindCodeAgeSequence();
14422  if (sequence == NULL) {
14423    return kNoAgeCodeAge;
14424  }
14425  Age age;
14426  MarkingParity parity;
14427  GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
14428  return age;
14429}
14430
14431
14432void Code::GetCodeAgeAndParity(Code* code, Age* age,
14433                               MarkingParity* parity) {
14434  Isolate* isolate = code->GetIsolate();
14435  Builtins* builtins = isolate->builtins();
14436  Code* stub = NULL;
14437#define HANDLE_CODE_AGE(AGE)                                            \
14438  stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
14439  if (code == stub) {                                                   \
14440    *age = k##AGE##CodeAge;                                             \
14441    *parity = EVEN_MARKING_PARITY;                                      \
14442    return;                                                             \
14443  }                                                                     \
14444  stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
14445  if (code == stub) {                                                   \
14446    *age = k##AGE##CodeAge;                                             \
14447    *parity = ODD_MARKING_PARITY;                                       \
14448    return;                                                             \
14449  }
14450  CODE_AGE_LIST(HANDLE_CODE_AGE)
14451#undef HANDLE_CODE_AGE
14452  stub = *builtins->MarkCodeAsExecutedOnce();
14453  if (code == stub) {
14454    *age = kNotExecutedCodeAge;
14455    *parity = NO_MARKING_PARITY;
14456    return;
14457  }
14458  stub = *builtins->MarkCodeAsExecutedTwice();
14459  if (code == stub) {
14460    *age = kExecutedOnceCodeAge;
14461    *parity = NO_MARKING_PARITY;
14462    return;
14463  }
14464  stub = *builtins->MarkCodeAsToBeExecutedOnce();
14465  if (code == stub) {
14466    *age = kToBeExecutedOnceCodeAge;
14467    *parity = NO_MARKING_PARITY;
14468    return;
14469  }
14470  UNREACHABLE();
14471}
14472
14473
14474Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
14475  Builtins* builtins = isolate->builtins();
14476  switch (age) {
14477#define HANDLE_CODE_AGE(AGE)                                            \
14478    case k##AGE##CodeAge: {                                             \
14479      Code* stub = parity == EVEN_MARKING_PARITY                        \
14480          ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
14481          : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
14482      return stub;                                                      \
14483    }
14484    CODE_AGE_LIST(HANDLE_CODE_AGE)
14485#undef HANDLE_CODE_AGE
14486    case kNotExecutedCodeAge: {
14487      DCHECK(parity == NO_MARKING_PARITY);
14488      return *builtins->MarkCodeAsExecutedOnce();
14489    }
14490    case kExecutedOnceCodeAge: {
14491      DCHECK(parity == NO_MARKING_PARITY);
14492      return *builtins->MarkCodeAsExecutedTwice();
14493    }
14494    case kToBeExecutedOnceCodeAge: {
14495      DCHECK(parity == NO_MARKING_PARITY);
14496      return *builtins->MarkCodeAsToBeExecutedOnce();
14497    }
14498    default:
14499      UNREACHABLE();
14500      break;
14501  }
14502  return NULL;
14503}
14504
14505
14506void Code::PrintDeoptLocation(FILE* out, Address pc) {
14507  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
14508  class SourcePosition pos = info.position;
14509  if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
14510    if (FLAG_hydrogen_track_positions) {
14511      PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
14512             pos.inlining_id(), pos.position(),
14513             Deoptimizer::GetDeoptReason(info.deopt_reason));
14514    } else {
14515      PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
14516             Deoptimizer::GetDeoptReason(info.deopt_reason));
14517    }
14518  }
14519}
14520
14521
14522bool Code::CanDeoptAt(Address pc) {
14523  DeoptimizationInputData* deopt_data =
14524      DeoptimizationInputData::cast(deoptimization_data());
14525  Address code_start_address = instruction_start();
14526  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
14527    if (deopt_data->Pc(i)->value() == -1) continue;
14528    Address address = code_start_address + deopt_data->Pc(i)->value();
14529    if (address == pc) return true;
14530  }
14531  return false;
14532}
14533
14534
14535// Identify kind of code.
14536const char* Code::Kind2String(Kind kind) {
14537  switch (kind) {
14538#define CASE(name) case name: return #name;
14539    CODE_KIND_LIST(CASE)
14540#undef CASE
14541    case NUMBER_OF_KINDS: break;
14542  }
14543  UNREACHABLE();
14544  return NULL;
14545}
14546
14547
14548Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
14549  DCHECK(code->kind() == OPTIMIZED_FUNCTION);
14550  WeakCell* raw_cell = code->CachedWeakCell();
14551  if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
14552  Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
14553  DeoptimizationInputData::cast(code->deoptimization_data())
14554      ->SetWeakCellCache(*cell);
14555  return cell;
14556}
14557
14558
14559WeakCell* Code::CachedWeakCell() {
14560  DCHECK(kind() == OPTIMIZED_FUNCTION);
14561  Object* weak_cell_cache =
14562      DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
14563  if (weak_cell_cache->IsWeakCell()) {
14564    DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
14565    return WeakCell::cast(weak_cell_cache);
14566  }
14567  return NULL;
14568}
14569
14570
14571#ifdef ENABLE_DISASSEMBLER
14572
14573void DeoptimizationInputData::DeoptimizationInputDataPrint(
14574    std::ostream& os) {  // NOLINT
14575  disasm::NameConverter converter;
14576  int const inlined_function_count = InlinedFunctionCount()->value();
14577  os << "Inlined functions (count = " << inlined_function_count << ")\n";
14578  for (int id = 0; id < inlined_function_count; ++id) {
14579    Object* info = LiteralArray()->get(id);
14580    os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
14581  }
14582  os << "\n";
14583  int deopt_count = DeoptCount();
14584  os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
14585  if (0 != deopt_count) {
14586    os << " index  ast id    argc     pc";
14587    if (FLAG_print_code_verbose) os << "  commands";
14588    os << "\n";
14589  }
14590  for (int i = 0; i < deopt_count; i++) {
14591    os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
14592       << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
14593       << std::setw(6) << Pc(i)->value();
14594
14595    if (!FLAG_print_code_verbose) {
14596      os << "\n";
14597      continue;
14598    }
14599    // Print details of the frame translation.
14600    int translation_index = TranslationIndex(i)->value();
14601    TranslationIterator iterator(TranslationByteArray(), translation_index);
14602    Translation::Opcode opcode =
14603        static_cast<Translation::Opcode>(iterator.Next());
14604    DCHECK(Translation::BEGIN == opcode);
14605    int frame_count = iterator.Next();
14606    int jsframe_count = iterator.Next();
14607    os << "  " << Translation::StringFor(opcode)
14608       << " {frame count=" << frame_count
14609       << ", js frame count=" << jsframe_count << "}\n";
14610
14611    while (iterator.HasNext() &&
14612           Translation::BEGIN !=
14613           (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
14614      os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
14615
14616      switch (opcode) {
14617        case Translation::BEGIN:
14618          UNREACHABLE();
14619          break;
14620
14621        case Translation::JS_FRAME: {
14622          int ast_id = iterator.Next();
14623          int shared_info_id = iterator.Next();
14624          unsigned height = iterator.Next();
14625          Object* shared_info = LiteralArray()->get(shared_info_id);
14626          os << "{ast_id=" << ast_id << ", function="
14627             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14628             << ", height=" << height << "}";
14629          break;
14630        }
14631
14632        case Translation::INTERPRETED_FRAME: {
14633          int bytecode_offset = iterator.Next();
14634          int shared_info_id = iterator.Next();
14635          unsigned height = iterator.Next();
14636          Object* shared_info = LiteralArray()->get(shared_info_id);
14637          os << "{bytecode_offset=" << bytecode_offset << ", function="
14638             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14639             << ", height=" << height << "}";
14640          break;
14641        }
14642
14643        case Translation::JS_FRAME_FUNCTION: {
14644          os << "{function}";
14645          break;
14646        }
14647
14648        case Translation::COMPILED_STUB_FRAME: {
14649          Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
14650          os << "{kind=" << stub_kind << "}";
14651          break;
14652        }
14653
14654        case Translation::ARGUMENTS_ADAPTOR_FRAME:
14655        case Translation::CONSTRUCT_STUB_FRAME: {
14656          int shared_info_id = iterator.Next();
14657          Object* shared_info = LiteralArray()->get(shared_info_id);
14658          unsigned height = iterator.Next();
14659          os << "{function="
14660             << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
14661             << ", height=" << height << "}";
14662          break;
14663        }
14664
14665        case Translation::GETTER_STUB_FRAME:
14666        case Translation::SETTER_STUB_FRAME: {
14667          int shared_info_id = iterator.Next();
14668          Object* shared_info = LiteralArray()->get(shared_info_id);
14669          os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
14670                                          ->DebugName()) << "}";
14671          break;
14672        }
14673
14674        case Translation::REGISTER: {
14675          int reg_code = iterator.Next();
14676          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
14677          break;
14678        }
14679
14680        case Translation::INT32_REGISTER: {
14681          int reg_code = iterator.Next();
14682          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
14683          break;
14684        }
14685
14686        case Translation::UINT32_REGISTER: {
14687          int reg_code = iterator.Next();
14688          os << "{input=" << converter.NameOfCPURegister(reg_code)
14689             << " (unsigned)}";
14690          break;
14691        }
14692
14693        case Translation::BOOL_REGISTER: {
14694          int reg_code = iterator.Next();
14695          os << "{input=" << converter.NameOfCPURegister(reg_code)
14696             << " (bool)}";
14697          break;
14698        }
14699
14700        case Translation::DOUBLE_REGISTER: {
14701          int reg_code = iterator.Next();
14702          os << "{input=" << DoubleRegister::from_code(reg_code).ToString()
14703             << "}";
14704          break;
14705        }
14706
14707        case Translation::STACK_SLOT: {
14708          int input_slot_index = iterator.Next();
14709          os << "{input=" << input_slot_index << "}";
14710          break;
14711        }
14712
14713        case Translation::INT32_STACK_SLOT: {
14714          int input_slot_index = iterator.Next();
14715          os << "{input=" << input_slot_index << "}";
14716          break;
14717        }
14718
14719        case Translation::UINT32_STACK_SLOT: {
14720          int input_slot_index = iterator.Next();
14721          os << "{input=" << input_slot_index << " (unsigned)}";
14722          break;
14723        }
14724
14725        case Translation::BOOL_STACK_SLOT: {
14726          int input_slot_index = iterator.Next();
14727          os << "{input=" << input_slot_index << " (bool)}";
14728          break;
14729        }
14730
14731        case Translation::DOUBLE_STACK_SLOT: {
14732          int input_slot_index = iterator.Next();
14733          os << "{input=" << input_slot_index << "}";
14734          break;
14735        }
14736
14737        case Translation::LITERAL: {
14738          int literal_index = iterator.Next();
14739          Object* literal_value = LiteralArray()->get(literal_index);
14740          os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
14741             << ")}";
14742          break;
14743        }
14744
14745        case Translation::DUPLICATED_OBJECT: {
14746          int object_index = iterator.Next();
14747          os << "{object_index=" << object_index << "}";
14748          break;
14749        }
14750
14751        case Translation::ARGUMENTS_OBJECT:
14752        case Translation::CAPTURED_OBJECT: {
14753          int args_length = iterator.Next();
14754          os << "{length=" << args_length << "}";
14755          break;
14756        }
14757      }
14758      os << "\n";
14759    }
14760  }
14761}
14762
14763
14764void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
14765    std::ostream& os) {  // NOLINT
14766  os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
14767     << ")\n";
14768  if (this->DeoptPoints() == 0) return;
14769
14770  os << "ast id        pc  state\n";
14771  for (int i = 0; i < this->DeoptPoints(); i++) {
14772    int pc_and_state = this->PcAndState(i)->value();
14773    os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
14774       << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
14775       << FullCodeGenerator::State2String(
14776              FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
14777  }
14778}
14779
14780
14781void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
14782  os << "   from   to       hdlr\n";
14783  for (int i = 0; i < length(); i += kRangeEntrySize) {
14784    int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
14785    int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
14786    int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
14787    int handler_offset = HandlerOffsetField::decode(handler_field);
14788    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
14789    int depth = Smi::cast(get(i + kRangeDepthIndex))->value();
14790    os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
14791       << ")  ->  " << std::setw(4) << handler_offset
14792       << " (prediction=" << prediction << ", depth=" << depth << ")\n";
14793  }
14794}
14795
14796
14797void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
14798  os << "   off      hdlr (c)\n";
14799  for (int i = 0; i < length(); i += kReturnEntrySize) {
14800    int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
14801    int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
14802    int handler_offset = HandlerOffsetField::decode(handler_field);
14803    CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
14804    os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
14805       << handler_offset << " (prediction=" << prediction << ")\n";
14806  }
14807}
14808
14809
14810const char* Code::ICState2String(InlineCacheState state) {
14811  switch (state) {
14812    case UNINITIALIZED: return "UNINITIALIZED";
14813    case PREMONOMORPHIC: return "PREMONOMORPHIC";
14814    case MONOMORPHIC: return "MONOMORPHIC";
14815    case PROTOTYPE_FAILURE:
14816      return "PROTOTYPE_FAILURE";
14817    case POLYMORPHIC: return "POLYMORPHIC";
14818    case MEGAMORPHIC: return "MEGAMORPHIC";
14819    case GENERIC: return "GENERIC";
14820    case DEBUG_STUB: return "DEBUG_STUB";
14821  }
14822  UNREACHABLE();
14823  return NULL;
14824}
14825
14826
14827const char* Code::StubType2String(StubType type) {
14828  switch (type) {
14829    case NORMAL: return "NORMAL";
14830    case FAST: return "FAST";
14831  }
14832  UNREACHABLE();  // keep the compiler happy
14833  return NULL;
14834}
14835
14836
14837void Code::PrintExtraICState(std::ostream& os,  // NOLINT
14838                             Kind kind, ExtraICState extra) {
14839  os << "extra_ic_state = ";
14840  if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
14841      is_strict(static_cast<LanguageMode>(extra))) {
14842    os << "STRICT\n";
14843  } else {
14844    os << extra << "\n";
14845  }
14846}
14847
14848
14849void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
14850  os << "kind = " << Kind2String(kind()) << "\n";
14851  if (IsCodeStubOrIC()) {
14852    const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
14853    os << "major_key = " << (n == NULL ? "null" : n) << "\n";
14854  }
14855  if (is_inline_cache_stub()) {
14856    os << "ic_state = " << ICState2String(ic_state()) << "\n";
14857    PrintExtraICState(os, kind(), extra_ic_state());
14858    if (ic_state() == MONOMORPHIC) {
14859      os << "type = " << StubType2String(type()) << "\n";
14860    }
14861    if (is_compare_ic_stub()) {
14862      DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
14863      CompareICStub stub(stub_key(), GetIsolate());
14864      os << "compare_state = " << CompareICState::GetStateName(stub.left())
14865         << "*" << CompareICState::GetStateName(stub.right()) << " -> "
14866         << CompareICState::GetStateName(stub.state()) << "\n";
14867      os << "compare_operation = " << Token::Name(stub.op()) << "\n";
14868    }
14869  }
14870  if ((name != NULL) && (name[0] != '\0')) {
14871    os << "name = " << name << "\n";
14872  } else if (kind() == BUILTIN) {
14873    name = GetIsolate()->builtins()->Lookup(instruction_start());
14874    if (name != NULL) {
14875      os << "name = " << name << "\n";
14876    }
14877  }
14878  if (kind() == OPTIMIZED_FUNCTION) {
14879    os << "stack_slots = " << stack_slots() << "\n";
14880  }
14881  os << "compiler = " << (is_turbofanned()
14882                              ? "turbofan"
14883                              : is_crankshafted() ? "crankshaft"
14884                                                  : kind() == Code::FUNCTION
14885                                                        ? "full-codegen"
14886                                                        : "unknown") << "\n";
14887
14888  os << "Instructions (size = " << instruction_size() << ")\n";
14889  {
14890    Isolate* isolate = GetIsolate();
14891    int size = instruction_size();
14892    int safepoint_offset =
14893        is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
14894    int back_edge_offset = (kind() == Code::FUNCTION)
14895                               ? static_cast<int>(back_edge_table_offset())
14896                               : size;
14897    int constant_pool_offset = FLAG_enable_embedded_constant_pool
14898                                   ? this->constant_pool_offset()
14899                                   : size;
14900
14901    // Stop before reaching any embedded tables
14902    int code_size = Min(safepoint_offset, back_edge_offset);
14903    code_size = Min(code_size, constant_pool_offset);
14904    byte* begin = instruction_start();
14905    byte* end = begin + code_size;
14906    Disassembler::Decode(isolate, &os, begin, end, this);
14907
14908    if (constant_pool_offset < size) {
14909      int constant_pool_size = size - constant_pool_offset;
14910      DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
14911      os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
14912      Vector<char> buf = Vector<char>::New(50);
14913      intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
14914      for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
14915        SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
14916        os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
14917      }
14918    }
14919  }
14920  os << "\n";
14921
14922  if (kind() == FUNCTION) {
14923    DeoptimizationOutputData* data =
14924        DeoptimizationOutputData::cast(this->deoptimization_data());
14925    data->DeoptimizationOutputDataPrint(os);
14926  } else if (kind() == OPTIMIZED_FUNCTION) {
14927    DeoptimizationInputData* data =
14928        DeoptimizationInputData::cast(this->deoptimization_data());
14929    data->DeoptimizationInputDataPrint(os);
14930  }
14931  os << "\n";
14932
14933  if (is_crankshafted()) {
14934    SafepointTable table(this);
14935    os << "Safepoints (size = " << table.size() << ")\n";
14936    for (unsigned i = 0; i < table.length(); i++) {
14937      unsigned pc_offset = table.GetPcOffset(i);
14938      os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
14939      os << std::setw(4) << pc_offset << "  ";
14940      table.PrintEntry(i, os);
14941      os << " (sp -> fp)  ";
14942      SafepointEntry entry = table.GetEntry(i);
14943      if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
14944        os << std::setw(6) << entry.deoptimization_index();
14945      } else {
14946        os << "<none>";
14947      }
14948      if (entry.argument_count() > 0) {
14949        os << " argc: " << entry.argument_count();
14950      }
14951      os << "\n";
14952    }
14953    os << "\n";
14954  } else if (kind() == FUNCTION) {
14955    unsigned offset = back_edge_table_offset();
14956    // If there is no back edge table, the "table start" will be at or after
14957    // (due to alignment) the end of the instruction stream.
14958    if (static_cast<int>(offset) < instruction_size()) {
14959      DisallowHeapAllocation no_gc;
14960      BackEdgeTable back_edges(this, &no_gc);
14961
14962      os << "Back edges (size = " << back_edges.length() << ")\n";
14963      os << "ast_id  pc_offset  loop_depth\n";
14964
14965      for (uint32_t i = 0; i < back_edges.length(); i++) {
14966        os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
14967           << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
14968           << back_edges.loop_depth(i) << "\n";
14969      }
14970
14971      os << "\n";
14972    }
14973#ifdef OBJECT_PRINT
14974    if (!type_feedback_info()->IsUndefined()) {
14975      OFStream os(stdout);
14976      TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
14977      os << "\n";
14978    }
14979#endif
14980  }
14981
14982  if (handler_table()->length() > 0) {
14983    os << "Handler Table (size = " << handler_table()->Size() << ")\n";
14984    if (kind() == FUNCTION) {
14985      HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
14986    } else if (kind() == OPTIMIZED_FUNCTION) {
14987      HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
14988    }
14989    os << "\n";
14990  }
14991
14992  os << "RelocInfo (size = " << relocation_size() << ")\n";
14993  for (RelocIterator it(this); !it.done(); it.next()) {
14994    it.rinfo()->Print(GetIsolate(), os);
14995  }
14996  os << "\n";
14997}
14998#endif  // ENABLE_DISASSEMBLER
14999
15000
15001void BytecodeArray::Disassemble(std::ostream& os) {
15002  os << "Parameter count " << parameter_count() << "\n";
15003  os << "Frame size " << frame_size() << "\n";
15004  Vector<char> buf = Vector<char>::New(50);
15005
15006  const uint8_t* first_bytecode_address = GetFirstBytecodeAddress();
15007  int bytecode_size = 0;
15008  for (int i = 0; i < this->length(); i += bytecode_size) {
15009    const uint8_t* bytecode_start = &first_bytecode_address[i];
15010    interpreter::Bytecode bytecode =
15011        interpreter::Bytecodes::FromByte(bytecode_start[0]);
15012    bytecode_size = interpreter::Bytecodes::Size(bytecode);
15013
15014    SNPrintF(buf, "%p", bytecode_start);
15015    os << buf.start() << " : ";
15016    interpreter::Bytecodes::Decode(os, bytecode_start, parameter_count());
15017
15018    if (interpreter::Bytecodes::IsJumpConstantWide(bytecode)) {
15019      DCHECK_EQ(bytecode_size, 3);
15020      int index = static_cast<int>(ReadUnalignedUInt16(bytecode_start + 1));
15021      int offset = Smi::cast(constant_pool()->get(index))->value();
15022      SNPrintF(buf, " (%p)", bytecode_start + offset);
15023      os << buf.start();
15024    } else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) {
15025      DCHECK_EQ(bytecode_size, 2);
15026      int index = static_cast<int>(bytecode_start[1]);
15027      int offset = Smi::cast(constant_pool()->get(index))->value();
15028      SNPrintF(buf, " (%p)", bytecode_start + offset);
15029      os << buf.start();
15030    } else if (interpreter::Bytecodes::IsJump(bytecode)) {
15031      DCHECK_EQ(bytecode_size, 2);
15032      int offset = static_cast<int8_t>(bytecode_start[1]);
15033      SNPrintF(buf, " (%p)", bytecode_start + offset);
15034      os << buf.start();
15035    }
15036    os << "\n";
15037  }
15038
15039  os << "Constant pool (size = " << constant_pool()->length() << ")\n";
15040  constant_pool()->Print();
15041}
15042
15043
15044// static
15045void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
15046  DCHECK(capacity >= 0);
15047  array->GetIsolate()->factory()->NewJSArrayStorage(
15048      array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
15049}
15050
15051
15052// Returns false if the passed-in index is marked non-configurable, which will
15053// cause the truncation operation to halt, and thus no further old values need
15054// be collected.
15055static bool GetOldValue(Isolate* isolate,
15056                        Handle<JSObject> object,
15057                        uint32_t index,
15058                        List<Handle<Object> >* old_values,
15059                        List<uint32_t>* indices) {
15060  LookupIterator it(isolate, object, index, LookupIterator::HIDDEN);
15061  CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
15062  DCHECK(it.IsFound());
15063  if (!it.IsConfigurable()) return false;
15064  Handle<Object> value =
15065      it.state() == LookupIterator::ACCESSOR
15066          ? Handle<Object>::cast(isolate->factory()->the_hole_value())
15067          : JSReceiver::GetDataProperty(&it);
15068  old_values->Add(value);
15069  indices->Add(index);
15070  return true;
15071}
15072
15073
15074void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
15075  // We should never end in here with a pixel or external array.
15076  DCHECK(array->AllowsSetLength());
15077  if (array->SetLengthWouldNormalize(new_length)) {
15078    JSObject::NormalizeElements(array);
15079  }
15080  array->GetElementsAccessor()->SetLength(array, new_length);
15081}
15082
15083
15084MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
15085                                                 uint32_t new_length) {
15086  if (!array->map()->is_observed()) {
15087    SetLength(array, new_length);
15088    return array;
15089  }
15090
15091  Isolate* isolate = array->GetIsolate();
15092  List<uint32_t> indices;
15093  List<Handle<Object> > old_values;
15094  Handle<Object> old_length_handle(array->length(), isolate);
15095  uint32_t old_length = 0;
15096  CHECK(old_length_handle->ToArrayLength(&old_length));
15097
15098  int num_elements = array->NumberOfOwnElements(ALL_PROPERTIES);
15099  if (num_elements > 0) {
15100    if (old_length == static_cast<uint32_t>(num_elements)) {
15101      // Simple case for arrays without holes.
15102      for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
15103        if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
15104      }
15105    } else {
15106      // For sparse arrays, only iterate over existing elements.
15107      // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
15108      // the to-be-removed indices twice.
15109      Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
15110      array->GetOwnElementKeys(*keys, ALL_PROPERTIES);
15111      while (num_elements-- > 0) {
15112        uint32_t index = NumberToUint32(keys->get(num_elements));
15113        if (index < new_length) break;
15114        if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
15115      }
15116    }
15117  }
15118
15119  SetLength(array, new_length);
15120
15121  CHECK(array->length()->ToArrayLength(&new_length));
15122  if (old_length == new_length) return array;
15123
15124  RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
15125
15126  for (int i = 0; i < indices.length(); ++i) {
15127    // For deletions where the property was an accessor, old_values[i]
15128    // will be the hole, which instructs EnqueueChangeRecord to elide
15129    // the "oldValue" property.
15130    RETURN_ON_EXCEPTION(
15131        isolate,
15132        JSObject::EnqueueChangeRecord(
15133            array, "delete", isolate->factory()->Uint32ToString(indices[i]),
15134            old_values[i]),
15135        Object);
15136  }
15137
15138  RETURN_ON_EXCEPTION(isolate,
15139                      JSObject::EnqueueChangeRecord(
15140                          array, "update", isolate->factory()->length_string(),
15141                          old_length_handle),
15142                      Object);
15143
15144  RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
15145
15146  uint32_t index = Min(old_length, new_length);
15147  uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
15148  uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
15149  Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
15150  if (delete_count > 0) {
15151    for (int i = indices.length() - 1; i >= 0; i--) {
15152      // Skip deletions where the property was an accessor, leaving holes
15153      // in the array of old values.
15154      if (old_values[i]->IsTheHole()) continue;
15155      JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
15156          .Assert();
15157    }
15158
15159    JSArray::SetLength(deleted, delete_count);
15160  }
15161
15162  RETURN_ON_EXCEPTION(
15163      isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
15164
15165  return array;
15166}
15167
15168
15169// static
15170void Map::AddDependentCode(Handle<Map> map,
15171                           DependentCode::DependencyGroup group,
15172                           Handle<Code> code) {
15173  Handle<WeakCell> cell = Code::WeakCellFor(code);
15174  Handle<DependentCode> codes = DependentCode::InsertWeakCode(
15175      Handle<DependentCode>(map->dependent_code()), group, cell);
15176  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
15177}
15178
15179
15180Handle<DependentCode> DependentCode::InsertCompilationDependencies(
15181    Handle<DependentCode> entries, DependencyGroup group,
15182    Handle<Foreign> info) {
15183  return Insert(entries, group, info);
15184}
15185
15186
15187Handle<DependentCode> DependentCode::InsertWeakCode(
15188    Handle<DependentCode> entries, DependencyGroup group,
15189    Handle<WeakCell> code_cell) {
15190  return Insert(entries, group, code_cell);
15191}
15192
15193
15194Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
15195                                            DependencyGroup group,
15196                                            Handle<Object> object) {
15197  if (entries->length() == 0 || entries->group() > group) {
15198    // There is no such group.
15199    return DependentCode::New(group, object, entries);
15200  }
15201  if (entries->group() < group) {
15202    // The group comes later in the list.
15203    Handle<DependentCode> old_next(entries->next_link());
15204    Handle<DependentCode> new_next = Insert(old_next, group, object);
15205    if (!old_next.is_identical_to(new_next)) {
15206      entries->set_next_link(*new_next);
15207    }
15208    return entries;
15209  }
15210  DCHECK_EQ(group, entries->group());
15211  int count = entries->count();
15212  // Check for existing entry to avoid duplicates.
15213  for (int i = 0; i < count; i++) {
15214    if (entries->object_at(i) == *object) return entries;
15215  }
15216  if (entries->length() < kCodesStartIndex + count + 1) {
15217    entries = EnsureSpace(entries);
15218    // Count could have changed, reload it.
15219    count = entries->count();
15220  }
15221  entries->set_object_at(count, *object);
15222  entries->set_count(count + 1);
15223  return entries;
15224}
15225
15226
15227Handle<DependentCode> DependentCode::New(DependencyGroup group,
15228                                         Handle<Object> object,
15229                                         Handle<DependentCode> next) {
15230  Isolate* isolate = next->GetIsolate();
15231  Handle<DependentCode> result = Handle<DependentCode>::cast(
15232      isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED));
15233  result->set_next_link(*next);
15234  result->set_flags(GroupField::encode(group) | CountField::encode(1));
15235  result->set_object_at(0, *object);
15236  return result;
15237}
15238
15239
15240Handle<DependentCode> DependentCode::EnsureSpace(
15241    Handle<DependentCode> entries) {
15242  if (entries->Compact()) return entries;
15243  Isolate* isolate = entries->GetIsolate();
15244  int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
15245  int grow_by = capacity - entries->length();
15246  return Handle<DependentCode>::cast(
15247      isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED));
15248}
15249
15250
15251bool DependentCode::Compact() {
15252  int old_count = count();
15253  int new_count = 0;
15254  for (int i = 0; i < old_count; i++) {
15255    Object* obj = object_at(i);
15256    if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
15257      if (i != new_count) {
15258        copy(i, new_count);
15259      }
15260      new_count++;
15261    }
15262  }
15263  set_count(new_count);
15264  for (int i = new_count; i < old_count; i++) {
15265    clear_at(i);
15266  }
15267  return new_count < old_count;
15268}
15269
15270
15271void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
15272                                         WeakCell* code_cell) {
15273  if (this->length() == 0 || this->group() > group) {
15274    // There is no such group.
15275    return;
15276  }
15277  if (this->group() < group) {
15278    // The group comes later in the list.
15279    next_link()->UpdateToFinishedCode(group, info, code_cell);
15280    return;
15281  }
15282  DCHECK_EQ(group, this->group());
15283  DisallowHeapAllocation no_gc;
15284  int count = this->count();
15285  for (int i = 0; i < count; i++) {
15286    if (object_at(i) == info) {
15287      set_object_at(i, code_cell);
15288      break;
15289    }
15290  }
15291#ifdef DEBUG
15292  for (int i = 0; i < count; i++) {
15293    DCHECK(object_at(i) != info);
15294  }
15295#endif
15296}
15297
15298
15299void DependentCode::RemoveCompilationDependencies(
15300    DependentCode::DependencyGroup group, Foreign* info) {
15301  if (this->length() == 0 || this->group() > group) {
15302    // There is no such group.
15303    return;
15304  }
15305  if (this->group() < group) {
15306    // The group comes later in the list.
15307    next_link()->RemoveCompilationDependencies(group, info);
15308    return;
15309  }
15310  DCHECK_EQ(group, this->group());
15311  DisallowHeapAllocation no_allocation;
15312  int old_count = count();
15313  // Find compilation info wrapper.
15314  int info_pos = -1;
15315  for (int i = 0; i < old_count; i++) {
15316    if (object_at(i) == info) {
15317      info_pos = i;
15318      break;
15319    }
15320  }
15321  if (info_pos == -1) return;  // Not found.
15322  // Use the last code to fill the gap.
15323  if (info_pos < old_count - 1) {
15324    copy(old_count - 1, info_pos);
15325  }
15326  clear_at(old_count - 1);
15327  set_count(old_count - 1);
15328
15329#ifdef DEBUG
15330  for (int i = 0; i < old_count - 1; i++) {
15331    DCHECK(object_at(i) != info);
15332  }
15333#endif
15334}
15335
15336
15337bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
15338  if (this->length() == 0 || this->group() > group) {
15339    // There is no such group.
15340    return false;
15341  }
15342  if (this->group() < group) {
15343    // The group comes later in the list.
15344    return next_link()->Contains(group, code_cell);
15345  }
15346  DCHECK_EQ(group, this->group());
15347  int count = this->count();
15348  for (int i = 0; i < count; i++) {
15349    if (object_at(i) == code_cell) return true;
15350  }
15351  return false;
15352}
15353
15354
15355bool DependentCode::IsEmpty(DependencyGroup group) {
15356  if (this->length() == 0 || this->group() > group) {
15357    // There is no such group.
15358    return true;
15359  }
15360  if (this->group() < group) {
15361    // The group comes later in the list.
15362    return next_link()->IsEmpty(group);
15363  }
15364  DCHECK_EQ(group, this->group());
15365  return count() == 0;
15366}
15367
15368
15369bool DependentCode::MarkCodeForDeoptimization(
15370    Isolate* isolate,
15371    DependentCode::DependencyGroup group) {
15372  if (this->length() == 0 || this->group() > group) {
15373    // There is no such group.
15374    return false;
15375  }
15376  if (this->group() < group) {
15377    // The group comes later in the list.
15378    return next_link()->MarkCodeForDeoptimization(isolate, group);
15379  }
15380  DCHECK_EQ(group, this->group());
15381  DisallowHeapAllocation no_allocation_scope;
15382  // Mark all the code that needs to be deoptimized.
15383  bool marked = false;
15384  bool invalidate_embedded_objects = group == kWeakCodeGroup;
15385  int count = this->count();
15386  for (int i = 0; i < count; i++) {
15387    Object* obj = object_at(i);
15388    if (obj->IsWeakCell()) {
15389      WeakCell* cell = WeakCell::cast(obj);
15390      if (cell->cleared()) continue;
15391      Code* code = Code::cast(cell->value());
15392      if (!code->marked_for_deoptimization()) {
15393        SetMarkedForDeoptimization(code, group);
15394        if (invalidate_embedded_objects) {
15395          code->InvalidateEmbeddedObjects();
15396        }
15397        marked = true;
15398      }
15399    } else {
15400      DCHECK(obj->IsForeign());
15401      CompilationDependencies* info =
15402          reinterpret_cast<CompilationDependencies*>(
15403              Foreign::cast(obj)->foreign_address());
15404      info->Abort();
15405    }
15406  }
15407  for (int i = 0; i < count; i++) {
15408    clear_at(i);
15409  }
15410  set_count(0);
15411  return marked;
15412}
15413
15414
15415void DependentCode::DeoptimizeDependentCodeGroup(
15416    Isolate* isolate,
15417    DependentCode::DependencyGroup group) {
15418  DCHECK(AllowCodeDependencyChange::IsAllowed());
15419  DisallowHeapAllocation no_allocation_scope;
15420  bool marked = MarkCodeForDeoptimization(isolate, group);
15421  if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
15422}
15423
15424
15425void DependentCode::SetMarkedForDeoptimization(Code* code,
15426                                               DependencyGroup group) {
15427  code->set_marked_for_deoptimization(true);
15428  if (FLAG_trace_deopt &&
15429      (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
15430    DeoptimizationInputData* deopt_data =
15431        DeoptimizationInputData::cast(code->deoptimization_data());
15432    CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
15433    PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
15434                         " (opt #%d) for deoptimization, reason: %s]\n",
15435           reinterpret_cast<intptr_t>(code),
15436           deopt_data->OptimizationId()->value(), DependencyGroupName(group));
15437  }
15438}
15439
15440
15441const char* DependentCode::DependencyGroupName(DependencyGroup group) {
15442  switch (group) {
15443    case kWeakCodeGroup:
15444      return "weak-code";
15445    case kTransitionGroup:
15446      return "transition";
15447    case kPrototypeCheckGroup:
15448      return "prototype-check";
15449    case kPropertyCellChangedGroup:
15450      return "property-cell-changed";
15451    case kFieldTypeGroup:
15452      return "field-type";
15453    case kInitialMapChangedGroup:
15454      return "initial-map-changed";
15455    case kAllocationSiteTenuringChangedGroup:
15456      return "allocation-site-tenuring-changed";
15457    case kAllocationSiteTransitionChangedGroup:
15458      return "allocation-site-transition-changed";
15459  }
15460  UNREACHABLE();
15461  return "?";
15462}
15463
15464
15465Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
15466                                       Handle<Object> prototype,
15467                                       PrototypeOptimizationMode mode) {
15468  Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
15469  if (new_map.is_null()) {
15470    new_map = Copy(map, "TransitionToPrototype");
15471    TransitionArray::PutPrototypeTransition(map, prototype, new_map);
15472    Map::SetPrototype(new_map, prototype, mode);
15473  }
15474  return new_map;
15475}
15476
15477
15478Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
15479                                     Handle<Object> value, bool from_javascript,
15480                                     ShouldThrow should_throw) {
15481  if (object->IsJSProxy()) {
15482    return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
15483                                 from_javascript, should_throw);
15484  }
15485  return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
15486                                from_javascript, should_throw);
15487}
15488
15489
15490// ES6: 9.5.2 [[SetPrototypeOf]] (V)
15491// static
15492Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
15493                                  bool from_javascript,
15494                                  ShouldThrow should_throw) {
15495  Isolate* isolate = proxy->GetIsolate();
15496  STACK_CHECK(Nothing<bool>());
15497  Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
15498  // 1. Assert: Either Type(V) is Object or Type(V) is Null.
15499  DCHECK(value->IsJSReceiver() || value->IsNull());
15500  // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
15501  Handle<Object> handler(proxy->handler(), isolate);
15502  // 3. If handler is null, throw a TypeError exception.
15503  // 4. Assert: Type(handler) is Object.
15504  if (proxy->IsRevoked()) {
15505    isolate->Throw(*isolate->factory()->NewTypeError(
15506        MessageTemplate::kProxyRevoked, trap_name));
15507    return Nothing<bool>();
15508  }
15509  // 5. Let target be the value of the [[ProxyTarget]] internal slot.
15510  Handle<JSReceiver> target(proxy->target(), isolate);
15511  // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
15512  Handle<Object> trap;
15513  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15514      isolate, trap,
15515      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
15516      Nothing<bool>());
15517  // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
15518  if (trap->IsUndefined()) {
15519    return JSReceiver::SetPrototype(target, value, from_javascript,
15520                                    should_throw);
15521  }
15522  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)).
15523  Handle<Object> argv[] = {target, value};
15524  Handle<Object> trap_result;
15525  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
15526      isolate, trap_result,
15527      Execution::Call(isolate, trap, handler, arraysize(argv), argv),
15528      Nothing<bool>());
15529  bool bool_trap_result = trap_result->BooleanValue();
15530  // 9. Let extensibleTarget be ? IsExtensible(target).
15531  Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
15532  if (is_extensible.IsNothing()) return Nothing<bool>();
15533  // 10. If extensibleTarget is true, return booleanTrapResult.
15534  if (is_extensible.FromJust()) {
15535    if (bool_trap_result) return Just(true);
15536    RETURN_FAILURE(
15537        isolate, should_throw,
15538        NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15539  }
15540  // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
15541  Handle<Object> target_proto;
15542  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
15543                                   Object::GetPrototype(isolate, target),
15544                                   Nothing<bool>());
15545  // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false,
15546  // throw a TypeError exception.
15547  if (bool_trap_result && !value->SameValue(*target_proto)) {
15548    isolate->Throw(*isolate->factory()->NewTypeError(
15549        MessageTemplate::kProxySetPrototypeOfNonExtensible));
15550    return Nothing<bool>();
15551  }
15552  // 13. Return booleanTrapResult.
15553  if (bool_trap_result) return Just(true);
15554  RETURN_FAILURE(
15555      isolate, should_throw,
15556      NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
15557}
15558
15559
15560Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
15561                                   Handle<Object> value, bool from_javascript,
15562                                   ShouldThrow should_throw) {
15563  Isolate* isolate = object->GetIsolate();
15564
15565  const bool observed = from_javascript && object->map()->is_observed();
15566  Handle<Object> old_value;
15567  if (observed) {
15568    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value,
15569                                     Object::GetPrototype(isolate, object),
15570                                     Nothing<bool>());
15571  }
15572
15573  Maybe<bool> result =
15574      SetPrototypeUnobserved(object, value, from_javascript, should_throw);
15575  MAYBE_RETURN(result, Nothing<bool>());
15576
15577  if (result.FromJust() && observed) {
15578    Handle<Object> new_value;
15579    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value,
15580                                     Object::GetPrototype(isolate, object),
15581                                     Nothing<bool>());
15582    if (!new_value->SameValue(*old_value)) {
15583      RETURN_ON_EXCEPTION_VALUE(
15584          isolate, JSObject::EnqueueChangeRecord(
15585                       object, "setPrototype",
15586                       isolate->factory()->proto_string(), old_value),
15587          Nothing<bool>());
15588    }
15589  }
15590
15591  return result;
15592}
15593
15594
15595Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
15596                                             Handle<Object> value,
15597                                             bool from_javascript,
15598                                             ShouldThrow should_throw) {
15599#ifdef DEBUG
15600  int size = object->Size();
15601#endif
15602
15603  Isolate* isolate = object->GetIsolate();
15604
15605  if (from_javascript) {
15606    if (object->IsAccessCheckNeeded() &&
15607        !isolate->MayAccess(handle(isolate->context()), object)) {
15608      isolate->ReportFailedAccessCheck(object);
15609      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
15610      RETURN_FAILURE(isolate, should_throw,
15611                     NewTypeError(MessageTemplate::kNoAccess));
15612    }
15613  } else {
15614    DCHECK(!object->IsAccessCheckNeeded());
15615  }
15616
15617  // Strong objects may not have their prototype set via __proto__ or
15618  // setPrototypeOf.
15619  if (from_javascript && object->map()->is_strong()) {
15620    RETURN_FAILURE(isolate, should_throw,
15621                   NewTypeError(MessageTemplate::kStrongSetProto, object));
15622  }
15623  Heap* heap = isolate->heap();
15624  // Silently ignore the change if value is not a JSObject or null.
15625  // SpiderMonkey behaves this way.
15626  if (!value->IsJSReceiver() && !value->IsNull()) return Just(true);
15627
15628  bool dictionary_elements_in_chain =
15629      object->map()->DictionaryElementsInPrototypeChainOnly();
15630
15631  bool all_extensible = object->map()->is_extensible();
15632  Handle<JSObject> real_receiver = object;
15633  if (from_javascript) {
15634    // Find the first object in the chain whose prototype object is not
15635    // hidden.
15636    PrototypeIterator iter(isolate, real_receiver);
15637    while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
15638      // Casting to JSObject is fine because hidden prototypes are never
15639      // JSProxies.
15640      real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
15641      iter.Advance();
15642      all_extensible = all_extensible && real_receiver->map()->is_extensible();
15643    }
15644  }
15645  Handle<Map> map(real_receiver->map());
15646
15647  // Nothing to do if prototype is already set.
15648  if (map->prototype() == *value) return Just(true);
15649
15650  // From 8.6.2 Object Internal Methods
15651  // ...
15652  // In addition, if [[Extensible]] is false the value of the [[Class]] and
15653  // [[Prototype]] internal properties of the object may not be modified.
15654  // ...
15655  // Implementation specific extensions that modify [[Class]], [[Prototype]]
15656  // or [[Extensible]] must not violate the invariants defined in the preceding
15657  // paragraph.
15658  if (!all_extensible) {
15659    RETURN_FAILURE(isolate, should_throw,
15660                   NewTypeError(MessageTemplate::kNonExtensibleProto, object));
15661  }
15662
15663  // Before we can set the prototype we need to be sure prototype cycles are
15664  // prevented.  It is sufficient to validate that the receiver is not in the
15665  // new prototype chain.
15666  for (PrototypeIterator iter(isolate, *value,
15667                              PrototypeIterator::START_AT_RECEIVER);
15668       !iter.IsAtEnd(); iter.Advance()) {
15669    if (iter.GetCurrent<JSReceiver>() == *object) {
15670      // Cycle detected.
15671      RETURN_FAILURE(isolate, should_throw,
15672                     NewTypeError(MessageTemplate::kCyclicProto));
15673    }
15674  }
15675
15676  // Set the new prototype of the object.
15677
15678  isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
15679
15680  PrototypeOptimizationMode mode =
15681      from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
15682  Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
15683  DCHECK(new_map->prototype() == *value);
15684  JSObject::MigrateToMap(real_receiver, new_map);
15685
15686  if (from_javascript && !dictionary_elements_in_chain &&
15687      new_map->DictionaryElementsInPrototypeChainOnly()) {
15688    // If the prototype chain didn't previously have element callbacks, then
15689    // KeyedStoreICs need to be cleared to ensure any that involve this
15690    // map go generic.
15691    TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
15692  }
15693
15694  heap->ClearInstanceofCache();
15695  DCHECK(size == object->Size());
15696  return Just(true);
15697}
15698
15699
15700void JSObject::EnsureCanContainElements(Handle<JSObject> object,
15701                                        Arguments* args,
15702                                        uint32_t first_arg,
15703                                        uint32_t arg_count,
15704                                        EnsureElementsMode mode) {
15705  // Elements in |Arguments| are ordered backwards (because they're on the
15706  // stack), but the method that's called here iterates over them in forward
15707  // direction.
15708  return EnsureCanContainElements(
15709      object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
15710}
15711
15712
15713ElementsAccessor* JSObject::GetElementsAccessor() {
15714  return ElementsAccessor::ForKind(GetElementsKind());
15715}
15716
15717
15718void JSObject::ValidateElements(Handle<JSObject> object) {
15719#ifdef ENABLE_SLOW_DCHECKS
15720  if (FLAG_enable_slow_asserts) {
15721    ElementsAccessor* accessor = object->GetElementsAccessor();
15722    accessor->Validate(object);
15723  }
15724#endif
15725}
15726
15727
15728static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
15729                                        uint32_t index,
15730                                        uint32_t* new_capacity) {
15731  STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
15732                JSObject::kMaxUncheckedFastElementsLength);
15733  if (index < capacity) {
15734    *new_capacity = capacity;
15735    return false;
15736  }
15737  if (index - capacity >= JSObject::kMaxGap) return true;
15738  *new_capacity = JSObject::NewElementsCapacity(index + 1);
15739  DCHECK_LT(index, *new_capacity);
15740  if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
15741      (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
15742       object->GetHeap()->InNewSpace(object))) {
15743    return false;
15744  }
15745  // If the fast-case backing storage takes up roughly three times as
15746  // much space (in machine words) as a dictionary backing storage
15747  // would, the object should have slow elements.
15748  int used_elements = object->GetFastElementsUsage();
15749  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
15750                        SeededNumberDictionary::kEntrySize;
15751  return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
15752}
15753
15754
15755bool JSObject::WouldConvertToSlowElements(uint32_t index) {
15756  if (HasFastElements()) {
15757    Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
15758    uint32_t capacity = static_cast<uint32_t>(backing_store->length());
15759    uint32_t new_capacity;
15760    return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
15761  }
15762  return false;
15763}
15764
15765
15766static ElementsKind BestFittingFastElementsKind(JSObject* object) {
15767  if (object->HasSloppyArgumentsElements()) {
15768    return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
15769  }
15770  DCHECK(object->HasDictionaryElements());
15771  SeededNumberDictionary* dictionary = object->element_dictionary();
15772  ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
15773  for (int i = 0; i < dictionary->Capacity(); i++) {
15774    Object* key = dictionary->KeyAt(i);
15775    if (key->IsNumber()) {
15776      Object* value = dictionary->ValueAt(i);
15777      if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
15778      if (!value->IsSmi()) {
15779        if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
15780        kind = FAST_HOLEY_DOUBLE_ELEMENTS;
15781      }
15782    }
15783  }
15784  return kind;
15785}
15786
15787
15788static bool ShouldConvertToFastElements(JSObject* object,
15789                                        SeededNumberDictionary* dictionary,
15790                                        uint32_t index,
15791                                        uint32_t* new_capacity) {
15792  // If properties with non-standard attributes or accessors were added, we
15793  // cannot go back to fast elements.
15794  if (dictionary->requires_slow_elements()) return false;
15795
15796  // Adding a property with this index will require slow elements.
15797  if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
15798
15799  if (object->IsJSArray()) {
15800    Object* length = JSArray::cast(object)->length();
15801    if (!length->IsSmi()) return false;
15802    *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
15803  } else {
15804    *new_capacity = dictionary->max_number_key() + 1;
15805  }
15806  *new_capacity = Max(index + 1, *new_capacity);
15807
15808  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
15809                             SeededNumberDictionary::kEntrySize;
15810
15811  // Turn fast if the dictionary only saves 50% space.
15812  return 2 * dictionary_size >= *new_capacity;
15813}
15814
15815
15816// static
15817MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
15818                                             uint32_t index,
15819                                             Handle<Object> value,
15820                                             PropertyAttributes attributes) {
15821  MAYBE_RETURN_NULL(
15822      AddDataElement(object, index, value, attributes, THROW_ON_ERROR));
15823  return value;
15824}
15825
15826
15827// static
15828Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
15829                                     Handle<Object> value,
15830                                     PropertyAttributes attributes,
15831                                     ShouldThrow should_throw) {
15832  DCHECK(object->map()->is_extensible());
15833
15834  Isolate* isolate = object->GetIsolate();
15835
15836  uint32_t old_length = 0;
15837  uint32_t new_capacity = 0;
15838
15839  Handle<Object> old_length_handle;
15840  if (object->IsJSArray()) {
15841    CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
15842    if (object->map()->is_observed()) {
15843      old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
15844    }
15845  }
15846
15847  ElementsKind kind = object->GetElementsKind();
15848  FixedArrayBase* elements = object->elements();
15849  ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15850  if (IsSloppyArgumentsElements(kind)) {
15851    elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
15852    dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15853  }
15854
15855  if (attributes != NONE) {
15856    kind = dictionary_kind;
15857  } else if (elements->IsSeededNumberDictionary()) {
15858    kind = ShouldConvertToFastElements(*object,
15859                                       SeededNumberDictionary::cast(elements),
15860                                       index, &new_capacity)
15861               ? BestFittingFastElementsKind(*object)
15862               : dictionary_kind;  // Overwrite in case of arguments.
15863  } else if (ShouldConvertToSlowElements(
15864                 *object, static_cast<uint32_t>(elements->length()), index,
15865                 &new_capacity)) {
15866    kind = dictionary_kind;
15867  }
15868
15869  ElementsKind to = value->OptimalElementsKind();
15870  if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
15871    to = GetHoleyElementsKind(to);
15872    kind = GetHoleyElementsKind(kind);
15873  }
15874  to = GetMoreGeneralElementsKind(kind, to);
15875  ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
15876  accessor->Add(object, index, value, attributes, new_capacity);
15877
15878  uint32_t new_length = old_length;
15879  Handle<Object> new_length_handle;
15880  if (object->IsJSArray() && index >= old_length) {
15881    new_length = index + 1;
15882    new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
15883    JSArray::cast(*object)->set_length(*new_length_handle);
15884  }
15885
15886  if (!old_length_handle.is_null() && new_length != old_length) {
15887    // |old_length_handle| is kept null above unless the object is observed.
15888    DCHECK(object->map()->is_observed());
15889    Handle<JSArray> array = Handle<JSArray>::cast(object);
15890    Handle<String> name = isolate->factory()->Uint32ToString(index);
15891
15892    RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array),
15893                              Nothing<bool>());
15894    RETURN_ON_EXCEPTION_VALUE(
15895        isolate, EnqueueChangeRecord(array, "add", name,
15896                                     isolate->factory()->the_hole_value()),
15897        Nothing<bool>());
15898    RETURN_ON_EXCEPTION_VALUE(
15899        isolate, EnqueueChangeRecord(array, "update",
15900                                     isolate->factory()->length_string(),
15901                                     old_length_handle),
15902        Nothing<bool>());
15903    RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array),
15904                              Nothing<bool>());
15905    Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
15906    RETURN_ON_EXCEPTION_VALUE(isolate,
15907                              EnqueueSpliceRecord(array, old_length, deleted,
15908                                                  new_length - old_length),
15909                              Nothing<bool>());
15910  } else if (object->map()->is_observed()) {
15911    Handle<String> name = isolate->factory()->Uint32ToString(index);
15912    RETURN_ON_EXCEPTION_VALUE(
15913        isolate, EnqueueChangeRecord(object, "add", name,
15914                                     isolate->factory()->the_hole_value()),
15915        Nothing<bool>());
15916  }
15917
15918  return Just(true);
15919}
15920
15921
15922bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
15923  if (!HasFastElements()) return false;
15924  uint32_t capacity = static_cast<uint32_t>(elements()->length());
15925  uint32_t new_capacity;
15926  return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
15927         ShouldConvertToSlowElements(this, capacity, new_length - 1,
15928                                     &new_capacity);
15929}
15930
15931
15932const double AllocationSite::kPretenureRatio = 0.85;
15933
15934
15935void AllocationSite::ResetPretenureDecision() {
15936  set_pretenure_decision(kUndecided);
15937  set_memento_found_count(0);
15938  set_memento_create_count(0);
15939}
15940
15941
15942PretenureFlag AllocationSite::GetPretenureMode() {
15943  PretenureDecision mode = pretenure_decision();
15944  // Zombie objects "decide" to be untenured.
15945  return mode == kTenure ? TENURED : NOT_TENURED;
15946}
15947
15948
15949bool AllocationSite::IsNestedSite() {
15950  DCHECK(FLAG_trace_track_allocation_sites);
15951  Object* current = GetHeap()->allocation_sites_list();
15952  while (current->IsAllocationSite()) {
15953    AllocationSite* current_site = AllocationSite::cast(current);
15954    if (current_site->nested_site() == this) {
15955      return true;
15956    }
15957    current = current_site->weak_next();
15958  }
15959  return false;
15960}
15961
15962
15963void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
15964                                              ElementsKind to_kind) {
15965  Isolate* isolate = site->GetIsolate();
15966
15967  if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
15968    Handle<JSArray> transition_info =
15969        handle(JSArray::cast(site->transition_info()));
15970    ElementsKind kind = transition_info->GetElementsKind();
15971    // if kind is holey ensure that to_kind is as well.
15972    if (IsHoleyElementsKind(kind)) {
15973      to_kind = GetHoleyElementsKind(to_kind);
15974    }
15975    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
15976      // If the array is huge, it's not likely to be defined in a local
15977      // function, so we shouldn't make new instances of it very often.
15978      uint32_t length = 0;
15979      CHECK(transition_info->length()->ToArrayLength(&length));
15980      if (length <= kMaximumArrayBytesToPretransition) {
15981        if (FLAG_trace_track_allocation_sites) {
15982          bool is_nested = site->IsNestedSite();
15983          PrintF(
15984              "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
15985              reinterpret_cast<void*>(*site),
15986              is_nested ? "(nested)" : "",
15987              ElementsKindToString(kind),
15988              ElementsKindToString(to_kind));
15989        }
15990        JSObject::TransitionElementsKind(transition_info, to_kind);
15991        site->dependent_code()->DeoptimizeDependentCodeGroup(
15992            isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
15993      }
15994    }
15995  } else {
15996    ElementsKind kind = site->GetElementsKind();
15997    // if kind is holey ensure that to_kind is as well.
15998    if (IsHoleyElementsKind(kind)) {
15999      to_kind = GetHoleyElementsKind(to_kind);
16000    }
16001    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
16002      if (FLAG_trace_track_allocation_sites) {
16003        PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
16004               reinterpret_cast<void*>(*site),
16005               ElementsKindToString(kind),
16006               ElementsKindToString(to_kind));
16007      }
16008      site->SetElementsKind(to_kind);
16009      site->dependent_code()->DeoptimizeDependentCodeGroup(
16010          isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
16011    }
16012  }
16013}
16014
16015
16016const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
16017  switch (decision) {
16018    case kUndecided: return "undecided";
16019    case kDontTenure: return "don't tenure";
16020    case kMaybeTenure: return "maybe tenure";
16021    case kTenure: return "tenure";
16022    case kZombie: return "zombie";
16023    default: UNREACHABLE();
16024  }
16025  return NULL;
16026}
16027
16028
16029void JSObject::UpdateAllocationSite(Handle<JSObject> object,
16030                                    ElementsKind to_kind) {
16031  if (!object->IsJSArray()) return;
16032
16033  Heap* heap = object->GetHeap();
16034  if (!heap->InNewSpace(*object)) return;
16035
16036  Handle<AllocationSite> site;
16037  {
16038    DisallowHeapAllocation no_allocation;
16039
16040    AllocationMemento* memento = heap->FindAllocationMemento(*object);
16041    if (memento == NULL) return;
16042
16043    // Walk through to the Allocation Site
16044    site = handle(memento->GetAllocationSite());
16045  }
16046  AllocationSite::DigestTransitionFeedback(site, to_kind);
16047}
16048
16049
16050void JSObject::TransitionElementsKind(Handle<JSObject> object,
16051                                      ElementsKind to_kind) {
16052  ElementsKind from_kind = object->GetElementsKind();
16053
16054  if (IsFastHoleyElementsKind(from_kind)) {
16055    to_kind = GetHoleyElementsKind(to_kind);
16056  }
16057
16058  if (from_kind == to_kind) return;
16059
16060  // This method should never be called for any other case.
16061  DCHECK(IsFastElementsKind(from_kind));
16062  DCHECK(IsFastElementsKind(to_kind));
16063  DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
16064
16065  UpdateAllocationSite(object, to_kind);
16066  if (object->elements() == object->GetHeap()->empty_fixed_array() ||
16067      IsFastDoubleElementsKind(from_kind) ==
16068          IsFastDoubleElementsKind(to_kind)) {
16069    // No change is needed to the elements() buffer, the transition
16070    // only requires a map change.
16071    Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
16072    MigrateToMap(object, new_map);
16073    if (FLAG_trace_elements_transitions) {
16074      Handle<FixedArrayBase> elms(object->elements());
16075      PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
16076    }
16077  } else {
16078    DCHECK((IsFastSmiElementsKind(from_kind) &&
16079            IsFastDoubleElementsKind(to_kind)) ||
16080           (IsFastDoubleElementsKind(from_kind) &&
16081            IsFastObjectElementsKind(to_kind)));
16082    uint32_t c = static_cast<uint32_t>(object->elements()->length());
16083    ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
16084  }
16085}
16086
16087
16088// static
16089bool Map::IsValidElementsTransition(ElementsKind from_kind,
16090                                    ElementsKind to_kind) {
16091  // Transitions can't go backwards.
16092  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
16093    return false;
16094  }
16095
16096  // Transitions from HOLEY -> PACKED are not allowed.
16097  return !IsFastHoleyElementsKind(from_kind) ||
16098      IsFastHoleyElementsKind(to_kind);
16099}
16100
16101
16102bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
16103  LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
16104                    LookupIterator::OWN_SKIP_INTERCEPTOR);
16105  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
16106  CHECK(it.IsFound());
16107  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
16108  return it.IsReadOnly();
16109}
16110
16111
16112bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
16113                                        uint32_t index) {
16114  uint32_t length = 0;
16115  CHECK(array->length()->ToArrayLength(&length));
16116  if (length <= index) return HasReadOnlyLength(array);
16117  return false;
16118}
16119
16120
16121template <typename BackingStore>
16122static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
16123  int limit = object->IsJSArray()
16124                  ? Smi::cast(JSArray::cast(object)->length())->value()
16125                  : store->length();
16126  int used = 0;
16127  for (int i = 0; i < limit; ++i) {
16128    if (!store->is_the_hole(i)) ++used;
16129  }
16130  return used;
16131}
16132
16133
16134int JSObject::GetFastElementsUsage() {
16135  FixedArrayBase* store = elements();
16136  switch (GetElementsKind()) {
16137    case FAST_SMI_ELEMENTS:
16138    case FAST_DOUBLE_ELEMENTS:
16139    case FAST_ELEMENTS:
16140      return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
16141                         : store->length();
16142    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16143      store = FixedArray::cast(FixedArray::cast(store)->get(1));
16144    // Fall through.
16145    case FAST_HOLEY_SMI_ELEMENTS:
16146    case FAST_HOLEY_ELEMENTS:
16147      return FastHoleyElementsUsage(this, FixedArray::cast(store));
16148    case FAST_HOLEY_DOUBLE_ELEMENTS:
16149      if (elements()->length() == 0) return 0;
16150      return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
16151
16152    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
16153    case DICTIONARY_ELEMENTS:
16154#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
16155    case TYPE##_ELEMENTS:                                                    \
16156
16157    TYPED_ARRAYS(TYPED_ARRAY_CASE)
16158#undef TYPED_ARRAY_CASE
16159    UNREACHABLE();
16160  }
16161  return 0;
16162}
16163
16164
16165// Certain compilers request function template instantiation when they
16166// see the definition of the other template functions in the
16167// class. This requires us to have the template functions put
16168// together, so even though this function belongs in objects-debug.cc,
16169// we keep it here instead to satisfy certain compilers.
16170#ifdef OBJECT_PRINT
16171template <typename Derived, typename Shape, typename Key>
16172void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
16173  int capacity = this->Capacity();
16174  for (int i = 0; i < capacity; i++) {
16175    Object* k = this->KeyAt(i);
16176    if (this->IsKey(k)) {
16177      os << "\n   ";
16178      if (k->IsString()) {
16179        String::cast(k)->StringPrint(os);
16180      } else {
16181        os << Brief(k);
16182      }
16183      os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i);
16184    }
16185  }
16186}
16187#endif
16188
16189
16190template<typename Derived, typename Shape, typename Key>
16191void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
16192  int pos = 0;
16193  int capacity = this->Capacity();
16194  DisallowHeapAllocation no_gc;
16195  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
16196  for (int i = 0; i < capacity; i++) {
16197    Object* k = this->KeyAt(i);
16198    if (this->IsKey(k)) {
16199      elements->set(pos++, this->ValueAt(i), mode);
16200    }
16201  }
16202  DCHECK(pos == elements->length());
16203}
16204
16205
16206InterceptorInfo* JSObject::GetNamedInterceptor() {
16207  DCHECK(map()->has_named_interceptor());
16208  JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
16209  DCHECK(constructor->shared()->IsApiFunction());
16210  Object* result =
16211      constructor->shared()->get_api_func_data()->named_property_handler();
16212  return InterceptorInfo::cast(result);
16213}
16214
16215
16216MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
16217                                                         bool* done) {
16218  *done = false;
16219  Isolate* isolate = it->isolate();
16220  // Make sure that the top context does not change when doing callbacks or
16221  // interceptor calls.
16222  AssertNoContextChange ncc(isolate);
16223
16224  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
16225  Handle<InterceptorInfo> interceptor = it->GetInterceptor();
16226  if (interceptor->getter()->IsUndefined()) {
16227    return isolate->factory()->undefined_value();
16228  }
16229
16230  Handle<JSObject> holder = it->GetHolder<JSObject>();
16231  v8::Local<v8::Value> result;
16232  PropertyCallbackArguments args(isolate, interceptor->data(),
16233                                 *it->GetReceiver(), *holder);
16234
16235  if (it->IsElement()) {
16236    uint32_t index = it->index();
16237    v8::IndexedPropertyGetterCallback getter =
16238        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
16239    LOG(isolate,
16240        ApiIndexedPropertyAccess("interceptor-indexed-get", *holder, index));
16241    result = args.Call(getter, index);
16242  } else {
16243    Handle<Name> name = it->name();
16244    DCHECK(!name->IsPrivate());
16245
16246    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
16247      return isolate->factory()->undefined_value();
16248    }
16249
16250    v8::GenericNamedPropertyGetterCallback getter =
16251        v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
16252            interceptor->getter());
16253    LOG(isolate,
16254        ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
16255    result = args.Call(getter, v8::Utils::ToLocal(name));
16256  }
16257
16258  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
16259  if (result.IsEmpty()) return isolate->factory()->undefined_value();
16260  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
16261  result_internal->VerifyApiCallResultType();
16262  *done = true;
16263  // Rebox handle before return
16264  return handle(*result_internal, isolate);
16265}
16266
16267
16268Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
16269                                           Handle<Name> name) {
16270  LookupIterator it = LookupIterator::PropertyOrElement(
16271      name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16272  return HasProperty(&it);
16273}
16274
16275
16276Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
16277                                             uint32_t index) {
16278  Isolate* isolate = object->GetIsolate();
16279  LookupIterator it(isolate, object, index,
16280                    LookupIterator::OWN_SKIP_INTERCEPTOR);
16281  return HasProperty(&it);
16282}
16283
16284
16285Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
16286                                                   Handle<Name> name) {
16287  LookupIterator it = LookupIterator::PropertyOrElement(
16288      name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
16289  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
16290  return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
16291                               : Nothing<bool>();
16292}
16293
16294
16295void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
16296  Object* temp = get(i);
16297  set(i, get(j));
16298  set(j, temp);
16299  if (this != numbers) {
16300    temp = numbers->get(i);
16301    numbers->set(i, Smi::cast(numbers->get(j)));
16302    numbers->set(j, Smi::cast(temp));
16303  }
16304}
16305
16306
16307static void InsertionSortPairs(FixedArray* content,
16308                               FixedArray* numbers,
16309                               int len) {
16310  for (int i = 1; i < len; i++) {
16311    int j = i;
16312    while (j > 0 &&
16313           (NumberToUint32(numbers->get(j - 1)) >
16314            NumberToUint32(numbers->get(j)))) {
16315      content->SwapPairs(numbers, j - 1, j);
16316      j--;
16317    }
16318  }
16319}
16320
16321
16322void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
16323  // In-place heap sort.
16324  DCHECK(content->length() == numbers->length());
16325
16326  // Bottom-up max-heap construction.
16327  for (int i = 1; i < len; ++i) {
16328    int child_index = i;
16329    while (child_index > 0) {
16330      int parent_index = ((child_index + 1) >> 1) - 1;
16331      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
16332      uint32_t child_value = NumberToUint32(numbers->get(child_index));
16333      if (parent_value < child_value) {
16334        content->SwapPairs(numbers, parent_index, child_index);
16335      } else {
16336        break;
16337      }
16338      child_index = parent_index;
16339    }
16340  }
16341
16342  // Extract elements and create sorted array.
16343  for (int i = len - 1; i > 0; --i) {
16344    // Put max element at the back of the array.
16345    content->SwapPairs(numbers, 0, i);
16346    // Sift down the new top element.
16347    int parent_index = 0;
16348    while (true) {
16349      int child_index = ((parent_index + 1) << 1) - 1;
16350      if (child_index >= i) break;
16351      uint32_t child1_value = NumberToUint32(numbers->get(child_index));
16352      uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
16353      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
16354      if (child_index + 1 >= i || child1_value > child2_value) {
16355        if (parent_value > child1_value) break;
16356        content->SwapPairs(numbers, parent_index, child_index);
16357        parent_index = child_index;
16358      } else {
16359        if (parent_value > child2_value) break;
16360        content->SwapPairs(numbers, parent_index, child_index + 1);
16361        parent_index = child_index + 1;
16362      }
16363    }
16364  }
16365}
16366
16367
16368// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
16369void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
16370  DCHECK(this->length() == numbers->length());
16371  // For small arrays, simply use insertion sort.
16372  if (len <= 10) {
16373    InsertionSortPairs(this, numbers, len);
16374    return;
16375  }
16376  // Check the range of indices.
16377  uint32_t min_index = NumberToUint32(numbers->get(0));
16378  uint32_t max_index = min_index;
16379  uint32_t i;
16380  for (i = 1; i < len; i++) {
16381    if (NumberToUint32(numbers->get(i)) < min_index) {
16382      min_index = NumberToUint32(numbers->get(i));
16383    } else if (NumberToUint32(numbers->get(i)) > max_index) {
16384      max_index = NumberToUint32(numbers->get(i));
16385    }
16386  }
16387  if (max_index - min_index + 1 == len) {
16388    // Indices form a contiguous range, unless there are duplicates.
16389    // Do an in-place linear time sort assuming distinct numbers, but
16390    // avoid hanging in case they are not.
16391    for (i = 0; i < len; i++) {
16392      uint32_t p;
16393      uint32_t j = 0;
16394      // While the current element at i is not at its correct position p,
16395      // swap the elements at these two positions.
16396      while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
16397             j++ < len) {
16398        SwapPairs(numbers, i, p);
16399      }
16400    }
16401  } else {
16402    HeapSortPairs(this, numbers, len);
16403    return;
16404  }
16405}
16406
16407
16408void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
16409                                       PropertyFilter filter) {
16410  if (HasFastProperties()) {
16411    int real_size = map()->NumberOfOwnDescriptors();
16412    Handle<DescriptorArray> descs(map()->instance_descriptors());
16413    for (int i = 0; i < real_size; i++) {
16414      PropertyDetails details = descs->GetDetails(i);
16415      if ((details.attributes() & filter) != 0) continue;
16416      if (filter & ONLY_ALL_CAN_READ) {
16417        if (details.kind() != kAccessor) continue;
16418        Object* accessors = descs->GetValue(i);
16419        if (!accessors->IsAccessorInfo()) continue;
16420        if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
16421      }
16422      Name* key = descs->GetKey(i);
16423      if (key->FilterKey(filter)) continue;
16424      keys->AddKey(key);
16425    }
16426  } else if (IsJSGlobalObject()) {
16427    GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
16428  } else {
16429    NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter);
16430  }
16431}
16432
16433
16434int JSObject::NumberOfOwnElements(PropertyFilter filter) {
16435  // Fast case for objects with no elements.
16436  if (!IsJSValue() && HasFastElements()) {
16437    uint32_t length =
16438        IsJSArray()
16439            ? static_cast<uint32_t>(
16440                  Smi::cast(JSArray::cast(this)->length())->value())
16441            : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length());
16442    if (length == 0) return 0;
16443  }
16444  // Compute the number of enumerable elements.
16445  return GetOwnElementKeys(NULL, filter);
16446}
16447
16448
16449void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
16450                                     KeyAccumulator* keys,
16451                                     PropertyFilter filter) {
16452  if (filter & SKIP_STRINGS) return;
16453  uint32_t string_keys = 0;
16454
16455  // If this is a String wrapper, add the string indices first,
16456  // as they're guaranteed to precede the elements in numerical order
16457  // and ascending order is required by ECMA-262, 6th, 9.1.12.
16458  if (object->IsJSValue()) {
16459    Object* val = JSValue::cast(*object)->value();
16460    if (val->IsString() && (filter & ONLY_ALL_CAN_READ) == 0) {
16461      String* str = String::cast(val);
16462      string_keys = str->length();
16463      for (uint32_t i = 0; i < string_keys; i++) {
16464        keys->AddKey(i);
16465      }
16466    }
16467  }
16468  ElementsAccessor* accessor = object->GetElementsAccessor();
16469  accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
16470}
16471
16472
16473int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
16474  int counter = 0;
16475
16476  // If this is a String wrapper, add the string indices first,
16477  // as they're guaranteed to precede the elements in numerical order
16478  // and ascending order is required by ECMA-262, 6th, 9.1.12.
16479  if (IsJSValue()) {
16480    Object* val = JSValue::cast(this)->value();
16481    if (val->IsString()) {
16482      String* str = String::cast(val);
16483      if (storage) {
16484        for (int i = 0; i < str->length(); i++) {
16485          storage->set(counter + i, Smi::FromInt(i));
16486        }
16487      }
16488      counter += str->length();
16489    }
16490  }
16491
16492  switch (GetElementsKind()) {
16493    case FAST_SMI_ELEMENTS:
16494    case FAST_ELEMENTS:
16495    case FAST_HOLEY_SMI_ELEMENTS:
16496    case FAST_HOLEY_ELEMENTS: {
16497      int length = IsJSArray() ?
16498          Smi::cast(JSArray::cast(this)->length())->value() :
16499          FixedArray::cast(elements())->length();
16500      for (int i = 0; i < length; i++) {
16501        if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
16502          if (storage != NULL) {
16503            storage->set(counter, Smi::FromInt(i));
16504          }
16505          counter++;
16506        }
16507      }
16508      DCHECK(!storage || storage->length() >= counter);
16509      break;
16510    }
16511    case FAST_DOUBLE_ELEMENTS:
16512    case FAST_HOLEY_DOUBLE_ELEMENTS: {
16513      int length = IsJSArray() ?
16514          Smi::cast(JSArray::cast(this)->length())->value() :
16515          FixedArrayBase::cast(elements())->length();
16516      for (int i = 0; i < length; i++) {
16517        if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
16518          if (storage != NULL) {
16519            storage->set(counter, Smi::FromInt(i));
16520          }
16521          counter++;
16522        }
16523      }
16524      DCHECK(!storage || storage->length() >= counter);
16525      break;
16526    }
16527
16528#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
16529    case TYPE##_ELEMENTS:                                                    \
16530
16531    TYPED_ARRAYS(TYPED_ARRAY_CASE)
16532#undef TYPED_ARRAY_CASE
16533    {
16534      int length = FixedArrayBase::cast(elements())->length();
16535      while (counter < length) {
16536        if (storage != NULL) {
16537          storage->set(counter, Smi::FromInt(counter));
16538        }
16539        counter++;
16540      }
16541      DCHECK(!storage || storage->length() >= counter);
16542      break;
16543    }
16544
16545    case DICTIONARY_ELEMENTS: {
16546      if (storage != NULL) {
16547        element_dictionary()->CopyKeysTo(storage, counter, filter,
16548                                         SeededNumberDictionary::SORTED);
16549      }
16550      counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
16551      break;
16552    }
16553    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
16554    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
16555      FixedArray* parameter_map = FixedArray::cast(elements());
16556      int mapped_length = parameter_map->length() - 2;
16557      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
16558      if (arguments->IsDictionary()) {
16559        // Copy the keys from arguments first, because Dictionary::CopyKeysTo
16560        // will insert in storage starting at index 0.
16561        SeededNumberDictionary* dictionary =
16562            SeededNumberDictionary::cast(arguments);
16563        if (storage != NULL) {
16564          dictionary->CopyKeysTo(storage, counter, filter,
16565                                 SeededNumberDictionary::UNSORTED);
16566        }
16567        counter += dictionary->NumberOfElementsFilterAttributes(filter);
16568        for (int i = 0; i < mapped_length; ++i) {
16569          if (!parameter_map->get(i + 2)->IsTheHole()) {
16570            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
16571            ++counter;
16572          }
16573        }
16574        if (storage != NULL) storage->SortPairs(storage, counter);
16575
16576      } else {
16577        int backing_length = arguments->length();
16578        int i = 0;
16579        for (; i < mapped_length; ++i) {
16580          if (!parameter_map->get(i + 2)->IsTheHole()) {
16581            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
16582            ++counter;
16583          } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
16584            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
16585            ++counter;
16586          }
16587        }
16588        for (; i < backing_length; ++i) {
16589          if (storage != NULL) storage->set(counter, Smi::FromInt(i));
16590          ++counter;
16591        }
16592      }
16593      break;
16594    }
16595  }
16596
16597  DCHECK(!storage || storage->length() == counter);
16598  return counter;
16599}
16600
16601
16602MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
16603                                                Handle<Object> object) {
16604  if (object->IsUndefined()) return isolate->factory()->undefined_to_string();
16605  if (object->IsNull()) return isolate->factory()->null_to_string();
16606
16607  Handle<JSReceiver> receiver;
16608  CHECK(Object::ToObject(isolate, object).ToHandle(&receiver));
16609
16610  Handle<String> tag;
16611  if (FLAG_harmony_tostring) {
16612    Handle<Object> to_string_tag;
16613    ASSIGN_RETURN_ON_EXCEPTION(
16614        isolate, to_string_tag,
16615        GetProperty(receiver, isolate->factory()->to_string_tag_symbol()),
16616        String);
16617    if (to_string_tag->IsString()) {
16618      tag = Handle<String>::cast(to_string_tag);
16619    }
16620  }
16621
16622  if (tag.is_null()) {
16623    ASSIGN_RETURN_ON_EXCEPTION(isolate, tag,
16624                               JSReceiver::BuiltinStringTag(receiver), String);
16625  }
16626
16627  IncrementalStringBuilder builder(isolate);
16628  builder.AppendCString("[object ");
16629  builder.AppendString(tag);
16630  builder.AppendCharacter(']');
16631  return builder.Finish();
16632}
16633
16634
16635const char* Symbol::PrivateSymbolToName() const {
16636  Heap* heap = GetIsolate()->heap();
16637#define SYMBOL_CHECK_AND_PRINT(name) \
16638  if (this == heap->name()) return #name;
16639  PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
16640#undef SYMBOL_CHECK_AND_PRINT
16641  return "UNKNOWN";
16642}
16643
16644
16645void Symbol::SymbolShortPrint(std::ostream& os) {
16646  os << "<Symbol: " << Hash();
16647  if (!name()->IsUndefined()) {
16648    os << " ";
16649    HeapStringAllocator allocator;
16650    StringStream accumulator(&allocator);
16651    String::cast(name())->StringShortPrint(&accumulator);
16652    os << accumulator.ToCString().get();
16653  } else {
16654    os << " (" << PrivateSymbolToName() << ")";
16655  }
16656  os << ">";
16657}
16658
16659
16660// StringSharedKeys are used as keys in the eval cache.
16661class StringSharedKey : public HashTableKey {
16662 public:
16663  StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
16664                  LanguageMode language_mode, int scope_position)
16665      : source_(source),
16666        shared_(shared),
16667        language_mode_(language_mode),
16668        scope_position_(scope_position) {}
16669
16670  bool IsMatch(Object* other) override {
16671    DisallowHeapAllocation no_allocation;
16672    if (!other->IsFixedArray()) {
16673      if (!other->IsNumber()) return false;
16674      uint32_t other_hash = static_cast<uint32_t>(other->Number());
16675      return Hash() == other_hash;
16676    }
16677    FixedArray* other_array = FixedArray::cast(other);
16678    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
16679    if (shared != *shared_) return false;
16680    int language_unchecked = Smi::cast(other_array->get(2))->value();
16681    DCHECK(is_valid_language_mode(language_unchecked));
16682    LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
16683    if (language_mode != language_mode_) return false;
16684    int scope_position = Smi::cast(other_array->get(3))->value();
16685    if (scope_position != scope_position_) return false;
16686    String* source = String::cast(other_array->get(1));
16687    return source->Equals(*source_);
16688  }
16689
16690  static uint32_t StringSharedHashHelper(String* source,
16691                                         SharedFunctionInfo* shared,
16692                                         LanguageMode language_mode,
16693                                         int scope_position) {
16694    uint32_t hash = source->Hash();
16695    if (shared->HasSourceCode()) {
16696      // Instead of using the SharedFunctionInfo pointer in the hash
16697      // code computation, we use a combination of the hash of the
16698      // script source code and the start position of the calling scope.
16699      // We do this to ensure that the cache entries can survive garbage
16700      // collection.
16701      Script* script(Script::cast(shared->script()));
16702      hash ^= String::cast(script->source())->Hash();
16703      STATIC_ASSERT(LANGUAGE_END == 3);
16704      if (is_strict(language_mode)) hash ^= 0x8000;
16705      if (is_strong(language_mode)) hash ^= 0x10000;
16706      hash += scope_position;
16707    }
16708    return hash;
16709  }
16710
16711  uint32_t Hash() override {
16712    return StringSharedHashHelper(*source_, *shared_, language_mode_,
16713                                  scope_position_);
16714  }
16715
16716  uint32_t HashForObject(Object* obj) override {
16717    DisallowHeapAllocation no_allocation;
16718    if (obj->IsNumber()) {
16719      return static_cast<uint32_t>(obj->Number());
16720    }
16721    FixedArray* other_array = FixedArray::cast(obj);
16722    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
16723    String* source = String::cast(other_array->get(1));
16724    int language_unchecked = Smi::cast(other_array->get(2))->value();
16725    DCHECK(is_valid_language_mode(language_unchecked));
16726    LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
16727    int scope_position = Smi::cast(other_array->get(3))->value();
16728    return StringSharedHashHelper(source, shared, language_mode,
16729                                  scope_position);
16730  }
16731
16732
16733  Handle<Object> AsHandle(Isolate* isolate) override {
16734    Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
16735    array->set(0, *shared_);
16736    array->set(1, *source_);
16737    array->set(2, Smi::FromInt(language_mode_));
16738    array->set(3, Smi::FromInt(scope_position_));
16739    return array;
16740  }
16741
16742 private:
16743  Handle<String> source_;
16744  Handle<SharedFunctionInfo> shared_;
16745  LanguageMode language_mode_;
16746  int scope_position_;
16747};
16748
16749
16750namespace {
16751
16752JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
16753  JSRegExp::Flags value = JSRegExp::kNone;
16754  int length = flags->length();
16755  // A longer flags string cannot be valid.
16756  if (length > 5) return JSRegExp::Flags(0);
16757  for (int i = 0; i < length; i++) {
16758    JSRegExp::Flag flag = JSRegExp::kNone;
16759    switch (flags->Get(i)) {
16760      case 'g':
16761        flag = JSRegExp::kGlobal;
16762        break;
16763      case 'i':
16764        flag = JSRegExp::kIgnoreCase;
16765        break;
16766      case 'm':
16767        flag = JSRegExp::kMultiline;
16768        break;
16769      case 'u':
16770        if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0);
16771        flag = JSRegExp::kUnicode;
16772        break;
16773      case 'y':
16774        if (!FLAG_harmony_regexps) return JSRegExp::Flags(0);
16775        flag = JSRegExp::kSticky;
16776        break;
16777      default:
16778        return JSRegExp::Flags(0);
16779    }
16780    // Duplicate flag.
16781    if (value & flag) return JSRegExp::Flags(0);
16782    value |= flag;
16783  }
16784  *success = true;
16785  return value;
16786}
16787
16788}  // namespace
16789
16790
16791// static
16792MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) {
16793  Isolate* isolate = pattern->GetIsolate();
16794  Handle<JSFunction> constructor = isolate->regexp_function();
16795  Handle<JSRegExp> regexp =
16796      Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
16797
16798  return JSRegExp::Initialize(regexp, pattern, flags);
16799}
16800
16801
16802// static
16803MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern,
16804                                    Handle<String> flags_string) {
16805  Isolate* isolate = pattern->GetIsolate();
16806  bool success = false;
16807  Flags flags = RegExpFlagsFromString(flags_string, &success);
16808  if (!success) {
16809    THROW_NEW_ERROR(
16810        isolate,
16811        NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
16812        JSRegExp);
16813  }
16814  return New(pattern, flags);
16815}
16816
16817
16818// static
16819Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
16820  Isolate* const isolate = regexp->GetIsolate();
16821  return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
16822}
16823
16824
16825template <typename Char>
16826inline int CountRequiredEscapes(Handle<String> source) {
16827  DisallowHeapAllocation no_gc;
16828  int escapes = 0;
16829  Vector<const Char> src = source->GetCharVector<Char>();
16830  for (int i = 0; i < src.length(); i++) {
16831    if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++;
16832  }
16833  return escapes;
16834}
16835
16836
16837template <typename Char, typename StringType>
16838inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
16839                                                   Handle<StringType> result) {
16840  DisallowHeapAllocation no_gc;
16841  Vector<const Char> src = source->GetCharVector<Char>();
16842  Vector<Char> dst(result->GetChars(), result->length());
16843  int s = 0;
16844  int d = 0;
16845  while (s < src.length()) {
16846    if (src[s] == '/' && (s == 0 || src[s - 1] != '\\')) dst[d++] = '\\';
16847    dst[d++] = src[s++];
16848  }
16849  DCHECK_EQ(result->length(), d);
16850  return result;
16851}
16852
16853
16854MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
16855                                       Handle<String> source) {
16856  String::Flatten(source);
16857  if (source->length() == 0) return isolate->factory()->query_colon_string();
16858  bool one_byte = source->IsOneByteRepresentationUnderneath();
16859  int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
16860                         : CountRequiredEscapes<uc16>(source);
16861  if (escapes == 0) return source;
16862  int length = source->length() + escapes;
16863  if (one_byte) {
16864    Handle<SeqOneByteString> result;
16865    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16866                               isolate->factory()->NewRawOneByteString(length),
16867                               String);
16868    return WriteEscapedRegExpSource<uint8_t>(source, result);
16869  } else {
16870    Handle<SeqTwoByteString> result;
16871    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
16872                               isolate->factory()->NewRawTwoByteString(length),
16873                               String);
16874    return WriteEscapedRegExpSource<uc16>(source, result);
16875  }
16876}
16877
16878
16879// static
16880MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16881                                           Handle<String> source,
16882                                           Handle<String> flags_string) {
16883  Isolate* isolate = source->GetIsolate();
16884  bool success = false;
16885  Flags flags = RegExpFlagsFromString(flags_string, &success);
16886  if (!success) {
16887    THROW_NEW_ERROR(
16888        isolate,
16889        NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
16890        JSRegExp);
16891  }
16892  return Initialize(regexp, source, flags);
16893}
16894
16895
16896// static
16897MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
16898                                           Handle<String> source, Flags flags) {
16899  Isolate* isolate = regexp->GetIsolate();
16900  Factory* factory = isolate->factory();
16901  // If source is the empty string we set it to "(?:)" instead as
16902  // suggested by ECMA-262, 5th, section 15.10.4.1.
16903  if (source->length() == 0) source = factory->query_colon_string();
16904
16905  Handle<String> escaped_source;
16906  ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
16907                             EscapeRegExpSource(isolate, source), JSRegExp);
16908
16909  regexp->set_source(*escaped_source);
16910  regexp->set_flags(Smi::FromInt(flags));
16911
16912  Map* map = regexp->map();
16913  Object* constructor = map->GetConstructor();
16914  if (constructor->IsJSFunction() &&
16915      JSFunction::cast(constructor)->initial_map() == map) {
16916    // If we still have the original map, set in-object properties directly.
16917    regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
16918                                  Smi::FromInt(0), SKIP_WRITE_BARRIER);
16919  } else {
16920    // Map has changed, so use generic, but slower, method.
16921    PropertyAttributes writable =
16922        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
16923    JSObject::SetOwnPropertyIgnoreAttributes(
16924        regexp, factory->last_index_string(),
16925        Handle<Smi>(Smi::FromInt(0), isolate), writable)
16926        .Check();
16927  }
16928
16929  RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
16930                      JSRegExp);
16931
16932  return regexp;
16933}
16934
16935
16936// RegExpKey carries the source and flags of a regular expression as key.
16937class RegExpKey : public HashTableKey {
16938 public:
16939  RegExpKey(Handle<String> string, JSRegExp::Flags flags)
16940      : string_(string), flags_(Smi::FromInt(flags)) {}
16941
16942  // Rather than storing the key in the hash table, a pointer to the
16943  // stored value is stored where the key should be.  IsMatch then
16944  // compares the search key to the found object, rather than comparing
16945  // a key to a key.
16946  bool IsMatch(Object* obj) override {
16947    FixedArray* val = FixedArray::cast(obj);
16948    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
16949        && (flags_ == val->get(JSRegExp::kFlagsIndex));
16950  }
16951
16952  uint32_t Hash() override { return RegExpHash(*string_, flags_); }
16953
16954  Handle<Object> AsHandle(Isolate* isolate) override {
16955    // Plain hash maps, which is where regexp keys are used, don't
16956    // use this function.
16957    UNREACHABLE();
16958    return MaybeHandle<Object>().ToHandleChecked();
16959  }
16960
16961  uint32_t HashForObject(Object* obj) override {
16962    FixedArray* val = FixedArray::cast(obj);
16963    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
16964                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
16965  }
16966
16967  static uint32_t RegExpHash(String* string, Smi* flags) {
16968    return string->Hash() + flags->value();
16969  }
16970
16971  Handle<String> string_;
16972  Smi* flags_;
16973};
16974
16975
16976Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
16977  if (hash_field_ == 0) Hash();
16978  return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
16979}
16980
16981
16982Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
16983  if (hash_field_ == 0) Hash();
16984  return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
16985}
16986
16987
16988Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
16989  if (hash_field_ == 0) Hash();
16990  return isolate->factory()->NewOneByteInternalizedSubString(
16991      string_, from_, length_, hash_field_);
16992}
16993
16994
16995bool SeqOneByteSubStringKey::IsMatch(Object* string) {
16996  Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
16997  return String::cast(string)->IsOneByteEqualTo(chars);
16998}
16999
17000
17001// InternalizedStringKey carries a string/internalized-string object as key.
17002class InternalizedStringKey : public HashTableKey {
17003 public:
17004  explicit InternalizedStringKey(Handle<String> string)
17005      : string_(string) { }
17006
17007  bool IsMatch(Object* string) override {
17008    return String::cast(string)->Equals(*string_);
17009  }
17010
17011  uint32_t Hash() override { return string_->Hash(); }
17012
17013  uint32_t HashForObject(Object* other) override {
17014    return String::cast(other)->Hash();
17015  }
17016
17017  Handle<Object> AsHandle(Isolate* isolate) override {
17018    // Internalize the string if possible.
17019    MaybeHandle<Map> maybe_map =
17020        isolate->factory()->InternalizedStringMapForString(string_);
17021    Handle<Map> map;
17022    if (maybe_map.ToHandle(&map)) {
17023      string_->set_map_no_write_barrier(*map);
17024      DCHECK(string_->IsInternalizedString());
17025      return string_;
17026    }
17027    // Otherwise allocate a new internalized string.
17028    return isolate->factory()->NewInternalizedStringImpl(
17029        string_, string_->length(), string_->hash_field());
17030  }
17031
17032  static uint32_t StringHash(Object* obj) {
17033    return String::cast(obj)->Hash();
17034  }
17035
17036  Handle<String> string_;
17037};
17038
17039
17040template<typename Derived, typename Shape, typename Key>
17041void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
17042  BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
17043}
17044
17045
17046template<typename Derived, typename Shape, typename Key>
17047void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
17048  BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
17049                                      kHeaderSize + length() * kPointerSize, v);
17050}
17051
17052
17053template<typename Derived, typename Shape, typename Key>
17054Handle<Derived> HashTable<Derived, Shape, Key>::New(
17055    Isolate* isolate,
17056    int at_least_space_for,
17057    MinimumCapacity capacity_option,
17058    PretenureFlag pretenure) {
17059  DCHECK(0 <= at_least_space_for);
17060  DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
17061
17062  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
17063                     ? at_least_space_for
17064                     : ComputeCapacity(at_least_space_for);
17065  if (capacity > HashTable::kMaxCapacity) {
17066    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
17067  }
17068
17069  Factory* factory = isolate->factory();
17070  int length = EntryToIndex(capacity);
17071  Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
17072  array->set_map_no_write_barrier(*factory->hash_table_map());
17073  Handle<Derived> table = Handle<Derived>::cast(array);
17074
17075  table->SetNumberOfElements(0);
17076  table->SetNumberOfDeletedElements(0);
17077  table->SetCapacity(capacity);
17078  return table;
17079}
17080
17081
17082// Find entry for key otherwise return kNotFound.
17083template <typename Derived, typename Shape>
17084int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
17085  if (!key->IsUniqueName()) {
17086    return DerivedDictionary::FindEntry(key);
17087  }
17088
17089  // Optimized for unique names. Knowledge of the key type allows:
17090  // 1. Move the check if the key is unique out of the loop.
17091  // 2. Avoid comparing hash codes in unique-to-unique comparison.
17092  // 3. Detect a case when a dictionary key is not unique but the key is.
17093  //    In case of positive result the dictionary key may be replaced by the
17094  //    internalized string with minimal performance penalty. It gives a chance
17095  //    to perform further lookups in code stubs (and significant performance
17096  //    boost a certain style of code).
17097
17098  // EnsureCapacity will guarantee the hash table is never full.
17099  uint32_t capacity = this->Capacity();
17100  uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
17101  uint32_t count = 1;
17102
17103  while (true) {
17104    int index = Derived::EntryToIndex(entry);
17105    Object* element = this->get(index);
17106    if (element->IsUndefined()) break;  // Empty entry.
17107    if (*key == element) return entry;
17108    if (!element->IsUniqueName() &&
17109        !element->IsTheHole() &&
17110        Name::cast(element)->Equals(*key)) {
17111      // Replace a key that is a non-internalized string by the equivalent
17112      // internalized string for faster further lookups.
17113      this->set(index, *key);
17114      return entry;
17115    }
17116    DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
17117    entry = Derived::NextProbe(entry, count++, capacity);
17118  }
17119  return Derived::kNotFound;
17120}
17121
17122
17123template<typename Derived, typename Shape, typename Key>
17124void HashTable<Derived, Shape, Key>::Rehash(
17125    Handle<Derived> new_table,
17126    Key key) {
17127  DCHECK(NumberOfElements() < new_table->Capacity());
17128
17129  DisallowHeapAllocation no_gc;
17130  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
17131
17132  // Copy prefix to new array.
17133  for (int i = kPrefixStartIndex;
17134       i < kPrefixStartIndex + Shape::kPrefixSize;
17135       i++) {
17136    new_table->set(i, get(i), mode);
17137  }
17138
17139  // Rehash the elements.
17140  int capacity = this->Capacity();
17141  for (int i = 0; i < capacity; i++) {
17142    uint32_t from_index = EntryToIndex(i);
17143    Object* k = this->get(from_index);
17144    if (IsKey(k)) {
17145      uint32_t hash = this->HashForObject(key, k);
17146      uint32_t insertion_index =
17147          EntryToIndex(new_table->FindInsertionEntry(hash));
17148      for (int j = 0; j < Shape::kEntrySize; j++) {
17149        new_table->set(insertion_index + j, get(from_index + j), mode);
17150      }
17151    }
17152  }
17153  new_table->SetNumberOfElements(NumberOfElements());
17154  new_table->SetNumberOfDeletedElements(0);
17155}
17156
17157
17158template<typename Derived, typename Shape, typename Key>
17159uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
17160    Key key,
17161    Object* k,
17162    int probe,
17163    uint32_t expected) {
17164  uint32_t hash = this->HashForObject(key, k);
17165  uint32_t capacity = this->Capacity();
17166  uint32_t entry = FirstProbe(hash, capacity);
17167  for (int i = 1; i < probe; i++) {
17168    if (entry == expected) return expected;
17169    entry = NextProbe(entry, i, capacity);
17170  }
17171  return entry;
17172}
17173
17174
17175template<typename Derived, typename Shape, typename Key>
17176void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
17177                                          uint32_t entry2,
17178                                          WriteBarrierMode mode) {
17179  int index1 = EntryToIndex(entry1);
17180  int index2 = EntryToIndex(entry2);
17181  Object* temp[Shape::kEntrySize];
17182  for (int j = 0; j < Shape::kEntrySize; j++) {
17183    temp[j] = get(index1 + j);
17184  }
17185  for (int j = 0; j < Shape::kEntrySize; j++) {
17186    set(index1 + j, get(index2 + j), mode);
17187  }
17188  for (int j = 0; j < Shape::kEntrySize; j++) {
17189    set(index2 + j, temp[j], mode);
17190  }
17191}
17192
17193
17194template<typename Derived, typename Shape, typename Key>
17195void HashTable<Derived, Shape, Key>::Rehash(Key key) {
17196  DisallowHeapAllocation no_gc;
17197  WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
17198  uint32_t capacity = Capacity();
17199  bool done = false;
17200  for (int probe = 1; !done; probe++) {
17201    // All elements at entries given by one of the first _probe_ probes
17202    // are placed correctly. Other elements might need to be moved.
17203    done = true;
17204    for (uint32_t current = 0; current < capacity; current++) {
17205      Object* current_key = get(EntryToIndex(current));
17206      if (IsKey(current_key)) {
17207        uint32_t target = EntryForProbe(key, current_key, probe, current);
17208        if (current == target) continue;
17209        Object* target_key = get(EntryToIndex(target));
17210        if (!IsKey(target_key) ||
17211            EntryForProbe(key, target_key, probe, target) != target) {
17212          // Put the current element into the correct position.
17213          Swap(current, target, mode);
17214          // The other element will be processed on the next iteration.
17215          current--;
17216        } else {
17217          // The place for the current element is occupied. Leave the element
17218          // for the next probe.
17219          done = false;
17220        }
17221      }
17222    }
17223  }
17224}
17225
17226
17227template<typename Derived, typename Shape, typename Key>
17228Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
17229    Handle<Derived> table,
17230    int n,
17231    Key key,
17232    PretenureFlag pretenure) {
17233  Isolate* isolate = table->GetIsolate();
17234  int capacity = table->Capacity();
17235  int nof = table->NumberOfElements() + n;
17236
17237  if (table->HasSufficientCapacity(n)) return table;
17238
17239  const int kMinCapacityForPretenure = 256;
17240  bool should_pretenure = pretenure == TENURED ||
17241      ((capacity > kMinCapacityForPretenure) &&
17242          !isolate->heap()->InNewSpace(*table));
17243  Handle<Derived> new_table = HashTable::New(
17244      isolate,
17245      nof * 2,
17246      USE_DEFAULT_MINIMUM_CAPACITY,
17247      should_pretenure ? TENURED : NOT_TENURED);
17248
17249  table->Rehash(new_table, key);
17250  return new_table;
17251}
17252
17253
17254template <typename Derived, typename Shape, typename Key>
17255bool HashTable<Derived, Shape, Key>::HasSufficientCapacity(int n) {
17256  int capacity = Capacity();
17257  int nof = NumberOfElements() + n;
17258  int nod = NumberOfDeletedElements();
17259  // Return true if:
17260  //   50% is still free after adding n elements and
17261  //   at most 50% of the free elements are deleted elements.
17262  if (nod <= (capacity - nof) >> 1) {
17263    int needed_free = nof >> 1;
17264    if (nof + needed_free <= capacity) return true;
17265  }
17266  return false;
17267}
17268
17269
17270template<typename Derived, typename Shape, typename Key>
17271Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
17272                                                       Key key) {
17273  int capacity = table->Capacity();
17274  int nof = table->NumberOfElements();
17275
17276  // Shrink to fit the number of elements if only a quarter of the
17277  // capacity is filled with elements.
17278  if (nof > (capacity >> 2)) return table;
17279  // Allocate a new dictionary with room for at least the current
17280  // number of elements. The allocation method will make sure that
17281  // there is extra room in the dictionary for additions. Don't go
17282  // lower than room for 16 elements.
17283  int at_least_room_for = nof;
17284  if (at_least_room_for < 16) return table;
17285
17286  Isolate* isolate = table->GetIsolate();
17287  const int kMinCapacityForPretenure = 256;
17288  bool pretenure =
17289      (at_least_room_for > kMinCapacityForPretenure) &&
17290      !isolate->heap()->InNewSpace(*table);
17291  Handle<Derived> new_table = HashTable::New(
17292      isolate,
17293      at_least_room_for,
17294      USE_DEFAULT_MINIMUM_CAPACITY,
17295      pretenure ? TENURED : NOT_TENURED);
17296
17297  table->Rehash(new_table, key);
17298  return new_table;
17299}
17300
17301
17302template<typename Derived, typename Shape, typename Key>
17303uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
17304  uint32_t capacity = Capacity();
17305  uint32_t entry = FirstProbe(hash, capacity);
17306  uint32_t count = 1;
17307  // EnsureCapacity will guarantee the hash table is never full.
17308  while (true) {
17309    Object* element = KeyAt(entry);
17310    if (element->IsUndefined() || element->IsTheHole()) break;
17311    entry = NextProbe(entry, count++, capacity);
17312  }
17313  return entry;
17314}
17315
17316
17317// Force instantiation of template instances class.
17318// Please note this list is compiler dependent.
17319
17320template class HashTable<StringTable, StringTableShape, HashTableKey*>;
17321
17322template class HashTable<CompilationCacheTable,
17323                         CompilationCacheShape,
17324                         HashTableKey*>;
17325
17326template class HashTable<ObjectHashTable,
17327                         ObjectHashTableShape,
17328                         Handle<Object> >;
17329
17330template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
17331
17332template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
17333
17334template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
17335                          Handle<Name> >;
17336
17337template class Dictionary<SeededNumberDictionary,
17338                          SeededNumberDictionaryShape,
17339                          uint32_t>;
17340
17341template class Dictionary<UnseededNumberDictionary,
17342                          UnseededNumberDictionaryShape,
17343                          uint32_t>;
17344
17345template Handle<SeededNumberDictionary>
17346Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17347    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
17348
17349template Handle<UnseededNumberDictionary>
17350Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
17351    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
17352
17353template Handle<NameDictionary>
17354Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
17355    New(Isolate*, int n, PretenureFlag pretenure);
17356
17357template Handle<GlobalDictionary>
17358Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::New(
17359    Isolate*, int n, PretenureFlag pretenure);
17360
17361template Handle<SeededNumberDictionary>
17362Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17363    AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
17364
17365template Handle<UnseededNumberDictionary>
17366Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
17367    AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
17368
17369template Object*
17370Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17371    SlowReverseLookup(Object* value);
17372
17373template Object*
17374Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
17375    SlowReverseLookup(Object* value);
17376
17377template Handle<Object>
17378Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
17379    Handle<NameDictionary>, int);
17380
17381template Handle<Object>
17382Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
17383           uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
17384
17385template Handle<NameDictionary>
17386HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
17387    New(Isolate*, int, MinimumCapacity, PretenureFlag);
17388
17389template Handle<NameDictionary>
17390HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
17391    Shrink(Handle<NameDictionary>, Handle<Name>);
17392
17393template Handle<SeededNumberDictionary>
17394HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17395    Shrink(Handle<SeededNumberDictionary>, uint32_t);
17396
17397template Handle<NameDictionary>
17398Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
17399    Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
17400
17401template Handle<GlobalDictionary>
17402    Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Add(
17403        Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
17404        PropertyDetails);
17405
17406template Handle<FixedArray> Dictionary<
17407    NameDictionary, NameDictionaryShape,
17408    Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
17409
17410template Handle<FixedArray> Dictionary<
17411    NameDictionary, NameDictionaryShape,
17412    Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
17413
17414template Handle<SeededNumberDictionary>
17415Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17416    Add(Handle<SeededNumberDictionary>,
17417        uint32_t,
17418        Handle<Object>,
17419        PropertyDetails);
17420
17421template Handle<UnseededNumberDictionary>
17422Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
17423    Add(Handle<UnseededNumberDictionary>,
17424        uint32_t,
17425        Handle<Object>,
17426        PropertyDetails);
17427
17428template Handle<SeededNumberDictionary>
17429Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
17430    EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
17431
17432template Handle<UnseededNumberDictionary>
17433Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
17434    EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
17435
17436template void Dictionary<NameDictionary, NameDictionaryShape,
17437                         Handle<Name> >::SetRequiresCopyOnCapacityChange();
17438
17439template Handle<NameDictionary>
17440Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
17441    EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
17442
17443template bool Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
17444                         uint32_t>::HasComplexElements();
17445
17446template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
17447                       uint32_t>::FindEntry(uint32_t);
17448
17449template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
17450    Handle<Name>);
17451
17452
17453Handle<Object> JSObject::PrepareSlowElementsForSort(
17454    Handle<JSObject> object, uint32_t limit) {
17455  DCHECK(object->HasDictionaryElements());
17456  Isolate* isolate = object->GetIsolate();
17457  // Must stay in dictionary mode, either because of requires_slow_elements,
17458  // or because we are not going to sort (and therefore compact) all of the
17459  // elements.
17460  Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
17461  Handle<SeededNumberDictionary> new_dict =
17462      SeededNumberDictionary::New(isolate, dict->NumberOfElements());
17463
17464  uint32_t pos = 0;
17465  uint32_t undefs = 0;
17466  int capacity = dict->Capacity();
17467  Handle<Smi> bailout(Smi::FromInt(-1), isolate);
17468  // Entry to the new dictionary does not cause it to grow, as we have
17469  // allocated one that is large enough for all entries.
17470  DisallowHeapAllocation no_gc;
17471  for (int i = 0; i < capacity; i++) {
17472    Object* k = dict->KeyAt(i);
17473    if (!dict->IsKey(k)) continue;
17474
17475    DCHECK(k->IsNumber());
17476    DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
17477    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
17478    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
17479
17480    HandleScope scope(isolate);
17481    Handle<Object> value(dict->ValueAt(i), isolate);
17482    PropertyDetails details = dict->DetailsAt(i);
17483    if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
17484      // Bail out and do the sorting of undefineds and array holes in JS.
17485      // Also bail out if the element is not supposed to be moved.
17486      return bailout;
17487    }
17488
17489    uint32_t key = NumberToUint32(k);
17490    if (key < limit) {
17491      if (value->IsUndefined()) {
17492        undefs++;
17493      } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17494        // Adding an entry with the key beyond smi-range requires
17495        // allocation. Bailout.
17496        return bailout;
17497      } else {
17498        Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17499            new_dict, pos, value, details, object->map()->is_prototype_map());
17500        DCHECK(result.is_identical_to(new_dict));
17501        USE(result);
17502        pos++;
17503      }
17504    } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
17505      // Adding an entry with the key beyond smi-range requires
17506      // allocation. Bailout.
17507      return bailout;
17508    } else {
17509      Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17510          new_dict, key, value, details, object->map()->is_prototype_map());
17511      DCHECK(result.is_identical_to(new_dict));
17512      USE(result);
17513    }
17514  }
17515
17516  uint32_t result = pos;
17517  PropertyDetails no_details = PropertyDetails::Empty();
17518  while (undefs > 0) {
17519    if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17520      // Adding an entry with the key beyond smi-range requires
17521      // allocation. Bailout.
17522      return bailout;
17523    }
17524    HandleScope scope(isolate);
17525    Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17526        new_dict, pos, isolate->factory()->undefined_value(), no_details,
17527        object->map()->is_prototype_map());
17528    DCHECK(result.is_identical_to(new_dict));
17529    USE(result);
17530    pos++;
17531    undefs--;
17532  }
17533
17534  object->set_elements(*new_dict);
17535
17536  AllowHeapAllocation allocate_return_value;
17537  return isolate->factory()->NewNumberFromUint(result);
17538}
17539
17540
17541// Collects all defined (non-hole) and non-undefined (array) elements at
17542// the start of the elements array.
17543// If the object is in dictionary mode, it is converted to fast elements
17544// mode.
17545Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
17546                                                uint32_t limit) {
17547  Isolate* isolate = object->GetIsolate();
17548  if (object->HasSloppyArgumentsElements() ||
17549      object->map()->is_observed()) {
17550    return handle(Smi::FromInt(-1), isolate);
17551  }
17552
17553  if (object->HasDictionaryElements()) {
17554    // Convert to fast elements containing only the existing properties.
17555    // Ordering is irrelevant, since we are going to sort anyway.
17556    Handle<SeededNumberDictionary> dict(object->element_dictionary());
17557    if (object->IsJSArray() || dict->requires_slow_elements() ||
17558        dict->max_number_key() >= limit) {
17559      return JSObject::PrepareSlowElementsForSort(object, limit);
17560    }
17561    // Convert to fast elements.
17562
17563    Handle<Map> new_map =
17564        JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
17565
17566    PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
17567        NOT_TENURED: TENURED;
17568    Handle<FixedArray> fast_elements =
17569        isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
17570    dict->CopyValuesTo(*fast_elements);
17571    JSObject::ValidateElements(object);
17572
17573    JSObject::SetMapAndElements(object, new_map, fast_elements);
17574  } else if (object->HasFixedTypedArrayElements()) {
17575    // Typed arrays cannot have holes or undefined elements.
17576    return handle(Smi::FromInt(
17577        FixedArrayBase::cast(object->elements())->length()), isolate);
17578  } else if (!object->HasFastDoubleElements()) {
17579    EnsureWritableFastElements(object);
17580  }
17581  DCHECK(object->HasFastSmiOrObjectElements() ||
17582         object->HasFastDoubleElements());
17583
17584  // Collect holes at the end, undefined before that and the rest at the
17585  // start, and return the number of non-hole, non-undefined values.
17586
17587  Handle<FixedArrayBase> elements_base(object->elements());
17588  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
17589  if (limit > elements_length) {
17590    limit = elements_length;
17591  }
17592  if (limit == 0) {
17593    return handle(Smi::FromInt(0), isolate);
17594  }
17595
17596  uint32_t result = 0;
17597  if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
17598    FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
17599    // Split elements into defined and the_hole, in that order.
17600    unsigned int holes = limit;
17601    // Assume most arrays contain no holes and undefined values, so minimize the
17602    // number of stores of non-undefined, non-the-hole values.
17603    for (unsigned int i = 0; i < holes; i++) {
17604      if (elements->is_the_hole(i)) {
17605        holes--;
17606      } else {
17607        continue;
17608      }
17609      // Position i needs to be filled.
17610      while (holes > i) {
17611        if (elements->is_the_hole(holes)) {
17612          holes--;
17613        } else {
17614          elements->set(i, elements->get_scalar(holes));
17615          break;
17616        }
17617      }
17618    }
17619    result = holes;
17620    while (holes < limit) {
17621      elements->set_the_hole(holes);
17622      holes++;
17623    }
17624  } else {
17625    FixedArray* elements = FixedArray::cast(*elements_base);
17626    DisallowHeapAllocation no_gc;
17627
17628    // Split elements into defined, undefined and the_hole, in that order.  Only
17629    // count locations for undefined and the hole, and fill them afterwards.
17630    WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
17631    unsigned int undefs = limit;
17632    unsigned int holes = limit;
17633    // Assume most arrays contain no holes and undefined values, so minimize the
17634    // number of stores of non-undefined, non-the-hole values.
17635    for (unsigned int i = 0; i < undefs; i++) {
17636      Object* current = elements->get(i);
17637      if (current->IsTheHole()) {
17638        holes--;
17639        undefs--;
17640      } else if (current->IsUndefined()) {
17641        undefs--;
17642      } else {
17643        continue;
17644      }
17645      // Position i needs to be filled.
17646      while (undefs > i) {
17647        current = elements->get(undefs);
17648        if (current->IsTheHole()) {
17649          holes--;
17650          undefs--;
17651        } else if (current->IsUndefined()) {
17652          undefs--;
17653        } else {
17654          elements->set(i, current, write_barrier);
17655          break;
17656        }
17657      }
17658    }
17659    result = undefs;
17660    while (undefs < holes) {
17661      elements->set_undefined(undefs);
17662      undefs++;
17663    }
17664    while (holes < limit) {
17665      elements->set_the_hole(holes);
17666      holes++;
17667    }
17668  }
17669
17670  return isolate->factory()->NewNumberFromUint(result);
17671}
17672
17673
17674ExternalArrayType JSTypedArray::type() {
17675  switch (elements()->map()->instance_type()) {
17676#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
17677    case FIXED_##TYPE##_ARRAY_TYPE:                                           \
17678      return kExternal##Type##Array;
17679
17680    TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
17681#undef INSTANCE_TYPE_TO_ARRAY_TYPE
17682
17683    default:
17684      UNREACHABLE();
17685      return static_cast<ExternalArrayType>(-1);
17686  }
17687}
17688
17689
17690size_t JSTypedArray::element_size() {
17691  switch (elements()->map()->instance_type()) {
17692#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
17693  case FIXED_##TYPE##_ARRAY_TYPE:                                    \
17694    return size;
17695
17696    TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
17697#undef INSTANCE_TYPE_TO_ELEMENT_SIZE
17698
17699    default:
17700      UNREACHABLE();
17701      return 0;
17702  }
17703}
17704
17705
17706void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
17707                                            Handle<Name> name) {
17708  DCHECK(!global->HasFastProperties());
17709  auto dictionary = handle(global->global_dictionary());
17710  int entry = dictionary->FindEntry(name);
17711  if (entry == GlobalDictionary::kNotFound) return;
17712  PropertyCell::InvalidateEntry(dictionary, entry);
17713}
17714
17715
17716// TODO(ishell): rename to EnsureEmptyPropertyCell or something.
17717Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
17718    Handle<JSGlobalObject> global, Handle<Name> name) {
17719  DCHECK(!global->HasFastProperties());
17720  auto dictionary = handle(global->global_dictionary());
17721  int entry = dictionary->FindEntry(name);
17722  Handle<PropertyCell> cell;
17723  if (entry != GlobalDictionary::kNotFound) {
17724    // This call should be idempotent.
17725    DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
17726    cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
17727    DCHECK(cell->property_details().cell_type() ==
17728               PropertyCellType::kUninitialized ||
17729           cell->property_details().cell_type() ==
17730               PropertyCellType::kInvalidated);
17731    DCHECK(cell->value()->IsTheHole());
17732    return cell;
17733  }
17734  Isolate* isolate = global->GetIsolate();
17735  cell = isolate->factory()->NewPropertyCell();
17736  PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
17737  dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
17738  global->set_properties(*dictionary);
17739  return cell;
17740}
17741
17742
17743// This class is used for looking up two character strings in the string table.
17744// If we don't have a hit we don't want to waste much time so we unroll the
17745// string hash calculation loop here for speed.  Doesn't work if the two
17746// characters form a decimal integer, since such strings have a different hash
17747// algorithm.
17748class TwoCharHashTableKey : public HashTableKey {
17749 public:
17750  TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
17751    : c1_(c1), c2_(c2) {
17752    // Char 1.
17753    uint32_t hash = seed;
17754    hash += c1;
17755    hash += hash << 10;
17756    hash ^= hash >> 6;
17757    // Char 2.
17758    hash += c2;
17759    hash += hash << 10;
17760    hash ^= hash >> 6;
17761    // GetHash.
17762    hash += hash << 3;
17763    hash ^= hash >> 11;
17764    hash += hash << 15;
17765    if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
17766    hash_ = hash;
17767#ifdef DEBUG
17768    // If this assert fails then we failed to reproduce the two-character
17769    // version of the string hashing algorithm above.  One reason could be
17770    // that we were passed two digits as characters, since the hash
17771    // algorithm is different in that case.
17772    uint16_t chars[2] = {c1, c2};
17773    uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
17774    hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
17775    DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
17776#endif
17777  }
17778
17779  bool IsMatch(Object* o) override {
17780    if (!o->IsString()) return false;
17781    String* other = String::cast(o);
17782    if (other->length() != 2) return false;
17783    if (other->Get(0) != c1_) return false;
17784    return other->Get(1) == c2_;
17785  }
17786
17787  uint32_t Hash() override { return hash_; }
17788  uint32_t HashForObject(Object* key) override {
17789    if (!key->IsString()) return 0;
17790    return String::cast(key)->Hash();
17791  }
17792
17793  Handle<Object> AsHandle(Isolate* isolate) override {
17794    // The TwoCharHashTableKey is only used for looking in the string
17795    // table, not for adding to it.
17796    UNREACHABLE();
17797    return MaybeHandle<Object>().ToHandleChecked();
17798  }
17799
17800 private:
17801  uint16_t c1_;
17802  uint16_t c2_;
17803  uint32_t hash_;
17804};
17805
17806
17807MaybeHandle<String> StringTable::InternalizeStringIfExists(
17808    Isolate* isolate,
17809    Handle<String> string) {
17810  if (string->IsInternalizedString()) {
17811    return string;
17812  }
17813  return LookupStringIfExists(isolate, string);
17814}
17815
17816
17817MaybeHandle<String> StringTable::LookupStringIfExists(
17818    Isolate* isolate,
17819    Handle<String> string) {
17820  Handle<StringTable> string_table = isolate->factory()->string_table();
17821  InternalizedStringKey key(string);
17822  int entry = string_table->FindEntry(&key);
17823  if (entry == kNotFound) {
17824    return MaybeHandle<String>();
17825  } else {
17826    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
17827    DCHECK(StringShape(*result).IsInternalized());
17828    return result;
17829  }
17830}
17831
17832
17833MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
17834    Isolate* isolate,
17835    uint16_t c1,
17836    uint16_t c2) {
17837  Handle<StringTable> string_table = isolate->factory()->string_table();
17838  TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
17839  int entry = string_table->FindEntry(&key);
17840  if (entry == kNotFound) {
17841    return MaybeHandle<String>();
17842  } else {
17843    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
17844    DCHECK(StringShape(*result).IsInternalized());
17845    return result;
17846  }
17847}
17848
17849
17850void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
17851                                                   int expected) {
17852  Handle<StringTable> table = isolate->factory()->string_table();
17853  // We need a key instance for the virtual hash function.
17854  InternalizedStringKey dummy_key(Handle<String>::null());
17855  table = StringTable::EnsureCapacity(table, expected, &dummy_key);
17856  isolate->heap()->SetRootStringTable(*table);
17857}
17858
17859
17860Handle<String> StringTable::LookupString(Isolate* isolate,
17861                                         Handle<String> string) {
17862  InternalizedStringKey key(string);
17863  return LookupKey(isolate, &key);
17864}
17865
17866
17867Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
17868  Handle<StringTable> table = isolate->factory()->string_table();
17869  int entry = table->FindEntry(key);
17870
17871  // String already in table.
17872  if (entry != kNotFound) {
17873    return handle(String::cast(table->KeyAt(entry)), isolate);
17874  }
17875
17876  // Adding new string. Grow table if needed.
17877  table = StringTable::EnsureCapacity(table, 1, key);
17878
17879  // Create string object.
17880  Handle<Object> string = key->AsHandle(isolate);
17881  // There must be no attempts to internalize strings that could throw
17882  // InvalidStringLength error.
17883  CHECK(!string.is_null());
17884
17885  // Add the new string and return it along with the string table.
17886  entry = table->FindInsertionEntry(key->Hash());
17887  table->set(EntryToIndex(entry), *string);
17888  table->ElementAdded();
17889
17890  isolate->heap()->SetRootStringTable(*table);
17891  return Handle<String>::cast(string);
17892}
17893
17894
17895String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
17896  Handle<StringTable> table = isolate->factory()->string_table();
17897  int entry = table->FindEntry(key);
17898  if (entry != kNotFound) return String::cast(table->KeyAt(entry));
17899  return NULL;
17900}
17901
17902
17903Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
17904                                             Handle<Context> context,
17905                                             LanguageMode language_mode) {
17906  Isolate* isolate = GetIsolate();
17907  Handle<SharedFunctionInfo> shared(context->closure()->shared());
17908  StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
17909  int entry = FindEntry(&key);
17910  if (entry == kNotFound) return isolate->factory()->undefined_value();
17911  int index = EntryToIndex(entry);
17912  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
17913  return Handle<Object>(get(index + 1), isolate);
17914}
17915
17916
17917Handle<Object> CompilationCacheTable::LookupEval(
17918    Handle<String> src, Handle<SharedFunctionInfo> outer_info,
17919    LanguageMode language_mode, int scope_position) {
17920  Isolate* isolate = GetIsolate();
17921  // Cache key is the tuple (source, outer shared function info, scope position)
17922  // to unambiguously identify the context chain the cached eval code assumes.
17923  StringSharedKey key(src, outer_info, language_mode, scope_position);
17924  int entry = FindEntry(&key);
17925  if (entry == kNotFound) return isolate->factory()->undefined_value();
17926  int index = EntryToIndex(entry);
17927  if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
17928  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
17929}
17930
17931
17932Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
17933                                                   JSRegExp::Flags flags) {
17934  Isolate* isolate = GetIsolate();
17935  DisallowHeapAllocation no_allocation;
17936  RegExpKey key(src, flags);
17937  int entry = FindEntry(&key);
17938  if (entry == kNotFound) return isolate->factory()->undefined_value();
17939  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
17940}
17941
17942
17943Handle<CompilationCacheTable> CompilationCacheTable::Put(
17944    Handle<CompilationCacheTable> cache, Handle<String> src,
17945    Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
17946  Isolate* isolate = cache->GetIsolate();
17947  Handle<SharedFunctionInfo> shared(context->closure()->shared());
17948  StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
17949  {
17950    Handle<Object> k = key.AsHandle(isolate);
17951    DisallowHeapAllocation no_allocation_scope;
17952    int entry = cache->FindEntry(&key);
17953    if (entry != kNotFound) {
17954      cache->set(EntryToIndex(entry), *k);
17955      cache->set(EntryToIndex(entry) + 1, *value);
17956      return cache;
17957    }
17958  }
17959
17960  cache = EnsureCapacity(cache, 1, &key);
17961  int entry = cache->FindInsertionEntry(key.Hash());
17962  Handle<Object> k =
17963      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
17964  cache->set(EntryToIndex(entry), *k);
17965  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
17966  cache->ElementAdded();
17967  return cache;
17968}
17969
17970
17971Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
17972    Handle<CompilationCacheTable> cache, Handle<String> src,
17973    Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
17974    int scope_position) {
17975  Isolate* isolate = cache->GetIsolate();
17976  StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
17977  {
17978    Handle<Object> k = key.AsHandle(isolate);
17979    DisallowHeapAllocation no_allocation_scope;
17980    int entry = cache->FindEntry(&key);
17981    if (entry != kNotFound) {
17982      cache->set(EntryToIndex(entry), *k);
17983      cache->set(EntryToIndex(entry) + 1, *value);
17984      return cache;
17985    }
17986  }
17987
17988  cache = EnsureCapacity(cache, 1, &key);
17989  int entry = cache->FindInsertionEntry(key.Hash());
17990  Handle<Object> k =
17991      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
17992  cache->set(EntryToIndex(entry), *k);
17993  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
17994  cache->ElementAdded();
17995  return cache;
17996}
17997
17998
17999Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
18000      Handle<CompilationCacheTable> cache, Handle<String> src,
18001      JSRegExp::Flags flags, Handle<FixedArray> value) {
18002  RegExpKey key(src, flags);
18003  cache = EnsureCapacity(cache, 1, &key);
18004  int entry = cache->FindInsertionEntry(key.Hash());
18005  // We store the value in the key slot, and compare the search key
18006  // to the stored value with a custon IsMatch function during lookups.
18007  cache->set(EntryToIndex(entry), *value);
18008  cache->set(EntryToIndex(entry) + 1, *value);
18009  cache->ElementAdded();
18010  return cache;
18011}
18012
18013
18014void CompilationCacheTable::Age() {
18015  DisallowHeapAllocation no_allocation;
18016  Object* the_hole_value = GetHeap()->the_hole_value();
18017  for (int entry = 0, size = Capacity(); entry < size; entry++) {
18018    int entry_index = EntryToIndex(entry);
18019    int value_index = entry_index + 1;
18020
18021    if (get(entry_index)->IsNumber()) {
18022      Smi* count = Smi::cast(get(value_index));
18023      count = Smi::FromInt(count->value() - 1);
18024      if (count->value() == 0) {
18025        NoWriteBarrierSet(this, entry_index, the_hole_value);
18026        NoWriteBarrierSet(this, value_index, the_hole_value);
18027        ElementRemoved();
18028      } else {
18029        NoWriteBarrierSet(this, value_index, count);
18030      }
18031    } else if (get(entry_index)->IsFixedArray()) {
18032      SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
18033      if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
18034        NoWriteBarrierSet(this, entry_index, the_hole_value);
18035        NoWriteBarrierSet(this, value_index, the_hole_value);
18036        ElementRemoved();
18037      }
18038    }
18039  }
18040}
18041
18042
18043void CompilationCacheTable::Remove(Object* value) {
18044  DisallowHeapAllocation no_allocation;
18045  Object* the_hole_value = GetHeap()->the_hole_value();
18046  for (int entry = 0, size = Capacity(); entry < size; entry++) {
18047    int entry_index = EntryToIndex(entry);
18048    int value_index = entry_index + 1;
18049    if (get(value_index) == value) {
18050      NoWriteBarrierSet(this, entry_index, the_hole_value);
18051      NoWriteBarrierSet(this, value_index, the_hole_value);
18052      ElementRemoved();
18053    }
18054  }
18055  return;
18056}
18057
18058
18059// StringsKey used for HashTable where key is array of internalized strings.
18060class StringsKey : public HashTableKey {
18061 public:
18062  explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
18063
18064  bool IsMatch(Object* strings) override {
18065    FixedArray* o = FixedArray::cast(strings);
18066    int len = strings_->length();
18067    if (o->length() != len) return false;
18068    for (int i = 0; i < len; i++) {
18069      if (o->get(i) != strings_->get(i)) return false;
18070    }
18071    return true;
18072  }
18073
18074  uint32_t Hash() override { return HashForObject(*strings_); }
18075
18076  uint32_t HashForObject(Object* obj) override {
18077    FixedArray* strings = FixedArray::cast(obj);
18078    int len = strings->length();
18079    uint32_t hash = 0;
18080    for (int i = 0; i < len; i++) {
18081      hash ^= String::cast(strings->get(i))->Hash();
18082    }
18083    return hash;
18084  }
18085
18086  Handle<Object> AsHandle(Isolate* isolate) override { return strings_; }
18087
18088 private:
18089  Handle<FixedArray> strings_;
18090};
18091
18092
18093template<typename Derived, typename Shape, typename Key>
18094Handle<Derived> Dictionary<Derived, Shape, Key>::New(
18095    Isolate* isolate,
18096    int at_least_space_for,
18097    PretenureFlag pretenure) {
18098  DCHECK(0 <= at_least_space_for);
18099  Handle<Derived> dict = DerivedHashTable::New(isolate,
18100                                               at_least_space_for,
18101                                               USE_DEFAULT_MINIMUM_CAPACITY,
18102                                               pretenure);
18103
18104  // Initialize the next enumeration index.
18105  dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
18106  return dict;
18107}
18108
18109
18110template <typename Derived, typename Shape, typename Key>
18111Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
18112    Handle<Derived> dictionary) {
18113  Factory* factory = dictionary->GetIsolate()->factory();
18114  int length = dictionary->NumberOfElements();
18115
18116  Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
18117  Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
18118
18119  // Fill both the iteration order array and the enumeration order array
18120  // with property details.
18121  int capacity = dictionary->Capacity();
18122  int pos = 0;
18123  for (int i = 0; i < capacity; i++) {
18124    if (dictionary->IsKey(dictionary->KeyAt(i))) {
18125      int index = dictionary->DetailsAt(i).dictionary_index();
18126      iteration_order->set(pos, Smi::FromInt(i));
18127      enumeration_order->set(pos, Smi::FromInt(index));
18128      pos++;
18129    }
18130  }
18131  DCHECK(pos == length);
18132
18133  // Sort the arrays wrt. enumeration order.
18134  iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
18135  return iteration_order;
18136}
18137
18138
18139template <typename Derived, typename Shape, typename Key>
18140Handle<FixedArray>
18141Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
18142    Handle<Derived> dictionary) {
18143  int length = dictionary->NumberOfElements();
18144
18145  Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
18146  DCHECK(iteration_order->length() == length);
18147
18148  // Iterate over the dictionary using the enumeration order and update
18149  // the dictionary with new enumeration indices.
18150  for (int i = 0; i < length; i++) {
18151    int index = Smi::cast(iteration_order->get(i))->value();
18152    DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
18153
18154    int enum_index = PropertyDetails::kInitialIndex + i;
18155
18156    PropertyDetails details = dictionary->DetailsAt(index);
18157    PropertyDetails new_details = details.set_index(enum_index);
18158    dictionary->DetailsAtPut(index, new_details);
18159  }
18160
18161  // Set the next enumeration index.
18162  dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
18163  return iteration_order;
18164}
18165
18166
18167template <typename Derived, typename Shape, typename Key>
18168void Dictionary<Derived, Shape, Key>::SetRequiresCopyOnCapacityChange() {
18169  DCHECK_EQ(0, DerivedHashTable::NumberOfElements());
18170  DCHECK_EQ(0, DerivedHashTable::NumberOfDeletedElements());
18171  // Make sure that HashTable::EnsureCapacity will create a copy.
18172  DerivedHashTable::SetNumberOfDeletedElements(DerivedHashTable::Capacity());
18173  DCHECK(!DerivedHashTable::HasSufficientCapacity(1));
18174}
18175
18176
18177template <typename Derived, typename Shape, typename Key>
18178Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
18179    Handle<Derived> dictionary, int n, Key key) {
18180  // Check whether there are enough enumeration indices to add n elements.
18181  if (Shape::kIsEnumerable &&
18182      !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
18183    // If not, we generate new indices for the properties.
18184    GenerateNewEnumerationIndices(dictionary);
18185  }
18186  return DerivedHashTable::EnsureCapacity(dictionary, n, key);
18187}
18188
18189
18190template <typename Derived, typename Shape, typename Key>
18191Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
18192    Handle<Derived> dictionary, int entry) {
18193  Factory* factory = dictionary->GetIsolate()->factory();
18194  PropertyDetails details = dictionary->DetailsAt(entry);
18195  if (!details.IsConfigurable()) return factory->false_value();
18196
18197  dictionary->SetEntry(
18198      entry, factory->the_hole_value(), factory->the_hole_value());
18199  dictionary->ElementRemoved();
18200  return factory->true_value();
18201}
18202
18203
18204template<typename Derived, typename Shape, typename Key>
18205Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
18206    Handle<Derived> dictionary, Key key, Handle<Object> value) {
18207  int entry = dictionary->FindEntry(key);
18208
18209  // If the entry is present set the value;
18210  if (entry != Dictionary::kNotFound) {
18211    dictionary->ValueAtPut(entry, *value);
18212    return dictionary;
18213  }
18214
18215  // Check whether the dictionary should be extended.
18216  dictionary = EnsureCapacity(dictionary, 1, key);
18217#ifdef DEBUG
18218  USE(Shape::AsHandle(dictionary->GetIsolate(), key));
18219#endif
18220  PropertyDetails details = PropertyDetails::Empty();
18221
18222  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
18223  return dictionary;
18224}
18225
18226
18227template<typename Derived, typename Shape, typename Key>
18228Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
18229    Handle<Derived> dictionary,
18230    Key key,
18231    Handle<Object> value,
18232    PropertyDetails details) {
18233  // Valdate key is absent.
18234  SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
18235  // Check whether the dictionary should be extended.
18236  dictionary = EnsureCapacity(dictionary, 1, key);
18237
18238  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
18239  return dictionary;
18240}
18241
18242
18243// Add a key, value pair to the dictionary.
18244template<typename Derived, typename Shape, typename Key>
18245void Dictionary<Derived, Shape, Key>::AddEntry(
18246    Handle<Derived> dictionary,
18247    Key key,
18248    Handle<Object> value,
18249    PropertyDetails details,
18250    uint32_t hash) {
18251  // Compute the key object.
18252  Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
18253
18254  uint32_t entry = dictionary->FindInsertionEntry(hash);
18255  // Insert element at empty or deleted entry
18256  if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
18257    // Assign an enumeration index to the property and update
18258    // SetNextEnumerationIndex.
18259    int index = dictionary->NextEnumerationIndex();
18260    details = details.set_index(index);
18261    dictionary->SetNextEnumerationIndex(index + 1);
18262  }
18263  dictionary->SetEntry(entry, k, value, details);
18264  DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
18265          dictionary->KeyAt(entry)->IsName()));
18266  dictionary->ElementAdded();
18267}
18268
18269
18270void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key,
18271                                                bool used_as_prototype) {
18272  DisallowHeapAllocation no_allocation;
18273  // If the dictionary requires slow elements an element has already
18274  // been added at a high index.
18275  if (requires_slow_elements()) return;
18276  // Check if this index is high enough that we should require slow
18277  // elements.
18278  if (key > kRequiresSlowElementsLimit) {
18279    if (used_as_prototype) {
18280      // TODO(verwaest): Remove this hack.
18281      TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
18282    }
18283    set_requires_slow_elements();
18284    return;
18285  }
18286  // Update max key value.
18287  Object* max_index_object = get(kMaxNumberKeyIndex);
18288  if (!max_index_object->IsSmi() || max_number_key() < key) {
18289    FixedArray::set(kMaxNumberKeyIndex,
18290                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
18291  }
18292}
18293
18294
18295Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
18296    Handle<SeededNumberDictionary> dictionary, uint32_t key,
18297    Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
18298  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
18299  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18300  return Add(dictionary, key, value, details);
18301}
18302
18303
18304Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
18305    Handle<UnseededNumberDictionary> dictionary,
18306    uint32_t key,
18307    Handle<Object> value) {
18308  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18309  return Add(dictionary, key, value, PropertyDetails::Empty());
18310}
18311
18312
18313Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
18314    Handle<SeededNumberDictionary> dictionary, uint32_t key,
18315    Handle<Object> value, bool used_as_prototype) {
18316  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
18317  return AtPut(dictionary, key, value);
18318}
18319
18320
18321Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
18322    Handle<UnseededNumberDictionary> dictionary,
18323    uint32_t key,
18324    Handle<Object> value) {
18325  return AtPut(dictionary, key, value);
18326}
18327
18328
18329Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
18330    Handle<SeededNumberDictionary> dictionary, uint32_t key,
18331    Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
18332  int entry = dictionary->FindEntry(key);
18333  if (entry == kNotFound) {
18334    return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
18335  }
18336  // Preserve enumeration index.
18337  details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
18338  Handle<Object> object_key =
18339      SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
18340  dictionary->SetEntry(entry, object_key, value, details);
18341  return dictionary;
18342}
18343
18344
18345Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
18346    Handle<UnseededNumberDictionary> dictionary,
18347    uint32_t key,
18348    Handle<Object> value) {
18349  int entry = dictionary->FindEntry(key);
18350  if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
18351  Handle<Object> object_key =
18352      UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
18353  dictionary->SetEntry(entry, object_key, value);
18354  return dictionary;
18355}
18356
18357
18358template <typename Derived, typename Shape, typename Key>
18359int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
18360    PropertyFilter filter) {
18361  int capacity = this->Capacity();
18362  int result = 0;
18363  for (int i = 0; i < capacity; i++) {
18364    Object* k = this->KeyAt(i);
18365    if (this->IsKey(k) && !k->FilterKey(filter)) {
18366      if (this->IsDeleted(i)) continue;
18367      PropertyDetails details = this->DetailsAt(i);
18368      PropertyAttributes attr = details.attributes();
18369      if ((attr & filter) == 0) result++;
18370    }
18371  }
18372  return result;
18373}
18374
18375
18376template <typename Derived, typename Shape, typename Key>
18377bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
18378  int capacity = this->Capacity();
18379  for (int i = 0; i < capacity; i++) {
18380    Object* k = this->KeyAt(i);
18381    if (this->IsKey(k) && !k->FilterKey(ALL_PROPERTIES)) {
18382      if (this->IsDeleted(i)) continue;
18383      PropertyDetails details = this->DetailsAt(i);
18384      if (details.type() == ACCESSOR_CONSTANT) return true;
18385      PropertyAttributes attr = details.attributes();
18386      if (attr & ALL_ATTRIBUTES_MASK) return true;
18387    }
18388  }
18389  return false;
18390}
18391
18392
18393template <typename Dictionary>
18394struct EnumIndexComparator {
18395  explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
18396  bool operator() (Smi* a, Smi* b) {
18397    PropertyDetails da(dict->DetailsAt(a->value()));
18398    PropertyDetails db(dict->DetailsAt(b->value()));
18399    return da.dictionary_index() < db.dictionary_index();
18400  }
18401  Dictionary* dict;
18402};
18403
18404
18405template <typename Derived, typename Shape, typename Key>
18406void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
18407  int length = storage->length();
18408  int capacity = this->Capacity();
18409  int properties = 0;
18410  for (int i = 0; i < capacity; i++) {
18411    Object* k = this->KeyAt(i);
18412    if (this->IsKey(k) && !k->IsSymbol()) {
18413      PropertyDetails details = this->DetailsAt(i);
18414      if (details.IsDontEnum() || this->IsDeleted(i)) continue;
18415      storage->set(properties, Smi::FromInt(i));
18416      properties++;
18417      if (properties == length) break;
18418    }
18419  }
18420  CHECK_EQ(length, properties);
18421  EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
18422  Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
18423  std::sort(start, start + length, cmp);
18424  for (int i = 0; i < length; i++) {
18425    int index = Smi::cast(storage->get(i))->value();
18426    storage->set(i, this->KeyAt(index));
18427  }
18428}
18429
18430
18431template <typename Derived, typename Shape, typename Key>
18432int Dictionary<Derived, Shape, Key>::CopyKeysTo(
18433    FixedArray* storage, int index, PropertyFilter filter,
18434    typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
18435  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
18436  int start_index = index;
18437  int capacity = this->Capacity();
18438  for (int i = 0; i < capacity; i++) {
18439    Object* k = this->KeyAt(i);
18440    if (!this->IsKey(k) || k->FilterKey(filter)) continue;
18441    if (this->IsDeleted(i)) continue;
18442    PropertyDetails details = this->DetailsAt(i);
18443    PropertyAttributes attr = details.attributes();
18444    if ((attr & filter) != 0) continue;
18445    storage->set(index++, k);
18446  }
18447  if (sort_mode == Dictionary::SORTED) {
18448    storage->SortPairs(storage, index);
18449  }
18450  DCHECK(storage->length() >= index);
18451  return index - start_index;
18452}
18453
18454
18455template <typename Derived, typename Shape, typename Key>
18456void Dictionary<Derived, Shape, Key>::CollectKeysTo(
18457    Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
18458    PropertyFilter filter) {
18459  int capacity = dictionary->Capacity();
18460  Handle<FixedArray> array =
18461      keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
18462  int array_size = 0;
18463
18464  {
18465    DisallowHeapAllocation no_gc;
18466    Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
18467    for (int i = 0; i < capacity; i++) {
18468      Object* k = raw_dict->KeyAt(i);
18469      if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
18470      if (raw_dict->IsDeleted(i)) continue;
18471      PropertyDetails details = raw_dict->DetailsAt(i);
18472      if ((details.attributes() & filter) != 0) continue;
18473      if (filter & ONLY_ALL_CAN_READ) {
18474        if (details.kind() != kAccessor) continue;
18475        Object* accessors = raw_dict->ValueAt(i);
18476        if (accessors->IsPropertyCell()) {
18477          accessors = PropertyCell::cast(accessors)->value();
18478        }
18479        if (!accessors->IsAccessorInfo()) continue;
18480        if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
18481      }
18482      array->set(array_size++, Smi::FromInt(i));
18483    }
18484
18485    EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
18486    Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
18487    std::sort(start, start + array_size, cmp);
18488  }
18489
18490  for (int i = 0; i < array_size; i++) {
18491    int index = Smi::cast(array->get(i))->value();
18492    keys->AddKey(dictionary->KeyAt(index));
18493  }
18494}
18495
18496
18497// Backwards lookup (slow).
18498template<typename Derived, typename Shape, typename Key>
18499Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
18500  int capacity = this->Capacity();
18501  for (int i = 0; i < capacity; i++) {
18502    Object* k = this->KeyAt(i);
18503    if (this->IsKey(k)) {
18504      Object* e = this->ValueAt(i);
18505      // TODO(dcarney): this should be templatized.
18506      if (e->IsPropertyCell()) {
18507        e = PropertyCell::cast(e)->value();
18508      }
18509      if (e == value) return k;
18510    }
18511  }
18512  Heap* heap = Dictionary::GetHeap();
18513  return heap->undefined_value();
18514}
18515
18516
18517Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
18518                                int32_t hash) {
18519  DisallowHeapAllocation no_gc;
18520  DCHECK(IsKey(*key));
18521
18522  int entry = FindEntry(isolate, key, hash);
18523  if (entry == kNotFound) return isolate->heap()->the_hole_value();
18524  return get(EntryToIndex(entry) + 1);
18525}
18526
18527
18528Object* ObjectHashTable::Lookup(Handle<Object> key) {
18529  DisallowHeapAllocation no_gc;
18530  DCHECK(IsKey(*key));
18531
18532  Isolate* isolate = GetIsolate();
18533
18534  // If the object does not have an identity hash, it was never used as a key.
18535  Object* hash = key->GetHash();
18536  if (hash->IsUndefined()) {
18537    return isolate->heap()->the_hole_value();
18538  }
18539  return Lookup(isolate, key, Smi::cast(hash)->value());
18540}
18541
18542
18543Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
18544  return Lookup(GetIsolate(), key, hash);
18545}
18546
18547
18548Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
18549                                             Handle<Object> key,
18550                                             Handle<Object> value) {
18551  DCHECK(table->IsKey(*key));
18552  DCHECK(!value->IsTheHole());
18553
18554  Isolate* isolate = table->GetIsolate();
18555  // Make sure the key object has an identity hash code.
18556  int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
18557
18558  return Put(table, key, value, hash);
18559}
18560
18561
18562Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
18563                                             Handle<Object> key,
18564                                             Handle<Object> value,
18565                                             int32_t hash) {
18566  DCHECK(table->IsKey(*key));
18567  DCHECK(!value->IsTheHole());
18568
18569  Isolate* isolate = table->GetIsolate();
18570
18571  int entry = table->FindEntry(isolate, key, hash);
18572
18573  // Key is already in table, just overwrite value.
18574  if (entry != kNotFound) {
18575    table->set(EntryToIndex(entry) + 1, *value);
18576    return table;
18577  }
18578
18579  // Check whether the hash table should be extended.
18580  table = EnsureCapacity(table, 1, key);
18581  table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
18582  return table;
18583}
18584
18585
18586Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
18587                                                Handle<Object> key,
18588                                                bool* was_present) {
18589  DCHECK(table->IsKey(*key));
18590
18591  Object* hash = key->GetHash();
18592  if (hash->IsUndefined()) {
18593    *was_present = false;
18594    return table;
18595  }
18596
18597  return Remove(table, key, was_present, Smi::cast(hash)->value());
18598}
18599
18600
18601Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
18602                                                Handle<Object> key,
18603                                                bool* was_present,
18604                                                int32_t hash) {
18605  DCHECK(table->IsKey(*key));
18606
18607  int entry = table->FindEntry(table->GetIsolate(), key, hash);
18608  if (entry == kNotFound) {
18609    *was_present = false;
18610    return table;
18611  }
18612
18613  *was_present = true;
18614  table->RemoveEntry(entry);
18615  return Shrink(table, key);
18616}
18617
18618
18619void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
18620  set(EntryToIndex(entry), key);
18621  set(EntryToIndex(entry) + 1, value);
18622  ElementAdded();
18623}
18624
18625
18626void ObjectHashTable::RemoveEntry(int entry) {
18627  set_the_hole(EntryToIndex(entry));
18628  set_the_hole(EntryToIndex(entry) + 1);
18629  ElementRemoved();
18630}
18631
18632
18633Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
18634  DisallowHeapAllocation no_gc;
18635  DCHECK(IsKey(*key));
18636  int entry = FindEntry(key);
18637  if (entry == kNotFound) return GetHeap()->the_hole_value();
18638  return get(EntryToValueIndex(entry));
18639}
18640
18641
18642Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
18643                                         Handle<HeapObject> key,
18644                                         Handle<HeapObject> value) {
18645  DCHECK(table->IsKey(*key));
18646  int entry = table->FindEntry(key);
18647  // Key is already in table, just overwrite value.
18648  if (entry != kNotFound) {
18649    table->set(EntryToValueIndex(entry), *value);
18650    return table;
18651  }
18652
18653  Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
18654
18655  // Check whether the hash table should be extended.
18656  table = EnsureCapacity(table, 1, key, TENURED);
18657
18658  table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
18659  return table;
18660}
18661
18662
18663void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
18664                             Handle<HeapObject> value) {
18665  DisallowHeapAllocation no_allocation;
18666  set(EntryToIndex(entry), *key_cell);
18667  set(EntryToValueIndex(entry), *value);
18668  ElementAdded();
18669}
18670
18671
18672template<class Derived, class Iterator, int entrysize>
18673Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
18674    Isolate* isolate, int capacity, PretenureFlag pretenure) {
18675  // Capacity must be a power of two, since we depend on being able
18676  // to divide and multiple by 2 (kLoadFactor) to derive capacity
18677  // from number of buckets. If we decide to change kLoadFactor
18678  // to something other than 2, capacity should be stored as another
18679  // field of this object.
18680  capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
18681  if (capacity > kMaxCapacity) {
18682    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
18683  }
18684  int num_buckets = capacity / kLoadFactor;
18685  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
18686      kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
18687  backing_store->set_map_no_write_barrier(
18688      isolate->heap()->ordered_hash_table_map());
18689  Handle<Derived> table = Handle<Derived>::cast(backing_store);
18690  for (int i = 0; i < num_buckets; ++i) {
18691    table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
18692  }
18693  table->SetNumberOfBuckets(num_buckets);
18694  table->SetNumberOfElements(0);
18695  table->SetNumberOfDeletedElements(0);
18696  return table;
18697}
18698
18699
18700template<class Derived, class Iterator, int entrysize>
18701Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
18702    Handle<Derived> table) {
18703  DCHECK(!table->IsObsolete());
18704
18705  int nof = table->NumberOfElements();
18706  int nod = table->NumberOfDeletedElements();
18707  int capacity = table->Capacity();
18708  if ((nof + nod) < capacity) return table;
18709  // Don't need to grow if we can simply clear out deleted entries instead.
18710  // Note that we can't compact in place, though, so we always allocate
18711  // a new table.
18712  return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
18713}
18714
18715
18716template<class Derived, class Iterator, int entrysize>
18717Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
18718    Handle<Derived> table) {
18719  DCHECK(!table->IsObsolete());
18720
18721  int nof = table->NumberOfElements();
18722  int capacity = table->Capacity();
18723  if (nof >= (capacity >> 2)) return table;
18724  return Rehash(table, capacity / 2);
18725}
18726
18727
18728template<class Derived, class Iterator, int entrysize>
18729Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
18730    Handle<Derived> table) {
18731  DCHECK(!table->IsObsolete());
18732
18733  Handle<Derived> new_table =
18734      Allocate(table->GetIsolate(),
18735               kMinCapacity,
18736               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
18737
18738  table->SetNextTable(*new_table);
18739  table->SetNumberOfDeletedElements(kClearedTableSentinel);
18740
18741  return new_table;
18742}
18743
18744template <class Derived, class Iterator, int entrysize>
18745bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
18746    Handle<Derived> table, Handle<Object> key) {
18747  int entry = table->KeyToFirstEntry(*key);
18748  // Walk the chain in the bucket to find the key.
18749  while (entry != kNotFound) {
18750    Object* candidate_key = table->KeyAt(entry);
18751    if (candidate_key->SameValueZero(*key)) return true;
18752    entry = table->NextChainEntry(entry);
18753  }
18754  return false;
18755}
18756
18757
18758Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
18759                                           Handle<Object> key) {
18760  int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
18761  int entry = table->HashToEntry(hash);
18762  // Walk the chain of the bucket and try finding the key.
18763  while (entry != kNotFound) {
18764    Object* candidate_key = table->KeyAt(entry);
18765    // Do not add if we have the key already
18766    if (candidate_key->SameValueZero(*key)) return table;
18767    entry = table->NextChainEntry(entry);
18768  }
18769
18770  table = OrderedHashSet::EnsureGrowable(table);
18771  // Read the existing bucket values.
18772  int bucket = table->HashToBucket(hash);
18773  int previous_entry = table->HashToEntry(hash);
18774  int nof = table->NumberOfElements();
18775  // Insert a new entry at the end,
18776  int new_entry = nof + table->NumberOfDeletedElements();
18777  int new_index = table->EntryToIndex(new_entry);
18778  table->set(new_index, *key);
18779  table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
18780  // and point the bucket to the new entry.
18781  table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
18782  table->SetNumberOfElements(nof + 1);
18783  return table;
18784}
18785
18786
18787template<class Derived, class Iterator, int entrysize>
18788Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
18789    Handle<Derived> table, int new_capacity) {
18790  DCHECK(!table->IsObsolete());
18791
18792  Handle<Derived> new_table =
18793      Allocate(table->GetIsolate(),
18794               new_capacity,
18795               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
18796  int nof = table->NumberOfElements();
18797  int nod = table->NumberOfDeletedElements();
18798  int new_buckets = new_table->NumberOfBuckets();
18799  int new_entry = 0;
18800  int removed_holes_index = 0;
18801
18802  for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
18803    Object* key = table->KeyAt(old_entry);
18804    if (key->IsTheHole()) {
18805      table->SetRemovedIndexAt(removed_holes_index++, old_entry);
18806      continue;
18807    }
18808
18809    Object* hash = key->GetHash();
18810    int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
18811    Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
18812    new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
18813    int new_index = new_table->EntryToIndex(new_entry);
18814    int old_index = table->EntryToIndex(old_entry);
18815    for (int i = 0; i < entrysize; ++i) {
18816      Object* value = table->get(old_index + i);
18817      new_table->set(new_index + i, value);
18818    }
18819    new_table->set(new_index + kChainOffset, chain_entry);
18820    ++new_entry;
18821  }
18822
18823  DCHECK_EQ(nod, removed_holes_index);
18824
18825  new_table->SetNumberOfElements(nof);
18826  table->SetNextTable(*new_table);
18827
18828  return new_table;
18829}
18830
18831
18832template Handle<OrderedHashSet>
18833OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
18834    Isolate* isolate, int capacity, PretenureFlag pretenure);
18835
18836template Handle<OrderedHashSet>
18837OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
18838    Handle<OrderedHashSet> table);
18839
18840template Handle<OrderedHashSet>
18841OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
18842    Handle<OrderedHashSet> table);
18843
18844template Handle<OrderedHashSet>
18845OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
18846    Handle<OrderedHashSet> table);
18847
18848template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
18849    Handle<OrderedHashSet> table, Handle<Object> key);
18850
18851
18852template Handle<OrderedHashMap>
18853OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
18854    Isolate* isolate, int capacity, PretenureFlag pretenure);
18855
18856template Handle<OrderedHashMap>
18857OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
18858    Handle<OrderedHashMap> table);
18859
18860template Handle<OrderedHashMap>
18861OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
18862    Handle<OrderedHashMap> table);
18863
18864template Handle<OrderedHashMap>
18865OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
18866    Handle<OrderedHashMap> table);
18867
18868template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
18869    Handle<OrderedHashMap> table, Handle<Object> key);
18870
18871
18872template<class Derived, class TableType>
18873void OrderedHashTableIterator<Derived, TableType>::Transition() {
18874  DisallowHeapAllocation no_allocation;
18875  TableType* table = TableType::cast(this->table());
18876  if (!table->IsObsolete()) return;
18877
18878  int index = Smi::cast(this->index())->value();
18879  while (table->IsObsolete()) {
18880    TableType* next_table = table->NextTable();
18881
18882    if (index > 0) {
18883      int nod = table->NumberOfDeletedElements();
18884
18885      if (nod == TableType::kClearedTableSentinel) {
18886        index = 0;
18887      } else {
18888        int old_index = index;
18889        for (int i = 0; i < nod; ++i) {
18890          int removed_index = table->RemovedIndexAt(i);
18891          if (removed_index >= old_index) break;
18892          --index;
18893        }
18894      }
18895    }
18896
18897    table = next_table;
18898  }
18899
18900  set_table(table);
18901  set_index(Smi::FromInt(index));
18902}
18903
18904
18905template<class Derived, class TableType>
18906bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
18907  DisallowHeapAllocation no_allocation;
18908  if (this->table()->IsUndefined()) return false;
18909
18910  Transition();
18911
18912  TableType* table = TableType::cast(this->table());
18913  int index = Smi::cast(this->index())->value();
18914  int used_capacity = table->UsedCapacity();
18915
18916  while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
18917    index++;
18918  }
18919
18920  set_index(Smi::FromInt(index));
18921
18922  if (index < used_capacity) return true;
18923
18924  set_table(GetHeap()->undefined_value());
18925  return false;
18926}
18927
18928
18929template<class Derived, class TableType>
18930Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
18931  DisallowHeapAllocation no_allocation;
18932  if (HasMore()) {
18933    FixedArray* array = FixedArray::cast(value_array->elements());
18934    static_cast<Derived*>(this)->PopulateValueArray(array);
18935    MoveNext();
18936    return Smi::cast(kind());
18937  }
18938  return Smi::FromInt(0);
18939}
18940
18941
18942template Smi*
18943OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
18944    JSArray* value_array);
18945
18946template bool
18947OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
18948
18949template void
18950OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
18951
18952template Object*
18953OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
18954
18955template void
18956OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
18957
18958
18959template Smi*
18960OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
18961    JSArray* value_array);
18962
18963template bool
18964OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
18965
18966template void
18967OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
18968
18969template Object*
18970OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
18971
18972template void
18973OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
18974
18975
18976void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
18977  Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
18978  set->set_table(*table);
18979}
18980
18981
18982void JSSet::Clear(Handle<JSSet> set) {
18983  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
18984  table = OrderedHashSet::Clear(table);
18985  set->set_table(*table);
18986}
18987
18988
18989void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
18990  Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
18991  map->set_table(*table);
18992}
18993
18994
18995void JSMap::Clear(Handle<JSMap> map) {
18996  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
18997  table = OrderedHashMap::Clear(table);
18998  map->set_table(*table);
18999}
19000
19001
19002void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
19003                                  Isolate* isolate) {
19004  Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
19005  weak_collection->set_table(*table);
19006}
19007
19008
19009void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
19010                           Handle<Object> key, Handle<Object> value,
19011                           int32_t hash) {
19012  DCHECK(key->IsJSReceiver() || key->IsSymbol());
19013  Handle<ObjectHashTable> table(
19014      ObjectHashTable::cast(weak_collection->table()));
19015  DCHECK(table->IsKey(*key));
19016  Handle<ObjectHashTable> new_table =
19017      ObjectHashTable::Put(table, key, value, hash);
19018  weak_collection->set_table(*new_table);
19019  if (*table != *new_table) {
19020    // Zap the old table since we didn't record slots for its elements.
19021    table->FillWithHoles(0, table->length());
19022  }
19023}
19024
19025
19026bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
19027                              Handle<Object> key, int32_t hash) {
19028  DCHECK(key->IsJSReceiver() || key->IsSymbol());
19029  Handle<ObjectHashTable> table(
19030      ObjectHashTable::cast(weak_collection->table()));
19031  DCHECK(table->IsKey(*key));
19032  bool was_present = false;
19033  Handle<ObjectHashTable> new_table =
19034      ObjectHashTable::Remove(table, key, &was_present, hash);
19035  weak_collection->set_table(*new_table);
19036  if (*table != *new_table) {
19037    // Zap the old table since we didn't record slots for its elements.
19038    table->FillWithHoles(0, table->length());
19039  }
19040  return was_present;
19041}
19042
19043
19044// Check if there is a break point at this code position.
19045bool DebugInfo::HasBreakPoint(int code_position) {
19046  // Get the break point info object for this code position.
19047  Object* break_point_info = GetBreakPointInfo(code_position);
19048
19049  // If there is no break point info object or no break points in the break
19050  // point info object there is no break point at this code position.
19051  if (break_point_info->IsUndefined()) return false;
19052  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
19053}
19054
19055
19056// Get the break point info object for this code position.
19057Object* DebugInfo::GetBreakPointInfo(int code_position) {
19058  // Find the index of the break point info object for this code position.
19059  int index = GetBreakPointInfoIndex(code_position);
19060
19061  // Return the break point info object if any.
19062  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
19063  return BreakPointInfo::cast(break_points()->get(index));
19064}
19065
19066
19067// Clear a break point at the specified code position.
19068void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
19069                                int code_position,
19070                                Handle<Object> break_point_object) {
19071  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
19072                                  debug_info->GetIsolate());
19073  if (break_point_info->IsUndefined()) return;
19074  BreakPointInfo::ClearBreakPoint(
19075      Handle<BreakPointInfo>::cast(break_point_info),
19076      break_point_object);
19077}
19078
19079
19080void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
19081                              int code_position,
19082                              int source_position,
19083                              int statement_position,
19084                              Handle<Object> break_point_object) {
19085  Isolate* isolate = debug_info->GetIsolate();
19086  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
19087                                  isolate);
19088  if (!break_point_info->IsUndefined()) {
19089    BreakPointInfo::SetBreakPoint(
19090        Handle<BreakPointInfo>::cast(break_point_info),
19091        break_point_object);
19092    return;
19093  }
19094
19095  // Adding a new break point for a code position which did not have any
19096  // break points before. Try to find a free slot.
19097  int index = kNoBreakPointInfo;
19098  for (int i = 0; i < debug_info->break_points()->length(); i++) {
19099    if (debug_info->break_points()->get(i)->IsUndefined()) {
19100      index = i;
19101      break;
19102    }
19103  }
19104  if (index == kNoBreakPointInfo) {
19105    // No free slot - extend break point info array.
19106    Handle<FixedArray> old_break_points =
19107        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
19108    Handle<FixedArray> new_break_points =
19109        isolate->factory()->NewFixedArray(
19110            old_break_points->length() +
19111            DebugInfo::kEstimatedNofBreakPointsInFunction);
19112
19113    debug_info->set_break_points(*new_break_points);
19114    for (int i = 0; i < old_break_points->length(); i++) {
19115      new_break_points->set(i, old_break_points->get(i));
19116    }
19117    index = old_break_points->length();
19118  }
19119  DCHECK(index != kNoBreakPointInfo);
19120
19121  // Allocate new BreakPointInfo object and set the break point.
19122  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
19123      isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
19124  new_break_point_info->set_code_position(code_position);
19125  new_break_point_info->set_source_position(source_position);
19126  new_break_point_info->set_statement_position(statement_position);
19127  new_break_point_info->set_break_point_objects(
19128      isolate->heap()->undefined_value());
19129  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
19130  debug_info->break_points()->set(index, *new_break_point_info);
19131}
19132
19133
19134// Get the break point objects for a code position.
19135Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
19136  Object* break_point_info = GetBreakPointInfo(code_position);
19137  if (break_point_info->IsUndefined()) {
19138    return GetIsolate()->factory()->undefined_value();
19139  }
19140  return Handle<Object>(
19141      BreakPointInfo::cast(break_point_info)->break_point_objects(),
19142      GetIsolate());
19143}
19144
19145
19146// Get the total number of break points.
19147int DebugInfo::GetBreakPointCount() {
19148  if (break_points()->IsUndefined()) return 0;
19149  int count = 0;
19150  for (int i = 0; i < break_points()->length(); i++) {
19151    if (!break_points()->get(i)->IsUndefined()) {
19152      BreakPointInfo* break_point_info =
19153          BreakPointInfo::cast(break_points()->get(i));
19154      count += break_point_info->GetBreakPointCount();
19155    }
19156  }
19157  return count;
19158}
19159
19160
19161Handle<Object> DebugInfo::FindBreakPointInfo(
19162    Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
19163  Isolate* isolate = debug_info->GetIsolate();
19164  if (!debug_info->break_points()->IsUndefined()) {
19165    for (int i = 0; i < debug_info->break_points()->length(); i++) {
19166      if (!debug_info->break_points()->get(i)->IsUndefined()) {
19167        Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
19168            BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
19169        if (BreakPointInfo::HasBreakPointObject(break_point_info,
19170                                                break_point_object)) {
19171          return break_point_info;
19172        }
19173      }
19174    }
19175  }
19176  return isolate->factory()->undefined_value();
19177}
19178
19179
19180// Find the index of the break point info object for the specified code
19181// position.
19182int DebugInfo::GetBreakPointInfoIndex(int code_position) {
19183  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
19184  for (int i = 0; i < break_points()->length(); i++) {
19185    if (!break_points()->get(i)->IsUndefined()) {
19186      BreakPointInfo* break_point_info =
19187          BreakPointInfo::cast(break_points()->get(i));
19188      if (break_point_info->code_position() == code_position) {
19189        return i;
19190      }
19191    }
19192  }
19193  return kNoBreakPointInfo;
19194}
19195
19196
19197// Remove the specified break point object.
19198void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
19199                                     Handle<Object> break_point_object) {
19200  Isolate* isolate = break_point_info->GetIsolate();
19201  // If there are no break points just ignore.
19202  if (break_point_info->break_point_objects()->IsUndefined()) return;
19203  // If there is a single break point clear it if it is the same.
19204  if (!break_point_info->break_point_objects()->IsFixedArray()) {
19205    if (break_point_info->break_point_objects() == *break_point_object) {
19206      break_point_info->set_break_point_objects(
19207          isolate->heap()->undefined_value());
19208    }
19209    return;
19210  }
19211  // If there are multiple break points shrink the array
19212  DCHECK(break_point_info->break_point_objects()->IsFixedArray());
19213  Handle<FixedArray> old_array =
19214      Handle<FixedArray>(
19215          FixedArray::cast(break_point_info->break_point_objects()));
19216  Handle<FixedArray> new_array =
19217      isolate->factory()->NewFixedArray(old_array->length() - 1);
19218  int found_count = 0;
19219  for (int i = 0; i < old_array->length(); i++) {
19220    if (old_array->get(i) == *break_point_object) {
19221      DCHECK(found_count == 0);
19222      found_count++;
19223    } else {
19224      new_array->set(i - found_count, old_array->get(i));
19225    }
19226  }
19227  // If the break point was found in the list change it.
19228  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
19229}
19230
19231
19232// Add the specified break point object.
19233void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
19234                                   Handle<Object> break_point_object) {
19235  Isolate* isolate = break_point_info->GetIsolate();
19236
19237  // If there was no break point objects before just set it.
19238  if (break_point_info->break_point_objects()->IsUndefined()) {
19239    break_point_info->set_break_point_objects(*break_point_object);
19240    return;
19241  }
19242  // If the break point object is the same as before just ignore.
19243  if (break_point_info->break_point_objects() == *break_point_object) return;
19244  // If there was one break point object before replace with array.
19245  if (!break_point_info->break_point_objects()->IsFixedArray()) {
19246    Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
19247    array->set(0, break_point_info->break_point_objects());
19248    array->set(1, *break_point_object);
19249    break_point_info->set_break_point_objects(*array);
19250    return;
19251  }
19252  // If there was more than one break point before extend array.
19253  Handle<FixedArray> old_array =
19254      Handle<FixedArray>(
19255          FixedArray::cast(break_point_info->break_point_objects()));
19256  Handle<FixedArray> new_array =
19257      isolate->factory()->NewFixedArray(old_array->length() + 1);
19258  for (int i = 0; i < old_array->length(); i++) {
19259    // If the break point was there before just ignore.
19260    if (old_array->get(i) == *break_point_object) return;
19261    new_array->set(i, old_array->get(i));
19262  }
19263  // Add the new break point.
19264  new_array->set(old_array->length(), *break_point_object);
19265  break_point_info->set_break_point_objects(*new_array);
19266}
19267
19268
19269bool BreakPointInfo::HasBreakPointObject(
19270    Handle<BreakPointInfo> break_point_info,
19271    Handle<Object> break_point_object) {
19272  // No break point.
19273  if (break_point_info->break_point_objects()->IsUndefined()) return false;
19274  // Single break point.
19275  if (!break_point_info->break_point_objects()->IsFixedArray()) {
19276    return break_point_info->break_point_objects() == *break_point_object;
19277  }
19278  // Multiple break points.
19279  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
19280  for (int i = 0; i < array->length(); i++) {
19281    if (array->get(i) == *break_point_object) {
19282      return true;
19283    }
19284  }
19285  return false;
19286}
19287
19288
19289// Get the number of break points.
19290int BreakPointInfo::GetBreakPointCount() {
19291  // No break point.
19292  if (break_point_objects()->IsUndefined()) return 0;
19293  // Single break point.
19294  if (!break_point_objects()->IsFixedArray()) return 1;
19295  // Multiple break points.
19296  return FixedArray::cast(break_point_objects())->length();
19297}
19298
19299
19300// static
19301MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
19302                                Handle<JSReceiver> new_target, double tv) {
19303  Isolate* const isolate = constructor->GetIsolate();
19304  Handle<JSObject> result;
19305  ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
19306                             JSObject::New(constructor, new_target), JSDate);
19307  if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
19308    tv = DoubleToInteger(tv) + 0.0;
19309  } else {
19310    tv = std::numeric_limits<double>::quiet_NaN();
19311  }
19312  Handle<Object> value = isolate->factory()->NewNumber(tv);
19313  Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
19314  return Handle<JSDate>::cast(result);
19315}
19316
19317
19318// static
19319double JSDate::CurrentTimeValue(Isolate* isolate) {
19320  if (FLAG_log_timer_events || FLAG_prof_cpp) LOG(isolate, CurrentTimeEvent());
19321
19322  // According to ECMA-262, section 15.9.1, page 117, the precision of
19323  // the number in a Date object representing a particular instant in
19324  // time is milliseconds. Therefore, we floor the result of getting
19325  // the OS time.
19326  return Floor(FLAG_verify_predictable
19327                   ? isolate->heap()->MonotonicallyIncreasingTimeInMs()
19328                   : base::OS::TimeCurrentMillis());
19329}
19330
19331
19332// static
19333Object* JSDate::GetField(Object* object, Smi* index) {
19334  return JSDate::cast(object)->DoGetField(
19335      static_cast<FieldIndex>(index->value()));
19336}
19337
19338
19339Object* JSDate::DoGetField(FieldIndex index) {
19340  DCHECK(index != kDateValue);
19341
19342  DateCache* date_cache = GetIsolate()->date_cache();
19343
19344  if (index < kFirstUncachedField) {
19345    Object* stamp = cache_stamp();
19346    if (stamp != date_cache->stamp() && stamp->IsSmi()) {
19347      // Since the stamp is not NaN, the value is also not NaN.
19348      int64_t local_time_ms =
19349          date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
19350      SetCachedFields(local_time_ms, date_cache);
19351    }
19352    switch (index) {
19353      case kYear: return year();
19354      case kMonth: return month();
19355      case kDay: return day();
19356      case kWeekday: return weekday();
19357      case kHour: return hour();
19358      case kMinute: return min();
19359      case kSecond: return sec();
19360      default: UNREACHABLE();
19361    }
19362  }
19363
19364  if (index >= kFirstUTCField) {
19365    return GetUTCField(index, value()->Number(), date_cache);
19366  }
19367
19368  double time = value()->Number();
19369  if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
19370
19371  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
19372  int days = DateCache::DaysFromTime(local_time_ms);
19373
19374  if (index == kDays) return Smi::FromInt(days);
19375
19376  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
19377  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
19378  DCHECK(index == kTimeInDay);
19379  return Smi::FromInt(time_in_day_ms);
19380}
19381
19382
19383Object* JSDate::GetUTCField(FieldIndex index,
19384                            double value,
19385                            DateCache* date_cache) {
19386  DCHECK(index >= kFirstUTCField);
19387
19388  if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
19389
19390  int64_t time_ms = static_cast<int64_t>(value);
19391
19392  if (index == kTimezoneOffset) {
19393    return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
19394  }
19395
19396  int days = DateCache::DaysFromTime(time_ms);
19397
19398  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
19399
19400  if (index <= kDayUTC) {
19401    int year, month, day;
19402    date_cache->YearMonthDayFromDays(days, &year, &month, &day);
19403    if (index == kYearUTC) return Smi::FromInt(year);
19404    if (index == kMonthUTC) return Smi::FromInt(month);
19405    DCHECK(index == kDayUTC);
19406    return Smi::FromInt(day);
19407  }
19408
19409  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
19410  switch (index) {
19411    case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
19412    case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
19413    case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
19414    case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
19415    case kDaysUTC: return Smi::FromInt(days);
19416    case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
19417    default: UNREACHABLE();
19418  }
19419
19420  UNREACHABLE();
19421  return NULL;
19422}
19423
19424
19425// static
19426Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
19427  Isolate* const isolate = date->GetIsolate();
19428  Handle<Object> value = isolate->factory()->NewNumber(v);
19429  bool value_is_nan = std::isnan(v);
19430  date->SetValue(*value, value_is_nan);
19431  return value;
19432}
19433
19434
19435void JSDate::SetValue(Object* value, bool is_value_nan) {
19436  set_value(value);
19437  if (is_value_nan) {
19438    HeapNumber* nan = GetIsolate()->heap()->nan_value();
19439    set_cache_stamp(nan, SKIP_WRITE_BARRIER);
19440    set_year(nan, SKIP_WRITE_BARRIER);
19441    set_month(nan, SKIP_WRITE_BARRIER);
19442    set_day(nan, SKIP_WRITE_BARRIER);
19443    set_hour(nan, SKIP_WRITE_BARRIER);
19444    set_min(nan, SKIP_WRITE_BARRIER);
19445    set_sec(nan, SKIP_WRITE_BARRIER);
19446    set_weekday(nan, SKIP_WRITE_BARRIER);
19447  } else {
19448    set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
19449  }
19450}
19451
19452
19453// static
19454MaybeHandle<Object> JSDate::ToPrimitive(Handle<JSReceiver> receiver,
19455                                        Handle<Object> hint) {
19456  Isolate* const isolate = receiver->GetIsolate();
19457  if (hint->IsString()) {
19458    Handle<String> hint_string = Handle<String>::cast(hint);
19459    if (hint_string->Equals(isolate->heap()->number_string())) {
19460      return JSReceiver::OrdinaryToPrimitive(receiver,
19461                                             OrdinaryToPrimitiveHint::kNumber);
19462    }
19463    if (hint_string->Equals(isolate->heap()->default_string()) ||
19464        hint_string->Equals(isolate->heap()->string_string())) {
19465      return JSReceiver::OrdinaryToPrimitive(receiver,
19466                                             OrdinaryToPrimitiveHint::kString);
19467    }
19468  }
19469  THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidHint, hint),
19470                  Object);
19471}
19472
19473
19474void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
19475  int days = DateCache::DaysFromTime(local_time_ms);
19476  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
19477  int year, month, day;
19478  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
19479  int weekday = date_cache->Weekday(days);
19480  int hour = time_in_day_ms / (60 * 60 * 1000);
19481  int min = (time_in_day_ms / (60 * 1000)) % 60;
19482  int sec = (time_in_day_ms / 1000) % 60;
19483  set_cache_stamp(date_cache->stamp());
19484  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
19485  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
19486  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
19487  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
19488  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
19489  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
19490  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
19491}
19492
19493
19494void JSArrayBuffer::Neuter() {
19495  CHECK(is_neuterable());
19496  CHECK(is_external());
19497  set_backing_store(NULL);
19498  set_byte_length(Smi::FromInt(0));
19499  set_was_neutered(true);
19500}
19501
19502
19503void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
19504                          bool is_external, void* data, size_t allocated_length,
19505                          SharedFlag shared) {
19506  DCHECK(array_buffer->GetInternalFieldCount() ==
19507         v8::ArrayBuffer::kInternalFieldCount);
19508  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
19509    array_buffer->SetInternalField(i, Smi::FromInt(0));
19510  }
19511  array_buffer->set_bit_field(0);
19512  array_buffer->set_is_external(is_external);
19513  array_buffer->set_is_neuterable(shared == SharedFlag::kNotShared);
19514  array_buffer->set_is_shared(shared == SharedFlag::kShared);
19515
19516  Handle<Object> byte_length =
19517      isolate->factory()->NewNumberFromSize(allocated_length);
19518  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
19519  array_buffer->set_byte_length(*byte_length);
19520  // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
19521  // are currently being constructed in the |ArrayBufferTracker|. The
19522  // registration method below handles the case of registering a buffer that has
19523  // already been promoted.
19524  array_buffer->set_backing_store(data);
19525
19526  if (data && !is_external) {
19527    isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
19528  }
19529}
19530
19531
19532bool JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer> array_buffer,
19533                                        Isolate* isolate,
19534                                        size_t allocated_length,
19535                                        bool initialize, SharedFlag shared) {
19536  void* data;
19537  CHECK(isolate->array_buffer_allocator() != NULL);
19538  // Prevent creating array buffers when serializing.
19539  DCHECK(!isolate->serializer_enabled());
19540  if (allocated_length != 0) {
19541    if (initialize) {
19542      data = isolate->array_buffer_allocator()->Allocate(allocated_length);
19543    } else {
19544      data = isolate->array_buffer_allocator()->AllocateUninitialized(
19545          allocated_length);
19546    }
19547    if (data == NULL) return false;
19548  } else {
19549    data = NULL;
19550  }
19551
19552  JSArrayBuffer::Setup(array_buffer, isolate, false, data, allocated_length,
19553                       shared);
19554  return true;
19555}
19556
19557
19558Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
19559    Handle<JSTypedArray> typed_array) {
19560
19561  Handle<Map> map(typed_array->map());
19562  Isolate* isolate = typed_array->GetIsolate();
19563
19564  DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
19565
19566  Handle<FixedTypedArrayBase> fixed_typed_array(
19567      FixedTypedArrayBase::cast(typed_array->elements()));
19568
19569  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
19570                               isolate);
19571  void* backing_store =
19572      isolate->array_buffer_allocator()->AllocateUninitialized(
19573          fixed_typed_array->DataSize());
19574  buffer->set_is_external(false);
19575  DCHECK(buffer->byte_length()->IsSmi() ||
19576         buffer->byte_length()->IsHeapNumber());
19577  DCHECK(NumberToInt32(buffer->byte_length()) == fixed_typed_array->DataSize());
19578  // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
19579  // are currently being constructed in the |ArrayBufferTracker|. The
19580  // registration method below handles the case of registering a buffer that has
19581  // already been promoted.
19582  buffer->set_backing_store(backing_store);
19583  isolate->heap()->RegisterNewArrayBuffer(*buffer);
19584  memcpy(buffer->backing_store(),
19585         fixed_typed_array->DataPtr(),
19586         fixed_typed_array->DataSize());
19587  Handle<FixedTypedArrayBase> new_elements =
19588      isolate->factory()->NewFixedTypedArrayWithExternalPointer(
19589          fixed_typed_array->length(), typed_array->type(),
19590          static_cast<uint8_t*>(buffer->backing_store()));
19591
19592  typed_array->set_elements(*new_elements);
19593
19594  return buffer;
19595}
19596
19597
19598Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
19599  Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
19600                                     GetIsolate());
19601  if (array_buffer->was_neutered() ||
19602      array_buffer->backing_store() != nullptr) {
19603    return array_buffer;
19604  }
19605  Handle<JSTypedArray> self(this);
19606  return MaterializeArrayBuffer(self);
19607}
19608
19609
19610Handle<PropertyCell> PropertyCell::InvalidateEntry(
19611    Handle<GlobalDictionary> dictionary, int entry) {
19612  Isolate* isolate = dictionary->GetIsolate();
19613  // Swap with a copy.
19614  DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
19615  Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
19616  auto new_cell = isolate->factory()->NewPropertyCell();
19617  new_cell->set_value(cell->value());
19618  dictionary->ValueAtPut(entry, *new_cell);
19619  bool is_the_hole = cell->value()->IsTheHole();
19620  // Cell is officially mutable henceforth.
19621  PropertyDetails details = cell->property_details();
19622  details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
19623                                              : PropertyCellType::kMutable);
19624  new_cell->set_property_details(details);
19625  // Old cell is ready for invalidation.
19626  if (is_the_hole) {
19627    cell->set_value(isolate->heap()->undefined_value());
19628  } else {
19629    cell->set_value(isolate->heap()->the_hole_value());
19630  }
19631  details = details.set_cell_type(PropertyCellType::kInvalidated);
19632  cell->set_property_details(details);
19633  cell->dependent_code()->DeoptimizeDependentCodeGroup(
19634      isolate, DependentCode::kPropertyCellChangedGroup);
19635  return new_cell;
19636}
19637
19638
19639PropertyCellConstantType PropertyCell::GetConstantType() {
19640  if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
19641  return PropertyCellConstantType::kStableMap;
19642}
19643
19644
19645static bool RemainsConstantType(Handle<PropertyCell> cell,
19646                                Handle<Object> value) {
19647  // TODO(dcarney): double->smi and smi->double transition from kConstant
19648  if (cell->value()->IsSmi() && value->IsSmi()) {
19649    return true;
19650  } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
19651    return HeapObject::cast(cell->value())->map() ==
19652               HeapObject::cast(*value)->map() &&
19653           HeapObject::cast(*value)->map()->is_stable();
19654  }
19655  return false;
19656}
19657
19658
19659PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
19660                                           Handle<Object> value,
19661                                           PropertyDetails details) {
19662  PropertyCellType type = details.cell_type();
19663  DCHECK(!value->IsTheHole());
19664  if (cell->value()->IsTheHole()) {
19665    switch (type) {
19666      // Only allow a cell to transition once into constant state.
19667      case PropertyCellType::kUninitialized:
19668        if (value->IsUndefined()) return PropertyCellType::kUndefined;
19669        return PropertyCellType::kConstant;
19670      case PropertyCellType::kInvalidated:
19671        return PropertyCellType::kMutable;
19672      default:
19673        UNREACHABLE();
19674        return PropertyCellType::kMutable;
19675    }
19676  }
19677  switch (type) {
19678    case PropertyCellType::kUndefined:
19679      return PropertyCellType::kConstant;
19680    case PropertyCellType::kConstant:
19681      if (*value == cell->value()) return PropertyCellType::kConstant;
19682    // Fall through.
19683    case PropertyCellType::kConstantType:
19684      if (RemainsConstantType(cell, value)) {
19685        return PropertyCellType::kConstantType;
19686      }
19687    // Fall through.
19688    case PropertyCellType::kMutable:
19689      return PropertyCellType::kMutable;
19690  }
19691  UNREACHABLE();
19692  return PropertyCellType::kMutable;
19693}
19694
19695
19696void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
19697                              Handle<Object> value, PropertyDetails details) {
19698  DCHECK(!value->IsTheHole());
19699  DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
19700  Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
19701  const PropertyDetails original_details = cell->property_details();
19702  // Data accesses could be cached in ics or optimized code.
19703  bool invalidate =
19704      original_details.kind() == kData && details.kind() == kAccessor;
19705  int index = original_details.dictionary_index();
19706  PropertyCellType old_type = original_details.cell_type();
19707  // Preserve the enumeration index unless the property was deleted or never
19708  // initialized.
19709  if (cell->value()->IsTheHole()) {
19710    index = dictionary->NextEnumerationIndex();
19711    dictionary->SetNextEnumerationIndex(index + 1);
19712    // Negative lookup cells must be invalidated.
19713    invalidate = true;
19714  }
19715  DCHECK(index > 0);
19716  details = details.set_index(index);
19717
19718  PropertyCellType new_type = UpdatedType(cell, value, original_details);
19719  if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
19720
19721  // Install new property details and cell value.
19722  details = details.set_cell_type(new_type);
19723  cell->set_property_details(details);
19724  cell->set_value(*value);
19725
19726  // Deopt when transitioning from a constant type.
19727  if (!invalidate && (old_type != new_type ||
19728                      original_details.IsReadOnly() != details.IsReadOnly())) {
19729    Isolate* isolate = dictionary->GetIsolate();
19730    cell->dependent_code()->DeoptimizeDependentCodeGroup(
19731        isolate, DependentCode::kPropertyCellChangedGroup);
19732  }
19733}
19734
19735
19736// static
19737void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
19738                                            Handle<Object> new_value) {
19739  if (cell->value() != *new_value) {
19740    cell->set_value(*new_value);
19741    Isolate* isolate = cell->GetIsolate();
19742    cell->dependent_code()->DeoptimizeDependentCodeGroup(
19743        isolate, DependentCode::kPropertyCellChangedGroup);
19744  }
19745}
19746
19747}  // namespace internal
19748}  // namespace v8
19749