Reland of "Remove ExternalArray, derived types, and element kinds"
[platform/upstream/v8.git] / src / objects.cc
1 // Copyright 2013 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 <iomanip>
6 #include <sstream>
7
8 #include "src/v8.h"
9
10 #include "src/accessors.h"
11 #include "src/allocation-site-scopes.h"
12 #include "src/api.h"
13 #include "src/arguments.h"
14 #include "src/base/bits.h"
15 #include "src/base/utils/random-number-generator.h"
16 #include "src/bootstrapper.h"
17 #include "src/code-stubs.h"
18 #include "src/codegen.h"
19 #include "src/compilation-dependencies.h"
20 #include "src/compiler.h"
21 #include "src/cpu-profiler.h"
22 #include "src/date.h"
23 #include "src/debug.h"
24 #include "src/deoptimizer.h"
25 #include "src/elements.h"
26 #include "src/execution.h"
27 #include "src/field-index-inl.h"
28 #include "src/field-index.h"
29 #include "src/full-codegen/full-codegen.h"
30 #include "src/heap/mark-compact.h"
31 #include "src/heap/objects-visiting-inl.h"
32 #include "src/hydrogen.h"
33 #include "src/ic/ic.h"
34 #include "src/interpreter/bytecodes.h"
35 #include "src/log.h"
36 #include "src/lookup.h"
37 #include "src/macro-assembler.h"
38 #include "src/messages.h"
39 #include "src/objects-inl.h"
40 #include "src/prototype.h"
41 #include "src/safepoint-table.h"
42 #include "src/string-search.h"
43 #include "src/string-stream.h"
44 #include "src/utils.h"
45
46 #ifdef ENABLE_DISASSEMBLER
47 #include "src/disasm.h"
48 #include "src/disassembler.h"
49 #endif
50
51 namespace v8 {
52 namespace internal {
53
54 Handle<HeapType> Object::OptimalType(Isolate* isolate,
55                                      Representation representation) {
56   if (representation.IsNone()) return HeapType::None(isolate);
57   if (FLAG_track_field_types) {
58     if (representation.IsHeapObject() && IsHeapObject()) {
59       // We can track only JavaScript objects with stable maps.
60       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
61       if (map->is_stable() &&
62           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
63           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
64         return HeapType::Class(map, isolate);
65       }
66     }
67   }
68   return HeapType::Any(isolate);
69 }
70
71
72 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
73                                          Handle<Object> object,
74                                          Handle<Context> native_context) {
75   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
76   Handle<JSFunction> constructor;
77   if (object->IsNumber()) {
78     constructor = handle(native_context->number_function(), isolate);
79   } else if (object->IsBoolean()) {
80     constructor = handle(native_context->boolean_function(), isolate);
81   } else if (object->IsString()) {
82     constructor = handle(native_context->string_function(), isolate);
83   } else if (object->IsSymbol()) {
84     constructor = handle(native_context->symbol_function(), isolate);
85   } else if (object->IsFloat32x4()) {
86     constructor = handle(native_context->float32x4_function(), isolate);
87   } else {
88     return MaybeHandle<JSReceiver>();
89   }
90   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
91   Handle<JSValue>::cast(result)->set_value(*object);
92   return result;
93 }
94
95
96 bool Object::BooleanValue() {
97   if (IsBoolean()) return IsTrue();
98   if (IsSmi()) return Smi::cast(this)->value() != 0;
99   if (IsUndefined() || IsNull()) return false;
100   if (IsUndetectableObject()) return false;   // Undetectable object is false.
101   if (IsString()) return String::cast(this)->length() != 0;
102   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
103   if (IsFloat32x4()) return true;  // Simd value types always evaluate to true.
104   return true;
105 }
106
107
108 bool Object::IsCallable() const {
109   const Object* fun = this;
110   while (fun->IsJSFunctionProxy()) {
111     fun = JSFunctionProxy::cast(fun)->call_trap();
112   }
113   return fun->IsJSFunction() ||
114          (fun->IsHeapObject() &&
115           HeapObject::cast(fun)->map()->has_instance_call_handler());
116 }
117
118
119 bool Object::IsPromise(Handle<Object> object) {
120   if (!object->IsJSObject()) return false;
121   auto js_object = Handle<JSObject>::cast(object);
122   // Promises can't have access checks.
123   if (js_object->map()->is_access_check_needed()) return false;
124   auto isolate = js_object->GetIsolate();
125   // TODO(dcarney): this should just be read from the symbol registry so as not
126   // to be context dependent.
127   auto key = isolate->promise_status();
128   // Shouldn't be possible to throw here.
129   return JSObject::HasRealNamedProperty(js_object, key).FromJust();
130 }
131
132
133 MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
134                                         LanguageMode language_mode) {
135   for (; it->IsFound(); it->Next()) {
136     switch (it->state()) {
137       case LookupIterator::NOT_FOUND:
138       case LookupIterator::TRANSITION:
139         UNREACHABLE();
140       case LookupIterator::JSPROXY:
141         return JSProxy::GetPropertyWithHandler(
142             it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
143       case LookupIterator::INTERCEPTOR: {
144         bool done;
145         Handle<Object> result;
146         ASSIGN_RETURN_ON_EXCEPTION(
147             it->isolate(), result,
148             JSObject::GetPropertyWithInterceptor(it, &done), Object);
149         if (done) return result;
150         break;
151       }
152       case LookupIterator::ACCESS_CHECK:
153         if (it->HasAccess()) break;
154         return JSObject::GetPropertyWithFailedAccessCheck(it);
155       case LookupIterator::ACCESSOR:
156         return GetPropertyWithAccessor(it, language_mode);
157       case LookupIterator::INTEGER_INDEXED_EXOTIC:
158         return ReadAbsentProperty(it, language_mode);
159       case LookupIterator::DATA:
160         return it->GetDataValue();
161     }
162   }
163   return ReadAbsentProperty(it, language_mode);
164 }
165
166
167 Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object,
168                                            Handle<Name> name) {
169   LookupIterator it(object, name,
170                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
171   return GetDataProperty(&it);
172 }
173
174
175 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
176   for (; it->IsFound(); it->Next()) {
177     switch (it->state()) {
178       case LookupIterator::INTERCEPTOR:
179       case LookupIterator::NOT_FOUND:
180       case LookupIterator::TRANSITION:
181         UNREACHABLE();
182       case LookupIterator::ACCESS_CHECK:
183         if (it->HasAccess()) continue;
184       // Fall through.
185       case LookupIterator::JSPROXY:
186         it->NotFound();
187         return it->isolate()->factory()->undefined_value();
188       case LookupIterator::ACCESSOR:
189         // TODO(verwaest): For now this doesn't call into
190         // ExecutableAccessorInfo, since clients don't need it. Update once
191         // relevant.
192         it->NotFound();
193         return it->isolate()->factory()->undefined_value();
194       case LookupIterator::INTEGER_INDEXED_EXOTIC:
195         return it->isolate()->factory()->undefined_value();
196       case LookupIterator::DATA:
197         return it->GetDataValue();
198     }
199   }
200   return it->isolate()->factory()->undefined_value();
201 }
202
203
204 bool Object::ToInt32(int32_t* value) {
205   if (IsSmi()) {
206     *value = Smi::cast(this)->value();
207     return true;
208   }
209   if (IsHeapNumber()) {
210     double num = HeapNumber::cast(this)->value();
211     if (FastI2D(FastD2I(num)) == num) {
212       *value = FastD2I(num);
213       return true;
214     }
215   }
216   return false;
217 }
218
219
220 bool Object::ToUint32(uint32_t* value) {
221   if (IsSmi()) {
222     int num = Smi::cast(this)->value();
223     if (num >= 0) {
224       *value = static_cast<uint32_t>(num);
225       return true;
226     }
227   }
228   if (IsHeapNumber()) {
229     double num = HeapNumber::cast(this)->value();
230     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
231       *value = FastD2UI(num);
232       return true;
233     }
234   }
235   return false;
236 }
237
238
239 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
240   if (!object->IsHeapObject()) return false;
241   return IsTemplateFor(HeapObject::cast(object)->map());
242 }
243
244
245 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
246   // There is a constraint on the object; check.
247   if (!map->IsJSObjectMap()) return false;
248   // Fetch the constructor function of the object.
249   Object* cons_obj = map->GetConstructor();
250   if (!cons_obj->IsJSFunction()) return false;
251   JSFunction* fun = JSFunction::cast(cons_obj);
252   // Iterate through the chain of inheriting function templates to
253   // see if the required one occurs.
254   for (Object* type = fun->shared()->function_data();
255        type->IsFunctionTemplateInfo();
256        type = FunctionTemplateInfo::cast(type)->parent_template()) {
257     if (type == this) return true;
258   }
259   // Didn't find the required type in the inheritance chain.
260   return false;
261 }
262
263
264 // TODO(dcarney): CallOptimization duplicates this logic, merge.
265 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
266                                                     Object* receiver) {
267   // API calls are only supported with JSObject receivers.
268   if (!receiver->IsJSObject()) return isolate->heap()->null_value();
269   Object* recv_type = this->signature();
270   // No signature, return holder.
271   if (recv_type->IsUndefined()) return receiver;
272   FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
273   // Check the receiver.
274   for (PrototypeIterator iter(isolate, receiver,
275                               PrototypeIterator::START_AT_RECEIVER);
276        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
277     if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
278   }
279   return isolate->heap()->null_value();
280 }
281
282
283 Handle<FixedArray> JSObject::EnsureWritableFastElements(
284     Handle<JSObject> object) {
285   DCHECK(object->HasFastSmiOrObjectElements());
286   Isolate* isolate = object->GetIsolate();
287   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
288   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
289   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
290       elems, isolate->factory()->fixed_array_map());
291   object->set_elements(*writable_elems);
292   isolate->counters()->cow_arrays_converted()->Increment();
293   return writable_elems;
294 }
295
296
297 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
298                                                     Handle<Object> receiver,
299                                                     Handle<Name> name) {
300   Isolate* isolate = proxy->GetIsolate();
301
302   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
303   if (name->IsSymbol()) return isolate->factory()->undefined_value();
304
305   Handle<Object> args[] = { receiver, name };
306   return CallTrap(
307       proxy, "get",  isolate->derived_get_trap(), arraysize(args), args);
308 }
309
310
311 MaybeHandle<Object> Object::GetPropertyWithAccessor(
312     LookupIterator* it, LanguageMode language_mode) {
313   Isolate* isolate = it->isolate();
314   Handle<Object> structure = it->GetAccessors();
315   Handle<Object> receiver = it->GetReceiver();
316
317   // We should never get here to initialize a const with the hole value since a
318   // const declaration would conflict with the getter.
319   DCHECK(!structure->IsForeign());
320
321   // API style callbacks.
322   if (structure->IsAccessorInfo()) {
323     Handle<JSObject> holder = it->GetHolder<JSObject>();
324     Handle<Name> name = it->GetName();
325     Handle<ExecutableAccessorInfo> info =
326         Handle<ExecutableAccessorInfo>::cast(structure);
327     if (!info->IsCompatibleReceiver(*receiver)) {
328       THROW_NEW_ERROR(isolate,
329                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
330                                    name, receiver),
331                       Object);
332     }
333
334     v8::AccessorNameGetterCallback call_fun =
335         v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
336     if (call_fun == nullptr) return isolate->factory()->undefined_value();
337
338     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
339     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
340     v8::Local<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(name));
341     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
342     if (result.IsEmpty()) {
343       return ReadAbsentProperty(isolate, receiver, name, language_mode);
344     }
345     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
346     return_value->VerifyApiCallResultType();
347     // Rebox handle before return.
348     return handle(*return_value, isolate);
349   }
350
351   // Regular accessor.
352   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
353   if (getter->IsSpecFunction()) {
354     // TODO(rossberg): nicer would be to cast to some JSCallable here...
355     return Object::GetPropertyWithDefinedGetter(
356         receiver, Handle<JSReceiver>::cast(getter));
357   }
358   // Getter is not a function.
359   return ReadAbsentProperty(isolate, receiver, it->GetName(), language_mode);
360 }
361
362
363 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
364                                            Handle<AccessorInfo> info,
365                                            Handle<Map> map) {
366   if (!info->HasExpectedReceiverType()) return true;
367   if (!map->IsJSObjectMap()) return false;
368   return FunctionTemplateInfo::cast(info->expected_receiver_type())
369       ->IsTemplateFor(*map);
370 }
371
372
373 MaybeHandle<Object> Object::SetPropertyWithAccessor(
374     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
375   Isolate* isolate = it->isolate();
376   Handle<Object> structure = it->GetAccessors();
377   Handle<Object> receiver = it->GetReceiver();
378
379   // We should never get here to initialize a const with the hole value since a
380   // const declaration would conflict with the setter.
381   DCHECK(!structure->IsForeign());
382
383   // API style callbacks.
384   if (structure->IsExecutableAccessorInfo()) {
385     Handle<JSObject> holder = it->GetHolder<JSObject>();
386     Handle<Name> name = it->GetName();
387     Handle<ExecutableAccessorInfo> info =
388         Handle<ExecutableAccessorInfo>::cast(structure);
389     if (!info->IsCompatibleReceiver(*receiver)) {
390       THROW_NEW_ERROR(isolate,
391                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
392                                    name, receiver),
393                       Object);
394     }
395
396     v8::AccessorNameSetterCallback call_fun =
397         v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
398     if (call_fun == nullptr) return value;
399
400     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
401     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
402     args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
403     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
404     return value;
405   }
406
407   // Regular accessor.
408   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
409   if (setter->IsSpecFunction()) {
410     // TODO(rossberg): nicer would be to cast to some JSCallable here...
411     return SetPropertyWithDefinedSetter(
412         receiver, Handle<JSReceiver>::cast(setter), value);
413   }
414
415   if (is_sloppy(language_mode)) return value;
416
417   THROW_NEW_ERROR(isolate,
418                   NewTypeError(MessageTemplate::kNoSetterInCallback,
419                                it->GetName(), it->GetHolder<JSObject>()),
420                   Object);
421 }
422
423
424 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
425     Handle<Object> receiver,
426     Handle<JSReceiver> getter) {
427   Isolate* isolate = getter->GetIsolate();
428
429   // Platforms with simulators like arm/arm64 expose a funny issue. If the
430   // simulator has a separate JS stack pointer from the C++ stack pointer, it
431   // can miss C++ stack overflows in the stack guard at the start of JavaScript
432   // functions. It would be very expensive to check the C++ stack pointer at
433   // that location. The best solution seems to be to break the impasse by
434   // adding checks at possible recursion points. What's more, we don't put
435   // this stack check behind the USE_SIMULATOR define in order to keep
436   // behavior the same between hardware and simulators.
437   StackLimitCheck check(isolate);
438   if (check.JsHasOverflowed()) {
439     isolate->StackOverflow();
440     return MaybeHandle<Object>();
441   }
442
443   Debug* debug = isolate->debug();
444   // Handle stepping into a getter if step into is active.
445   // TODO(rossberg): should this apply to getters that are function proxies?
446   if (debug->is_active()) debug->HandleStepIn(getter, false);
447
448   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
449 }
450
451
452 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
453     Handle<Object> receiver,
454     Handle<JSReceiver> setter,
455     Handle<Object> value) {
456   Isolate* isolate = setter->GetIsolate();
457
458   Debug* debug = isolate->debug();
459   // Handle stepping into a setter if step into is active.
460   // TODO(rossberg): should this apply to getters that are function proxies?
461   if (debug->is_active()) debug->HandleStepIn(setter, false);
462
463   Handle<Object> argv[] = { value };
464   RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
465                                                arraysize(argv), argv, true),
466                       Object);
467   return value;
468 }
469
470
471 // static
472 bool JSObject::AllCanRead(LookupIterator* it) {
473   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
474   // which have already been checked.
475   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
476          it->state() == LookupIterator::INTERCEPTOR);
477   for (it->Next(); it->IsFound(); it->Next()) {
478     if (it->state() == LookupIterator::ACCESSOR) {
479       auto accessors = it->GetAccessors();
480       if (accessors->IsAccessorInfo()) {
481         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
482       }
483     } else if (it->state() == LookupIterator::INTERCEPTOR) {
484       if (it->GetInterceptor()->all_can_read()) return true;
485     }
486   }
487   return false;
488 }
489
490
491 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
492     LookupIterator* it) {
493   Handle<JSObject> checked = it->GetHolder<JSObject>();
494   while (AllCanRead(it)) {
495     if (it->state() == LookupIterator::ACCESSOR) {
496       return GetPropertyWithAccessor(it, SLOPPY);
497     }
498     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
499     bool done;
500     Handle<Object> result;
501     ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result,
502                                GetPropertyWithInterceptor(it, &done), Object);
503     if (done) return result;
504   }
505   it->isolate()->ReportFailedAccessCheck(checked);
506   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
507   return it->factory()->undefined_value();
508 }
509
510
511 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
512     LookupIterator* it) {
513   Handle<JSObject> checked = it->GetHolder<JSObject>();
514   while (AllCanRead(it)) {
515     if (it->state() == LookupIterator::ACCESSOR) {
516       return Just(it->property_details().attributes());
517     }
518     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
519     auto result = GetPropertyAttributesWithInterceptor(it);
520     if (it->isolate()->has_scheduled_exception()) break;
521     if (result.IsJust() && result.FromJust() != ABSENT) return result;
522   }
523   it->isolate()->ReportFailedAccessCheck(checked);
524   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
525                                       Nothing<PropertyAttributes>());
526   return Just(ABSENT);
527 }
528
529
530 // static
531 bool JSObject::AllCanWrite(LookupIterator* it) {
532   for (; it->IsFound(); it->Next()) {
533     if (it->state() == LookupIterator::ACCESSOR) {
534       Handle<Object> accessors = it->GetAccessors();
535       if (accessors->IsAccessorInfo()) {
536         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
537       }
538     }
539   }
540   return false;
541 }
542
543
544 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
545     LookupIterator* it, Handle<Object> value) {
546   Handle<JSObject> checked = it->GetHolder<JSObject>();
547   if (AllCanWrite(it)) {
548     // The supplied language-mode is ignored by SetPropertyWithAccessor.
549     return SetPropertyWithAccessor(it, value, SLOPPY);
550   }
551
552   it->isolate()->ReportFailedAccessCheck(checked);
553   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
554   return value;
555 }
556
557
558 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
559                                      Handle<Name> name,
560                                      Handle<Object> value,
561                                      PropertyDetails details) {
562   DCHECK(!object->HasFastProperties());
563   if (!name->IsUniqueName()) {
564     name = object->GetIsolate()->factory()->InternalizeString(
565         Handle<String>::cast(name));
566   }
567
568   if (object->IsGlobalObject()) {
569     Handle<GlobalDictionary> property_dictionary(object->global_dictionary());
570
571     int entry = property_dictionary->FindEntry(name);
572     if (entry == GlobalDictionary::kNotFound) {
573       auto cell = object->GetIsolate()->factory()->NewPropertyCell();
574       cell->set_value(*value);
575       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
576                                             : PropertyCellType::kConstant;
577       details = details.set_cell_type(cell_type);
578       value = cell;
579       property_dictionary =
580           GlobalDictionary::Add(property_dictionary, name, value, details);
581       object->set_properties(*property_dictionary);
582     } else {
583       PropertyCell::UpdateCell(property_dictionary, entry, value, details);
584     }
585   } else {
586     Handle<NameDictionary> property_dictionary(object->property_dictionary());
587
588     int entry = property_dictionary->FindEntry(name);
589     if (entry == NameDictionary::kNotFound) {
590       property_dictionary =
591           NameDictionary::Add(property_dictionary, name, value, details);
592       object->set_properties(*property_dictionary);
593     } else {
594       PropertyDetails original_details = property_dictionary->DetailsAt(entry);
595       int enumeration_index = original_details.dictionary_index();
596       DCHECK(enumeration_index > 0);
597       details = details.set_index(enumeration_index);
598       property_dictionary->SetEntry(entry, name, value, details);
599     }
600   }
601 }
602
603
604 Map* Object::GetRootMap(Isolate* isolate) {
605   DisallowHeapAllocation no_alloc;
606   if (IsSmi()) {
607     Context* context = isolate->context()->native_context();
608     return context->number_function()->initial_map();
609   }
610
611   HeapObject* heap_object = HeapObject::cast(this);
612
613   // The object is either a number, a string, a symbol, a boolean, a SIMD value,
614   // a real JS object, or a Harmony proxy.
615   if (heap_object->IsJSReceiver()) {
616     return heap_object->map();
617   }
618   Context* context = isolate->context()->native_context();
619
620   if (heap_object->IsHeapNumber()) {
621     return context->number_function()->initial_map();
622   }
623   if (heap_object->IsString()) {
624     return context->string_function()->initial_map();
625   }
626   if (heap_object->IsSymbol()) {
627     return context->symbol_function()->initial_map();
628   }
629   if (heap_object->IsBoolean()) {
630     return context->boolean_function()->initial_map();
631   }
632   if (heap_object->IsFloat32x4()) {
633     return context->float32x4_function()->initial_map();
634   }
635   return isolate->heap()->null_value()->map();
636 }
637
638
639 Object* Object::GetHash() {
640   Object* hash = GetSimpleHash();
641   if (hash->IsSmi()) return hash;
642
643   DCHECK(IsJSReceiver());
644   return JSReceiver::cast(this)->GetIdentityHash();
645 }
646
647
648 Object* Object::GetSimpleHash() {
649   // The object is either a Smi, a HeapNumber, a name, an odd-ball,
650   // a SIMD value type, a real JS object, or a Harmony proxy.
651   if (IsSmi()) {
652     uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed);
653     return Smi::FromInt(hash & Smi::kMaxValue);
654   }
655   if (IsHeapNumber()) {
656     double num = HeapNumber::cast(this)->value();
657     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
658     if (i::IsMinusZero(num)) num = 0;
659     if (IsSmiDouble(num)) {
660       return Smi::FromInt(FastD2I(num))->GetHash();
661     }
662     uint32_t hash = ComputeLongHash(double_to_uint64(num));
663     return Smi::FromInt(hash & Smi::kMaxValue);
664   }
665   if (IsName()) {
666     uint32_t hash = Name::cast(this)->Hash();
667     return Smi::FromInt(hash);
668   }
669   if (IsOddball()) {
670     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
671     return Smi::FromInt(hash);
672   }
673   if (IsFloat32x4()) {
674     Float32x4* simd = Float32x4::cast(this);
675     uint32_t seed = v8::internal::kZeroHashSeed;
676     uint32_t hash;
677     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(0)), seed);
678     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(1)), hash * 31);
679     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(2)), hash * 31);
680     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(3)), hash * 31);
681     return Smi::FromInt(hash & Smi::kMaxValue);
682   }
683   DCHECK(IsJSReceiver());
684   JSReceiver* receiver = JSReceiver::cast(this);
685   return receiver->GetHeap()->undefined_value();
686 }
687
688
689 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
690   Handle<Object> hash(object->GetSimpleHash(), isolate);
691   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
692
693   DCHECK(object->IsJSReceiver());
694   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
695 }
696
697
698 bool Object::SameValue(Object* other) {
699   if (other == this) return true;
700
701   // The object is either a number, a name, an odd-ball,
702   // a real JS object, or a Harmony proxy.
703   if (IsNumber() && other->IsNumber()) {
704     return v8::internal::SameValue(Number(), other->Number());
705   }
706   if (IsString() && other->IsString()) {
707     return String::cast(this)->Equals(String::cast(other));
708   }
709   if (IsFloat32x4() && other->IsFloat32x4()) {
710     Float32x4* x = Float32x4::cast(this);
711     Float32x4* y = Float32x4::cast(other);
712     return v8::internal::SameValue(x->get_lane(0), y->get_lane(0)) &&
713            v8::internal::SameValue(x->get_lane(1), y->get_lane(1)) &&
714            v8::internal::SameValue(x->get_lane(2), y->get_lane(2)) &&
715            v8::internal::SameValue(x->get_lane(3), y->get_lane(3));
716   }
717   return false;
718 }
719
720
721 bool Object::SameValueZero(Object* other) {
722   if (other == this) return true;
723
724   // The object is either a number, a name, an odd-ball,
725   // a real JS object, or a Harmony proxy.
726   if (IsNumber() && other->IsNumber()) {
727     return v8::internal::SameValueZero(Number(), other->Number());
728   }
729   if (IsString() && other->IsString()) {
730     return String::cast(this)->Equals(String::cast(other));
731   }
732   if (IsFloat32x4() && other->IsFloat32x4()) {
733     Float32x4* x = Float32x4::cast(this);
734     Float32x4* y = Float32x4::cast(other);
735     return v8::internal::SameValueZero(x->get_lane(0), y->get_lane(0)) &&
736            v8::internal::SameValueZero(x->get_lane(1), y->get_lane(1)) &&
737            v8::internal::SameValueZero(x->get_lane(2), y->get_lane(2)) &&
738            v8::internal::SameValueZero(x->get_lane(3), y->get_lane(3));
739   }
740   return false;
741 }
742
743
744 void Object::ShortPrint(FILE* out) {
745   OFStream os(out);
746   os << Brief(this);
747 }
748
749
750 void Object::ShortPrint(StringStream* accumulator) {
751   std::ostringstream os;
752   os << Brief(this);
753   accumulator->Add(os.str().c_str());
754 }
755
756
757 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
758
759
760 std::ostream& operator<<(std::ostream& os, const Brief& v) {
761   if (v.value->IsSmi()) {
762     Smi::cast(v.value)->SmiPrint(os);
763   } else {
764     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
765     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
766     obj->HeapObjectShortPrint(os);
767   }
768   return os;
769 }
770
771
772 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
773   os << value();
774 }
775
776
777 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
778 // English?  Returns false for non-ASCII or words that don't start with
779 // a capital letter.  The a/an rule follows pronunciation in English.
780 // We don't use the BBC's overcorrect "an historic occasion" though if
781 // you speak a dialect you may well say "an 'istoric occasion".
782 static bool AnWord(String* str) {
783   if (str->length() == 0) return false;  // A nothing.
784   int c0 = str->Get(0);
785   int c1 = str->length() > 1 ? str->Get(1) : 0;
786   if (c0 == 'U') {
787     if (c1 > 'Z') {
788       return true;  // An Umpire, but a UTF8String, a U.
789     }
790   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
791     return true;    // An Ape, an ABCBook.
792   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
793            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
794             c0 == 'S' || c0 == 'X')) {
795     return true;    // An MP3File, an M.
796   }
797   return false;
798 }
799
800
801 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
802                                    PretenureFlag pretenure) {
803   DCHECK(AllowHeapAllocation::IsAllowed());
804   DCHECK(cons->second()->length() != 0);
805   Isolate* isolate = cons->GetIsolate();
806   int length = cons->length();
807   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
808                                                             : TENURED;
809   Handle<SeqString> result;
810   if (cons->IsOneByteRepresentation()) {
811     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
812         length, tenure).ToHandleChecked();
813     DisallowHeapAllocation no_gc;
814     WriteToFlat(*cons, flat->GetChars(), 0, length);
815     result = flat;
816   } else {
817     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
818         length, tenure).ToHandleChecked();
819     DisallowHeapAllocation no_gc;
820     WriteToFlat(*cons, flat->GetChars(), 0, length);
821     result = flat;
822   }
823   cons->set_first(*result);
824   cons->set_second(isolate->heap()->empty_string());
825   DCHECK(result->IsFlat());
826   return result;
827 }
828
829
830
831 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
832   // Externalizing twice leaks the external resource, so it's
833   // prohibited by the API.
834   DCHECK(!this->IsExternalString());
835 #ifdef ENABLE_SLOW_DCHECKS
836   if (FLAG_enable_slow_asserts) {
837     // Assert that the resource and the string are equivalent.
838     DCHECK(static_cast<size_t>(this->length()) == resource->length());
839     ScopedVector<uc16> smart_chars(this->length());
840     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
841     DCHECK(memcmp(smart_chars.start(),
842                   resource->data(),
843                   resource->length() * sizeof(smart_chars[0])) == 0);
844   }
845 #endif  // DEBUG
846   int size = this->Size();  // Byte size of the original string.
847   // Abort if size does not allow in-place conversion.
848   if (size < ExternalString::kShortSize) return false;
849   Heap* heap = GetHeap();
850   bool is_one_byte = this->IsOneByteRepresentation();
851   bool is_internalized = this->IsInternalizedString();
852
853   // Morph the string to an external string by replacing the map and
854   // reinitializing the fields.  This won't work if the space the existing
855   // string occupies is too small for a regular  external string.
856   // Instead, we resort to a short external string instead, omitting
857   // the field caching the address of the backing store.  When we encounter
858   // short external strings in generated code, we need to bailout to runtime.
859   Map* new_map;
860   if (size < ExternalString::kSize) {
861     new_map = is_internalized
862         ? (is_one_byte
863            ? heap->short_external_internalized_string_with_one_byte_data_map()
864            : heap->short_external_internalized_string_map())
865         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
866                        : heap->short_external_string_map());
867   } else {
868     new_map = is_internalized
869         ? (is_one_byte
870            ? heap->external_internalized_string_with_one_byte_data_map()
871            : heap->external_internalized_string_map())
872         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
873                        : heap->external_string_map());
874   }
875
876   // Byte size of the external String object.
877   int new_size = this->SizeFromMap(new_map);
878   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
879
880   // We are storing the new map using release store after creating a filler for
881   // the left-over space to avoid races with the sweeper thread.
882   this->synchronized_set_map(new_map);
883
884   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
885   self->set_resource(resource);
886   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
887
888   heap->AdjustLiveBytes(this->address(), new_size - size,
889                         Heap::CONCURRENT_TO_SWEEPER);
890   return true;
891 }
892
893
894 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
895   // Externalizing twice leaks the external resource, so it's
896   // prohibited by the API.
897   DCHECK(!this->IsExternalString());
898 #ifdef ENABLE_SLOW_DCHECKS
899   if (FLAG_enable_slow_asserts) {
900     // Assert that the resource and the string are equivalent.
901     DCHECK(static_cast<size_t>(this->length()) == resource->length());
902     if (this->IsTwoByteRepresentation()) {
903       ScopedVector<uint16_t> smart_chars(this->length());
904       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
905       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
906     }
907     ScopedVector<char> smart_chars(this->length());
908     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
909     DCHECK(memcmp(smart_chars.start(),
910                   resource->data(),
911                   resource->length() * sizeof(smart_chars[0])) == 0);
912   }
913 #endif  // DEBUG
914   int size = this->Size();  // Byte size of the original string.
915   // Abort if size does not allow in-place conversion.
916   if (size < ExternalString::kShortSize) return false;
917   Heap* heap = GetHeap();
918   bool is_internalized = this->IsInternalizedString();
919
920   // Morph the string to an external string by replacing the map and
921   // reinitializing the fields.  This won't work if the space the existing
922   // string occupies is too small for a regular  external string.
923   // Instead, we resort to a short external string instead, omitting
924   // the field caching the address of the backing store.  When we encounter
925   // short external strings in generated code, we need to bailout to runtime.
926   Map* new_map;
927   if (size < ExternalString::kSize) {
928     new_map = is_internalized
929                   ? heap->short_external_one_byte_internalized_string_map()
930                   : heap->short_external_one_byte_string_map();
931   } else {
932     new_map = is_internalized
933                   ? heap->external_one_byte_internalized_string_map()
934                   : heap->external_one_byte_string_map();
935   }
936
937   // Byte size of the external String object.
938   int new_size = this->SizeFromMap(new_map);
939   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
940
941   // We are storing the new map using release store after creating a filler for
942   // the left-over space to avoid races with the sweeper thread.
943   this->synchronized_set_map(new_map);
944
945   ExternalOneByteString* self = ExternalOneByteString::cast(this);
946   self->set_resource(resource);
947   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
948
949   heap->AdjustLiveBytes(this->address(), new_size - size,
950                         Heap::CONCURRENT_TO_SWEEPER);
951   return true;
952 }
953
954
955 void String::StringShortPrint(StringStream* accumulator) {
956   int len = length();
957   if (len > kMaxShortPrintLength) {
958     accumulator->Add("<Very long string[%u]>", len);
959     return;
960   }
961
962   if (!LooksValid()) {
963     accumulator->Add("<Invalid String>");
964     return;
965   }
966
967   StringCharacterStream stream(this);
968
969   bool truncated = false;
970   if (len > kMaxShortPrintLength) {
971     len = kMaxShortPrintLength;
972     truncated = true;
973   }
974   bool one_byte = true;
975   for (int i = 0; i < len; i++) {
976     uint16_t c = stream.GetNext();
977
978     if (c < 32 || c >= 127) {
979       one_byte = false;
980     }
981   }
982   stream.Reset(this);
983   if (one_byte) {
984     accumulator->Add("<String[%u]: ", length());
985     for (int i = 0; i < len; i++) {
986       accumulator->Put(static_cast<char>(stream.GetNext()));
987     }
988     accumulator->Put('>');
989   } else {
990     // Backslash indicates that the string contains control
991     // characters and that backslashes are therefore escaped.
992     accumulator->Add("<String[%u]\\: ", length());
993     for (int i = 0; i < len; i++) {
994       uint16_t c = stream.GetNext();
995       if (c == '\n') {
996         accumulator->Add("\\n");
997       } else if (c == '\r') {
998         accumulator->Add("\\r");
999       } else if (c == '\\') {
1000         accumulator->Add("\\\\");
1001       } else if (c < 32 || c > 126) {
1002         accumulator->Add("\\x%02x", c);
1003       } else {
1004         accumulator->Put(static_cast<char>(c));
1005       }
1006     }
1007     if (truncated) {
1008       accumulator->Put('.');
1009       accumulator->Put('.');
1010       accumulator->Put('.');
1011     }
1012     accumulator->Put('>');
1013   }
1014   return;
1015 }
1016
1017
1018 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
1019   if (end < 0) end = length();
1020   StringCharacterStream stream(this, start);
1021   for (int i = start; i < end && stream.HasMore(); i++) {
1022     os << AsUC16(stream.GetNext());
1023   }
1024 }
1025
1026
1027 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1028   switch (map()->instance_type()) {
1029     case JS_ARRAY_TYPE: {
1030       double length = JSArray::cast(this)->length()->IsUndefined()
1031           ? 0
1032           : JSArray::cast(this)->length()->Number();
1033       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1034       break;
1035     }
1036     case JS_WEAK_MAP_TYPE: {
1037       accumulator->Add("<JS WeakMap>");
1038       break;
1039     }
1040     case JS_WEAK_SET_TYPE: {
1041       accumulator->Add("<JS WeakSet>");
1042       break;
1043     }
1044     case JS_REGEXP_TYPE: {
1045       accumulator->Add("<JS RegExp>");
1046       break;
1047     }
1048     case JS_FUNCTION_TYPE: {
1049       JSFunction* function = JSFunction::cast(this);
1050       Object* fun_name = function->shared()->DebugName();
1051       bool printed = false;
1052       if (fun_name->IsString()) {
1053         String* str = String::cast(fun_name);
1054         if (str->length() > 0) {
1055           accumulator->Add("<JS Function ");
1056           accumulator->Put(str);
1057           printed = true;
1058         }
1059       }
1060       if (!printed) {
1061         accumulator->Add("<JS Function");
1062       }
1063       accumulator->Add(" (SharedFunctionInfo %p)",
1064                        reinterpret_cast<void*>(function->shared()));
1065       accumulator->Put('>');
1066       break;
1067     }
1068     case JS_GENERATOR_OBJECT_TYPE: {
1069       accumulator->Add("<JS Generator>");
1070       break;
1071     }
1072     case JS_MODULE_TYPE: {
1073       accumulator->Add("<JS Module>");
1074       break;
1075     }
1076     // All other JSObjects are rather similar to each other (JSObject,
1077     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1078     default: {
1079       Map* map_of_this = map();
1080       Heap* heap = GetHeap();
1081       Object* constructor = map_of_this->GetConstructor();
1082       bool printed = false;
1083       if (constructor->IsHeapObject() &&
1084           !heap->Contains(HeapObject::cast(constructor))) {
1085         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1086       } else {
1087         bool global_object = IsJSGlobalProxy();
1088         if (constructor->IsJSFunction()) {
1089           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1090             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1091           } else {
1092             Object* constructor_name =
1093                 JSFunction::cast(constructor)->shared()->name();
1094             if (constructor_name->IsString()) {
1095               String* str = String::cast(constructor_name);
1096               if (str->length() > 0) {
1097                 bool vowel = AnWord(str);
1098                 accumulator->Add("<%sa%s ",
1099                        global_object ? "Global Object: " : "",
1100                        vowel ? "n" : "");
1101                 accumulator->Put(str);
1102                 accumulator->Add(" with %smap %p",
1103                     map_of_this->is_deprecated() ? "deprecated " : "",
1104                     map_of_this);
1105                 printed = true;
1106               }
1107             }
1108           }
1109         }
1110         if (!printed) {
1111           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1112         }
1113       }
1114       if (IsJSValue()) {
1115         accumulator->Add(" value = ");
1116         JSValue::cast(this)->value()->ShortPrint(accumulator);
1117       }
1118       accumulator->Put('>');
1119       break;
1120     }
1121   }
1122 }
1123
1124
1125 void JSObject::PrintElementsTransition(
1126     FILE* file, Handle<JSObject> object,
1127     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1128     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1129   if (from_kind != to_kind) {
1130     OFStream os(file);
1131     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1132        << ElementsKindToString(to_kind) << "] in ";
1133     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1134     PrintF(file, " for ");
1135     object->ShortPrint(file);
1136     PrintF(file, " from ");
1137     from_elements->ShortPrint(file);
1138     PrintF(file, " to ");
1139     to_elements->ShortPrint(file);
1140     PrintF(file, "\n");
1141   }
1142 }
1143
1144
1145 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
1146                                PropertyAttributes attributes) {
1147   OFStream os(file);
1148   os << "[reconfiguring ";
1149   constructor_name()->PrintOn(file);
1150   os << "] ";
1151   Name* name = instance_descriptors()->GetKey(modify_index);
1152   if (name->IsString()) {
1153     String::cast(name)->PrintOn(file);
1154   } else {
1155     os << "{symbol " << static_cast<void*>(name) << "}";
1156   }
1157   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
1158   os << attributes << " [";
1159   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1160   os << "]\n";
1161 }
1162
1163
1164 void Map::PrintGeneralization(FILE* file,
1165                               const char* reason,
1166                               int modify_index,
1167                               int split,
1168                               int descriptors,
1169                               bool constant_to_field,
1170                               Representation old_representation,
1171                               Representation new_representation,
1172                               HeapType* old_field_type,
1173                               HeapType* new_field_type) {
1174   OFStream os(file);
1175   os << "[generalizing ";
1176   constructor_name()->PrintOn(file);
1177   os << "] ";
1178   Name* name = instance_descriptors()->GetKey(modify_index);
1179   if (name->IsString()) {
1180     String::cast(name)->PrintOn(file);
1181   } else {
1182     os << "{symbol " << static_cast<void*>(name) << "}";
1183   }
1184   os << ":";
1185   if (constant_to_field) {
1186     os << "c";
1187   } else {
1188     os << old_representation.Mnemonic() << "{";
1189     old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1190     os << "}";
1191   }
1192   os << "->" << new_representation.Mnemonic() << "{";
1193   new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1194   os << "} (";
1195   if (strlen(reason) > 0) {
1196     os << reason;
1197   } else {
1198     os << "+" << (descriptors - split) << " maps";
1199   }
1200   os << ") [";
1201   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1202   os << "]\n";
1203 }
1204
1205
1206 void JSObject::PrintInstanceMigration(FILE* file,
1207                                       Map* original_map,
1208                                       Map* new_map) {
1209   PrintF(file, "[migrating ");
1210   map()->constructor_name()->PrintOn(file);
1211   PrintF(file, "] ");
1212   DescriptorArray* o = original_map->instance_descriptors();
1213   DescriptorArray* n = new_map->instance_descriptors();
1214   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1215     Representation o_r = o->GetDetails(i).representation();
1216     Representation n_r = n->GetDetails(i).representation();
1217     if (!o_r.Equals(n_r)) {
1218       String::cast(o->GetKey(i))->PrintOn(file);
1219       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1220     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
1221                n->GetDetails(i).type() == DATA) {
1222       Name* name = o->GetKey(i);
1223       if (name->IsString()) {
1224         String::cast(name)->PrintOn(file);
1225       } else {
1226         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1227       }
1228       PrintF(file, " ");
1229     }
1230   }
1231   PrintF(file, "\n");
1232 }
1233
1234
1235 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
1236   Heap* heap = GetHeap();
1237   if (!heap->Contains(this)) {
1238     os << "!!!INVALID POINTER!!!";
1239     return;
1240   }
1241   if (!heap->Contains(map())) {
1242     os << "!!!INVALID MAP!!!";
1243     return;
1244   }
1245
1246   os << this << " ";
1247
1248   if (IsString()) {
1249     HeapStringAllocator allocator;
1250     StringStream accumulator(&allocator);
1251     String::cast(this)->StringShortPrint(&accumulator);
1252     os << accumulator.ToCString().get();
1253     return;
1254   }
1255   if (IsJSObject()) {
1256     HeapStringAllocator allocator;
1257     StringStream accumulator(&allocator);
1258     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1259     os << accumulator.ToCString().get();
1260     return;
1261   }
1262   switch (map()->instance_type()) {
1263     case MAP_TYPE:
1264       os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
1265          << ")>";
1266       break;
1267     case FIXED_ARRAY_TYPE:
1268       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1269       break;
1270     case FIXED_DOUBLE_ARRAY_TYPE:
1271       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1272          << "]>";
1273       break;
1274     case BYTE_ARRAY_TYPE:
1275       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1276       break;
1277     case BYTECODE_ARRAY_TYPE:
1278       os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
1279       break;
1280     case FREE_SPACE_TYPE:
1281       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1282       break;
1283 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1284   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1285     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1286        << "]>";                                                               \
1287     break;
1288
1289     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1290 #undef TYPED_ARRAY_SHORT_PRINT
1291
1292     case SHARED_FUNCTION_INFO_TYPE: {
1293       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1294       base::SmartArrayPointer<char> debug_name =
1295           shared->DebugName()->ToCString();
1296       if (debug_name[0] != 0) {
1297         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1298       } else {
1299         os << "<SharedFunctionInfo>";
1300       }
1301       break;
1302     }
1303     case JS_MESSAGE_OBJECT_TYPE:
1304       os << "<JSMessageObject>";
1305       break;
1306 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1307   case NAME##_TYPE:                        \
1308     os << "<" #Name ">";                   \
1309     break;
1310   STRUCT_LIST(MAKE_STRUCT_CASE)
1311 #undef MAKE_STRUCT_CASE
1312     case CODE_TYPE: {
1313       Code* code = Code::cast(this);
1314       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1315       break;
1316     }
1317     case ODDBALL_TYPE: {
1318       if (IsUndefined()) {
1319         os << "<undefined>";
1320       } else if (IsTheHole()) {
1321         os << "<the hole>";
1322       } else if (IsNull()) {
1323         os << "<null>";
1324       } else if (IsTrue()) {
1325         os << "<true>";
1326       } else if (IsFalse()) {
1327         os << "<false>";
1328       } else {
1329         os << "<Odd Oddball>";
1330       }
1331       break;
1332     }
1333     case SYMBOL_TYPE: {
1334       Symbol* symbol = Symbol::cast(this);
1335       symbol->SymbolShortPrint(os);
1336       break;
1337     }
1338     case HEAP_NUMBER_TYPE: {
1339       os << "<Number: ";
1340       HeapNumber::cast(this)->HeapNumberPrint(os);
1341       os << ">";
1342       break;
1343     }
1344     case MUTABLE_HEAP_NUMBER_TYPE: {
1345       os << "<MutableNumber: ";
1346       HeapNumber::cast(this)->HeapNumberPrint(os);
1347       os << '>';
1348       break;
1349     }
1350     case FLOAT32X4_TYPE: {
1351       os << "<Float32x4: ";
1352       Float32x4::cast(this)->Float32x4Print(os);
1353       os << ">";
1354       break;
1355     }
1356     case JS_PROXY_TYPE:
1357       os << "<JSProxy>";
1358       break;
1359     case JS_FUNCTION_PROXY_TYPE:
1360       os << "<JSFunctionProxy>";
1361       break;
1362     case FOREIGN_TYPE:
1363       os << "<Foreign>";
1364       break;
1365     case CELL_TYPE: {
1366       os << "Cell for ";
1367       HeapStringAllocator allocator;
1368       StringStream accumulator(&allocator);
1369       Cell::cast(this)->value()->ShortPrint(&accumulator);
1370       os << accumulator.ToCString().get();
1371       break;
1372     }
1373     case PROPERTY_CELL_TYPE: {
1374       os << "PropertyCell for ";
1375       HeapStringAllocator allocator;
1376       StringStream accumulator(&allocator);
1377       PropertyCell* cell = PropertyCell::cast(this);
1378       cell->value()->ShortPrint(&accumulator);
1379       os << accumulator.ToCString().get() << " " << cell->property_details();
1380       break;
1381     }
1382     case WEAK_CELL_TYPE: {
1383       os << "WeakCell for ";
1384       HeapStringAllocator allocator;
1385       StringStream accumulator(&allocator);
1386       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
1387       os << accumulator.ToCString().get();
1388       break;
1389     }
1390     default:
1391       os << "<Other heap object (" << map()->instance_type() << ")>";
1392       break;
1393   }
1394 }
1395
1396
1397 void HeapObject::Iterate(ObjectVisitor* v) {
1398   // Handle header
1399   IteratePointer(v, kMapOffset);
1400   // Handle object body
1401   Map* m = map();
1402   IterateBody(m->instance_type(), SizeFromMap(m), v);
1403 }
1404
1405
1406 void HeapObject::IterateBody(InstanceType type, int object_size,
1407                              ObjectVisitor* v) {
1408   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1409   // During GC, the map pointer field is encoded.
1410   if (type < FIRST_NONSTRING_TYPE) {
1411     switch (type & kStringRepresentationMask) {
1412       case kSeqStringTag:
1413         break;
1414       case kConsStringTag:
1415         ConsString::BodyDescriptor::IterateBody(this, v);
1416         break;
1417       case kSlicedStringTag:
1418         SlicedString::BodyDescriptor::IterateBody(this, v);
1419         break;
1420       case kExternalStringTag:
1421         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1422           reinterpret_cast<ExternalOneByteString*>(this)
1423               ->ExternalOneByteStringIterateBody(v);
1424         } else {
1425           reinterpret_cast<ExternalTwoByteString*>(this)->
1426               ExternalTwoByteStringIterateBody(v);
1427         }
1428         break;
1429     }
1430     return;
1431   }
1432
1433   switch (type) {
1434     case FIXED_ARRAY_TYPE:
1435       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1436       break;
1437     case FIXED_DOUBLE_ARRAY_TYPE:
1438       break;
1439     case JS_OBJECT_TYPE:
1440     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1441     case JS_GENERATOR_OBJECT_TYPE:
1442     case JS_MODULE_TYPE:
1443     case JS_VALUE_TYPE:
1444     case JS_DATE_TYPE:
1445     case JS_ARRAY_TYPE:
1446     case JS_ARRAY_BUFFER_TYPE:
1447     case JS_TYPED_ARRAY_TYPE:
1448     case JS_DATA_VIEW_TYPE:
1449     case JS_SET_TYPE:
1450     case JS_MAP_TYPE:
1451     case JS_SET_ITERATOR_TYPE:
1452     case JS_MAP_ITERATOR_TYPE:
1453     case JS_WEAK_MAP_TYPE:
1454     case JS_WEAK_SET_TYPE:
1455     case JS_REGEXP_TYPE:
1456     case JS_GLOBAL_PROXY_TYPE:
1457     case JS_GLOBAL_OBJECT_TYPE:
1458     case JS_BUILTINS_OBJECT_TYPE:
1459     case JS_MESSAGE_OBJECT_TYPE:
1460       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1461       break;
1462     case JS_FUNCTION_TYPE:
1463       reinterpret_cast<JSFunction*>(this)
1464           ->JSFunctionIterateBody(object_size, v);
1465       break;
1466     case ODDBALL_TYPE:
1467       Oddball::BodyDescriptor::IterateBody(this, v);
1468       break;
1469     case JS_PROXY_TYPE:
1470       JSProxy::BodyDescriptor::IterateBody(this, v);
1471       break;
1472     case JS_FUNCTION_PROXY_TYPE:
1473       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1474       break;
1475     case FOREIGN_TYPE:
1476       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1477       break;
1478     case MAP_TYPE:
1479       Map::BodyDescriptor::IterateBody(this, v);
1480       break;
1481     case CODE_TYPE:
1482       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1483       break;
1484     case CELL_TYPE:
1485       Cell::BodyDescriptor::IterateBody(this, v);
1486       break;
1487     case PROPERTY_CELL_TYPE:
1488       PropertyCell::BodyDescriptor::IterateBody(this, v);
1489       break;
1490     case WEAK_CELL_TYPE:
1491       WeakCell::BodyDescriptor::IterateBody(this, v);
1492       break;
1493     case SYMBOL_TYPE:
1494       Symbol::BodyDescriptor::IterateBody(this, v);
1495       break;
1496
1497     case HEAP_NUMBER_TYPE:
1498     case MUTABLE_HEAP_NUMBER_TYPE:
1499     case FLOAT32X4_TYPE:
1500     case FILLER_TYPE:
1501     case BYTE_ARRAY_TYPE:
1502     case BYTECODE_ARRAY_TYPE:
1503     case FREE_SPACE_TYPE:
1504       break;
1505
1506 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1507   case FIXED_##TYPE##_ARRAY_TYPE:                       \
1508     reinterpret_cast<FixedTypedArrayBase*>(this)        \
1509         ->FixedTypedArrayBaseIterateBody(v);            \
1510     break;
1511
1512
1513     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1514 #undef TYPED_ARRAY_CASE
1515
1516     case SHARED_FUNCTION_INFO_TYPE: {
1517       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1518       break;
1519     }
1520
1521 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1522         case NAME##_TYPE:
1523       STRUCT_LIST(MAKE_STRUCT_CASE)
1524 #undef MAKE_STRUCT_CASE
1525       if (type == ALLOCATION_SITE_TYPE) {
1526         AllocationSite::BodyDescriptor::IterateBody(this, v);
1527       } else {
1528         StructBodyDescriptor::IterateBody(this, object_size, v);
1529       }
1530       break;
1531     default:
1532       PrintF("Unknown type: %d\n", type);
1533       UNREACHABLE();
1534   }
1535 }
1536
1537
1538 bool HeapNumber::HeapNumberBooleanValue() {
1539   return DoubleToBoolean(value());
1540 }
1541
1542
1543 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
1544   os << value();
1545 }
1546
1547
1548 void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
1549   char arr[100];
1550   Vector<char> buffer(arr, arraysize(arr));
1551   os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
1552      << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
1553      << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
1554      << std::string(DoubleToCString(get_lane(3), buffer));
1555 }
1556
1557
1558 String* JSReceiver::class_name() {
1559   if (IsJSFunction() || IsJSFunctionProxy()) {
1560     return GetHeap()->Function_string();
1561   }
1562   Object* maybe_constructor = map()->GetConstructor();
1563   if (maybe_constructor->IsJSFunction()) {
1564     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1565     return String::cast(constructor->shared()->instance_class_name());
1566   }
1567   // If the constructor is not present, return "Object".
1568   return GetHeap()->Object_string();
1569 }
1570
1571
1572 String* Map::constructor_name() {
1573   if (is_prototype_map() && prototype_info()->IsPrototypeInfo()) {
1574     PrototypeInfo* proto_info = PrototypeInfo::cast(prototype_info());
1575     if (proto_info->constructor_name()->IsString()) {
1576       return String::cast(proto_info->constructor_name());
1577     }
1578   }
1579   Object* maybe_constructor = GetConstructor();
1580   if (maybe_constructor->IsJSFunction()) {
1581     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1582     String* name = String::cast(constructor->shared()->name());
1583     if (name->length() > 0) return name;
1584     String* inferred_name = constructor->shared()->inferred_name();
1585     if (inferred_name->length() > 0) return inferred_name;
1586     Object* proto = prototype();
1587     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1588   }
1589   // TODO(rossberg): what about proxies?
1590   // If the constructor is not present, return "Object".
1591   return GetHeap()->Object_string();
1592 }
1593
1594
1595 String* JSReceiver::constructor_name() {
1596   return map()->constructor_name();
1597 }
1598
1599
1600 static Handle<Object> WrapType(Handle<HeapType> type) {
1601   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
1602   return type;
1603 }
1604
1605
1606 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1607                                     Handle<Name> name,
1608                                     Handle<HeapType> type,
1609                                     PropertyAttributes attributes,
1610                                     Representation representation,
1611                                     TransitionFlag flag) {
1612   DCHECK(DescriptorArray::kNotFound ==
1613          map->instance_descriptors()->Search(
1614              *name, map->NumberOfOwnDescriptors()));
1615
1616   // Ensure the descriptor array does not get too big.
1617   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1618     return MaybeHandle<Map>();
1619   }
1620
1621   Isolate* isolate = map->GetIsolate();
1622
1623   // Compute the new index for new field.
1624   int index = map->NextFreePropertyIndex();
1625
1626   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1627     representation = Representation::Tagged();
1628     type = HeapType::Any(isolate);
1629   }
1630
1631   Handle<Object> wrapped_type(WrapType(type));
1632
1633   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
1634                                 representation);
1635   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1636   int unused_property_fields = new_map->unused_property_fields() - 1;
1637   if (unused_property_fields < 0) {
1638     unused_property_fields += JSObject::kFieldsAdded;
1639   }
1640   new_map->set_unused_property_fields(unused_property_fields);
1641   return new_map;
1642 }
1643
1644
1645 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1646                                        Handle<Name> name,
1647                                        Handle<Object> constant,
1648                                        PropertyAttributes attributes,
1649                                        TransitionFlag flag) {
1650   // Ensure the descriptor array does not get too big.
1651   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1652     return MaybeHandle<Map>();
1653   }
1654
1655   // Allocate new instance descriptors with (name, constant) added.
1656   DataConstantDescriptor new_constant_desc(name, constant, attributes);
1657   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1658 }
1659
1660
1661 void JSObject::AddSlowProperty(Handle<JSObject> object,
1662                                Handle<Name> name,
1663                                Handle<Object> value,
1664                                PropertyAttributes attributes) {
1665   DCHECK(!object->HasFastProperties());
1666   Isolate* isolate = object->GetIsolate();
1667   if (object->IsGlobalObject()) {
1668     Handle<GlobalDictionary> dict(object->global_dictionary());
1669     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1670     int entry = dict->FindEntry(name);
1671     // If there's a cell there, just invalidate and set the property.
1672     if (entry != GlobalDictionary::kNotFound) {
1673       PropertyCell::UpdateCell(dict, entry, value, details);
1674       // TODO(ishell): move this to UpdateCell.
1675       // Need to adjust the details.
1676       int index = dict->NextEnumerationIndex();
1677       dict->SetNextEnumerationIndex(index + 1);
1678       PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
1679       details = cell->property_details().set_index(index);
1680       cell->set_property_details(details);
1681
1682     } else {
1683       auto cell = isolate->factory()->NewPropertyCell();
1684       cell->set_value(*value);
1685       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
1686                                             : PropertyCellType::kConstant;
1687       details = details.set_cell_type(cell_type);
1688       value = cell;
1689
1690       Handle<GlobalDictionary> result =
1691           GlobalDictionary::Add(dict, name, value, details);
1692       if (*dict != *result) object->set_properties(*result);
1693     }
1694   } else {
1695     Handle<NameDictionary> dict(object->property_dictionary());
1696     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1697     Handle<NameDictionary> result =
1698         NameDictionary::Add(dict, name, value, details);
1699     if (*dict != *result) object->set_properties(*result);
1700   }
1701 }
1702
1703
1704 Context* JSObject::GetCreationContext() {
1705   Object* constructor = this->map()->GetConstructor();
1706   JSFunction* function;
1707   if (!constructor->IsJSFunction()) {
1708     // Functions have null as a constructor,
1709     // but any JSFunction knows its context immediately.
1710     function = JSFunction::cast(this);
1711   } else {
1712     function = JSFunction::cast(constructor);
1713   }
1714
1715   return function->context()->native_context();
1716 }
1717
1718
1719 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1720                                                   const char* type_str,
1721                                                   Handle<Name> name,
1722                                                   Handle<Object> old_value) {
1723   DCHECK(!object->IsJSGlobalProxy());
1724   DCHECK(!object->IsJSGlobalObject());
1725   Isolate* isolate = object->GetIsolate();
1726   HandleScope scope(isolate);
1727   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1728   Handle<Object> args[] = { type, object, name, old_value };
1729   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1730
1731   return Execution::Call(isolate,
1732                          Handle<JSFunction>(isolate->observers_notify_change()),
1733                          isolate->factory()->undefined_value(), argc, args);
1734 }
1735
1736
1737 const char* Representation::Mnemonic() const {
1738   switch (kind_) {
1739     case kNone: return "v";
1740     case kTagged: return "t";
1741     case kSmi: return "s";
1742     case kDouble: return "d";
1743     case kInteger32: return "i";
1744     case kHeapObject: return "h";
1745     case kExternal: return "x";
1746     default:
1747       UNREACHABLE();
1748       return NULL;
1749   }
1750 }
1751
1752
1753 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1754                                  int target_inobject, int target_unused,
1755                                  int* old_number_of_fields) {
1756   // If fields were added (or removed), rewrite the instance.
1757   *old_number_of_fields = NumberOfFields();
1758   DCHECK(target_number_of_fields >= *old_number_of_fields);
1759   if (target_number_of_fields != *old_number_of_fields) return true;
1760
1761   // If smi descriptors were replaced by double descriptors, rewrite.
1762   DescriptorArray* old_desc = instance_descriptors();
1763   DescriptorArray* new_desc = target->instance_descriptors();
1764   int limit = NumberOfOwnDescriptors();
1765   for (int i = 0; i < limit; i++) {
1766     if (new_desc->GetDetails(i).representation().IsDouble() !=
1767         old_desc->GetDetails(i).representation().IsDouble()) {
1768       return true;
1769     }
1770   }
1771
1772   // If no fields were added, and no inobject properties were removed, setting
1773   // the map is sufficient.
1774   if (target_inobject == inobject_properties()) return false;
1775   // In-object slack tracking may have reduced the object size of the new map.
1776   // In that case, succeed if all existing fields were inobject, and they still
1777   // fit within the new inobject size.
1778   DCHECK(target_inobject < inobject_properties());
1779   if (target_number_of_fields <= target_inobject) {
1780     DCHECK(target_number_of_fields + target_unused == target_inobject);
1781     return false;
1782   }
1783   // Otherwise, properties will need to be moved to the backing store.
1784   return true;
1785 }
1786
1787
1788 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1789                             int expected_additional_properties) {
1790   if (object->map() == *new_map) return;
1791   // If this object is a prototype (the callee will check), invalidate any
1792   // prototype chains involving it.
1793   InvalidatePrototypeChains(object->map());
1794   Handle<Map> old_map(object->map());
1795
1796   // If the map was registered with its prototype before, ensure that it
1797   // registers with its new prototype now. This preserves the invariant that
1798   // when a map on a prototype chain is registered with its prototype, then
1799   // all prototypes further up the chain are also registered with their
1800   // respective prototypes.
1801   Object* maybe_old_prototype = old_map->prototype();
1802   if (FLAG_track_prototype_users && old_map->is_prototype_map() &&
1803       maybe_old_prototype->IsJSObject()) {
1804     Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
1805     bool was_registered =
1806         JSObject::UnregisterPrototypeUser(old_prototype, old_map);
1807     if (was_registered) {
1808       JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate());
1809     }
1810   }
1811
1812   if (object->HasFastProperties()) {
1813     if (!new_map->is_dictionary_map()) {
1814       MigrateFastToFast(object, new_map);
1815       if (old_map->is_prototype_map()) {
1816         // Clear out the old descriptor array to avoid problems to sharing
1817         // the descriptor array without using an explicit.
1818         old_map->InitializeDescriptors(
1819             old_map->GetHeap()->empty_descriptor_array(),
1820             LayoutDescriptor::FastPointerLayout());
1821         // Ensure that no transition was inserted for prototype migrations.
1822         DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1823                          old_map->raw_transitions()));
1824         DCHECK(new_map->GetBackPointer()->IsUndefined());
1825       }
1826     } else {
1827       MigrateFastToSlow(object, new_map, expected_additional_properties);
1828     }
1829   } else {
1830     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1831     // must be used instead.
1832     CHECK(new_map->is_dictionary_map());
1833
1834     // Slow-to-slow migration is trivial.
1835     object->set_map(*new_map);
1836   }
1837
1838   // Careful: Don't allocate here!
1839   // For some callers of this method, |object| might be in an inconsistent
1840   // state now: the new map might have a new elements_kind, but the object's
1841   // elements pointer hasn't been updated yet. Callers will fix this, but in
1842   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
1843   DisallowHeapAllocation no_object_verification;
1844
1845   if (old_map->is_prototype_map() && FLAG_track_prototype_users) {
1846     DCHECK(new_map->is_prototype_map());
1847     DCHECK(object->map() == *new_map);
1848     new_map->set_prototype_info(old_map->prototype_info());
1849     old_map->set_prototype_info(Smi::FromInt(0));
1850     if (FLAG_trace_prototype_users) {
1851       PrintF("Moving prototype_info %p from map %p to map %p.\n",
1852              reinterpret_cast<void*>(new_map->prototype_info()),
1853              reinterpret_cast<void*>(*old_map),
1854              reinterpret_cast<void*>(*new_map));
1855     }
1856   }
1857 }
1858
1859
1860 // To migrate a fast instance to a fast map:
1861 // - First check whether the instance needs to be rewritten. If not, simply
1862 //   change the map.
1863 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1864 //   addition to unused space.
1865 // - Copy all existing properties in, in the following order: backing store
1866 //   properties, unused fields, inobject properties.
1867 // - If all allocation succeeded, commit the state atomically:
1868 //   * Copy inobject properties from the backing store back into the object.
1869 //   * Trim the difference in instance size of the object. This also cleanly
1870 //     frees inobject properties that moved to the backing store.
1871 //   * If there are properties left in the backing store, trim of the space used
1872 //     to temporarily store the inobject properties.
1873 //   * If there are properties left in the backing store, install the backing
1874 //     store.
1875 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1876   Isolate* isolate = object->GetIsolate();
1877   Handle<Map> old_map(object->map());
1878   int old_number_of_fields;
1879   int number_of_fields = new_map->NumberOfFields();
1880   int inobject = new_map->inobject_properties();
1881   int unused = new_map->unused_property_fields();
1882
1883   // Nothing to do if no functions were converted to fields and no smis were
1884   // converted to doubles.
1885   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1886                                        unused, &old_number_of_fields)) {
1887     object->synchronized_set_map(*new_map);
1888     return;
1889   }
1890
1891   int total_size = number_of_fields + unused;
1892   int external = total_size - inobject;
1893
1894   if (number_of_fields != old_number_of_fields &&
1895       new_map->GetBackPointer() == *old_map) {
1896     PropertyDetails details = new_map->GetLastDescriptorDetails();
1897
1898     if (old_map->unused_property_fields() > 0) {
1899       if (details.representation().IsDouble()) {
1900         FieldIndex index =
1901             FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1902         if (new_map->IsUnboxedDoubleField(index)) {
1903           object->RawFastDoublePropertyAtPut(index, 0);
1904         } else {
1905           Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1906           object->RawFastPropertyAtPut(index, *value);
1907         }
1908       }
1909       object->synchronized_set_map(*new_map);
1910       return;
1911     }
1912
1913     DCHECK(number_of_fields == old_number_of_fields + 1);
1914     // This migration is a transition from a map that has run out of property
1915     // space. Therefore it could be done by extending the backing store.
1916     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1917     Handle<FixedArray> new_storage =
1918         FixedArray::CopySize(old_storage, external);
1919
1920     // Properly initialize newly added property.
1921     Handle<Object> value;
1922     if (details.representation().IsDouble()) {
1923       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1924     } else {
1925       value = isolate->factory()->uninitialized_value();
1926     }
1927     DCHECK(details.type() == DATA);
1928     int target_index = details.field_index() - inobject;
1929     DCHECK(target_index >= 0);  // Must be a backing store index.
1930     new_storage->set(target_index, *value);
1931
1932     // From here on we cannot fail and we shouldn't GC anymore.
1933     DisallowHeapAllocation no_allocation;
1934
1935     // Set the new property value and do the map transition.
1936     object->set_properties(*new_storage);
1937     object->synchronized_set_map(*new_map);
1938     return;
1939   }
1940   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
1941
1942   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
1943   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
1944   int old_nof = old_map->NumberOfOwnDescriptors();
1945   int new_nof = new_map->NumberOfOwnDescriptors();
1946
1947   // This method only supports generalizing instances to at least the same
1948   // number of properties.
1949   DCHECK(old_nof <= new_nof);
1950
1951   for (int i = 0; i < old_nof; i++) {
1952     PropertyDetails details = new_descriptors->GetDetails(i);
1953     if (details.type() != DATA) continue;
1954     PropertyDetails old_details = old_descriptors->GetDetails(i);
1955     Representation old_representation = old_details.representation();
1956     Representation representation = details.representation();
1957     Handle<Object> value;
1958     if (old_details.type() == ACCESSOR_CONSTANT) {
1959       // In case of kAccessor -> kData property reconfiguration, the property
1960       // must already be prepared for data or certain type.
1961       DCHECK(!details.representation().IsNone());
1962       if (details.representation().IsDouble()) {
1963         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1964       } else {
1965         value = isolate->factory()->uninitialized_value();
1966       }
1967     } else if (old_details.type() == DATA_CONSTANT) {
1968       value = handle(old_descriptors->GetValue(i), isolate);
1969       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
1970     } else {
1971       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
1972       if (object->IsUnboxedDoubleField(index)) {
1973         double old = object->RawFastDoublePropertyAt(index);
1974         value = isolate->factory()->NewHeapNumber(
1975             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
1976
1977       } else {
1978         value = handle(object->RawFastPropertyAt(index), isolate);
1979         if (!old_representation.IsDouble() && representation.IsDouble()) {
1980           if (old_representation.IsNone()) {
1981             value = handle(Smi::FromInt(0), isolate);
1982           }
1983           value = Object::NewStorageFor(isolate, value, representation);
1984         } else if (old_representation.IsDouble() &&
1985                    !representation.IsDouble()) {
1986           value = Object::WrapForRead(isolate, value, old_representation);
1987         }
1988       }
1989     }
1990     DCHECK(!(representation.IsDouble() && value->IsSmi()));
1991     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
1992     if (target_index < 0) target_index += total_size;
1993     array->set(target_index, *value);
1994   }
1995
1996   for (int i = old_nof; i < new_nof; i++) {
1997     PropertyDetails details = new_descriptors->GetDetails(i);
1998     if (details.type() != DATA) continue;
1999     Handle<Object> value;
2000     if (details.representation().IsDouble()) {
2001       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2002     } else {
2003       value = isolate->factory()->uninitialized_value();
2004     }
2005     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2006     if (target_index < 0) target_index += total_size;
2007     array->set(target_index, *value);
2008   }
2009
2010   // From here on we cannot fail and we shouldn't GC anymore.
2011   DisallowHeapAllocation no_allocation;
2012
2013   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2014   // avoid overwriting |one_pointer_filler_map|.
2015   int limit = Min(inobject, number_of_fields);
2016   for (int i = 0; i < limit; i++) {
2017     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2018     Object* value = array->get(external + i);
2019     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
2020     // yet.
2021     if (new_map->IsUnboxedDoubleField(index)) {
2022       DCHECK(value->IsMutableHeapNumber());
2023       object->RawFastDoublePropertyAtPut(index,
2024                                          HeapNumber::cast(value)->value());
2025     } else {
2026       object->RawFastPropertyAtPut(index, value);
2027     }
2028   }
2029
2030   Heap* heap = isolate->heap();
2031
2032   // If there are properties in the new backing store, trim it to the correct
2033   // size and install the backing store into the object.
2034   if (external > 0) {
2035     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
2036     object->set_properties(*array);
2037   }
2038
2039   // Create filler object past the new instance size.
2040   int new_instance_size = new_map->instance_size();
2041   int instance_size_delta = old_map->instance_size() - new_instance_size;
2042   DCHECK(instance_size_delta >= 0);
2043
2044   if (instance_size_delta > 0) {
2045     Address address = object->address();
2046     heap->CreateFillerObjectAt(
2047         address + new_instance_size, instance_size_delta);
2048     heap->AdjustLiveBytes(address, -instance_size_delta,
2049                           Heap::CONCURRENT_TO_SWEEPER);
2050   }
2051
2052   // We are storing the new map using release store after creating a filler for
2053   // the left-over space to avoid races with the sweeper thread.
2054   object->synchronized_set_map(*new_map);
2055 }
2056
2057
2058 int Map::NumberOfFields() {
2059   DescriptorArray* descriptors = instance_descriptors();
2060   int result = 0;
2061   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2062     if (descriptors->GetDetails(i).location() == kField) result++;
2063   }
2064   return result;
2065 }
2066
2067
2068 Handle<Map> Map::CopyGeneralizeAllRepresentations(
2069     Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
2070     PropertyAttributes attributes, const char* reason) {
2071   Isolate* isolate = map->GetIsolate();
2072   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2073   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2074   Handle<DescriptorArray> descriptors =
2075       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
2076
2077   for (int i = 0; i < number_of_own_descriptors; i++) {
2078     descriptors->SetRepresentation(i, Representation::Tagged());
2079     if (descriptors->GetDetails(i).type() == DATA) {
2080       descriptors->SetValue(i, HeapType::Any());
2081     }
2082   }
2083
2084   Handle<LayoutDescriptor> new_layout_descriptor(
2085       LayoutDescriptor::FastPointerLayout(), isolate);
2086   Handle<Map> new_map = CopyReplaceDescriptors(
2087       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
2088       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
2089
2090   // Unless the instance is being migrated, ensure that modify_index is a field.
2091   if (modify_index >= 0) {
2092     PropertyDetails details = descriptors->GetDetails(modify_index);
2093     if (store_mode == FORCE_FIELD &&
2094         (details.type() != DATA || details.attributes() != attributes)) {
2095       int field_index = details.type() == DATA ? details.field_index()
2096                                                : new_map->NumberOfFields();
2097       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2098                        field_index, attributes, Representation::Tagged());
2099       descriptors->Replace(modify_index, &d);
2100       if (details.type() != DATA) {
2101         int unused_property_fields = new_map->unused_property_fields() - 1;
2102         if (unused_property_fields < 0) {
2103           unused_property_fields += JSObject::kFieldsAdded;
2104         }
2105         new_map->set_unused_property_fields(unused_property_fields);
2106       }
2107     } else {
2108       DCHECK(details.attributes() == attributes);
2109     }
2110
2111     if (FLAG_trace_generalization) {
2112       HeapType* field_type =
2113           (details.type() == DATA)
2114               ? map->instance_descriptors()->GetFieldType(modify_index)
2115               : NULL;
2116       map->PrintGeneralization(
2117           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
2118           new_map->NumberOfOwnDescriptors(),
2119           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
2120           details.representation(), Representation::Tagged(), field_type,
2121           HeapType::Any());
2122     }
2123   }
2124   return new_map;
2125 }
2126
2127
2128 void Map::DeprecateTransitionTree() {
2129   if (is_deprecated()) return;
2130   Object* transitions = raw_transitions();
2131   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2132   for (int i = 0; i < num_transitions; ++i) {
2133     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
2134   }
2135   deprecate();
2136   dependent_code()->DeoptimizeDependentCodeGroup(
2137       GetIsolate(), DependentCode::kTransitionGroup);
2138   NotifyLeafMapLayoutChange();
2139 }
2140
2141
2142 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2143   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
2144   // TODO(ishell): compare AccessorPairs.
2145   return false;
2146 }
2147
2148
2149 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2150 // the current instance_descriptors to ensure proper sharing of descriptor
2151 // arrays.
2152 // Returns true if the transition target at given key was deprecated.
2153 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2154                           PropertyAttributes attributes,
2155                           DescriptorArray* new_descriptors,
2156                           LayoutDescriptor* new_layout_descriptor) {
2157   bool transition_target_deprecated = false;
2158   Map* maybe_transition =
2159       TransitionArray::SearchTransition(this, kind, key, attributes);
2160   if (maybe_transition != NULL) {
2161     maybe_transition->DeprecateTransitionTree();
2162     transition_target_deprecated = true;
2163   }
2164
2165   // Don't overwrite the empty descriptor array.
2166   if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
2167
2168   DescriptorArray* to_replace = instance_descriptors();
2169   Map* current = this;
2170   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2171   while (current->instance_descriptors() == to_replace) {
2172     current->SetEnumLength(kInvalidEnumCacheSentinel);
2173     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2174     Object* next = current->GetBackPointer();
2175     if (next->IsUndefined()) break;
2176     current = Map::cast(next);
2177   }
2178
2179   set_owns_descriptors(false);
2180   return transition_target_deprecated;
2181 }
2182
2183
2184 Map* Map::FindRootMap() {
2185   Map* result = this;
2186   while (true) {
2187     Object* back = result->GetBackPointer();
2188     if (back->IsUndefined()) return result;
2189     result = Map::cast(back);
2190   }
2191 }
2192
2193
2194 Map* Map::FindLastMatchMap(int verbatim,
2195                            int length,
2196                            DescriptorArray* descriptors) {
2197   DisallowHeapAllocation no_allocation;
2198
2199   // This can only be called on roots of transition trees.
2200   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
2201
2202   Map* current = this;
2203
2204   for (int i = verbatim; i < length; i++) {
2205     Name* name = descriptors->GetKey(i);
2206     PropertyDetails details = descriptors->GetDetails(i);
2207     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
2208                                                   details.attributes());
2209     if (next == NULL) break;
2210     DescriptorArray* next_descriptors = next->instance_descriptors();
2211
2212     PropertyDetails next_details = next_descriptors->GetDetails(i);
2213     DCHECK_EQ(details.kind(), next_details.kind());
2214     DCHECK_EQ(details.attributes(), next_details.attributes());
2215     if (details.location() != next_details.location()) break;
2216     if (!details.representation().Equals(next_details.representation())) break;
2217
2218     if (next_details.location() == kField) {
2219       HeapType* next_field_type = next_descriptors->GetFieldType(i);
2220       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
2221         break;
2222       }
2223     } else {
2224       if (!EqualImmutableValues(descriptors->GetValue(i),
2225                                 next_descriptors->GetValue(i))) {
2226         break;
2227       }
2228     }
2229     current = next;
2230   }
2231   return current;
2232 }
2233
2234
2235 Map* Map::FindFieldOwner(int descriptor) {
2236   DisallowHeapAllocation no_allocation;
2237   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
2238   Map* result = this;
2239   while (true) {
2240     Object* back = result->GetBackPointer();
2241     if (back->IsUndefined()) break;
2242     Map* parent = Map::cast(back);
2243     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2244     result = parent;
2245   }
2246   return result;
2247 }
2248
2249
2250 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2251                           Representation new_representation,
2252                           Handle<Object> new_wrapped_type) {
2253   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
2254   DisallowHeapAllocation no_allocation;
2255   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2256   if (details.type() != DATA) return;
2257   Object* transitions = raw_transitions();
2258   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2259   for (int i = 0; i < num_transitions; ++i) {
2260     Map* target = TransitionArray::GetTarget(transitions, i);
2261     target->UpdateFieldType(descriptor, name, new_representation,
2262                             new_wrapped_type);
2263   }
2264   // It is allowed to change representation here only from None to something.
2265   DCHECK(details.representation().Equals(new_representation) ||
2266          details.representation().IsNone());
2267
2268   // Skip if already updated the shared descriptor.
2269   if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return;
2270   DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2271                    new_wrapped_type, details.attributes(), new_representation);
2272   instance_descriptors()->Replace(descriptor, &d);
2273 }
2274
2275
2276 // static
2277 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2278                                           Handle<HeapType> type2,
2279                                           Isolate* isolate) {
2280   if (type1->NowIs(type2)) return type2;
2281   if (type2->NowIs(type1)) return type1;
2282   return HeapType::Any(isolate);
2283 }
2284
2285
2286 // static
2287 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
2288                               Representation new_representation,
2289                               Handle<HeapType> new_field_type) {
2290   Isolate* isolate = map->GetIsolate();
2291
2292   // Check if we actually need to generalize the field type at all.
2293   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2294   Representation old_representation =
2295       old_descriptors->GetDetails(modify_index).representation();
2296   Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
2297                                   isolate);
2298
2299   if (old_representation.Equals(new_representation) &&
2300       new_field_type->NowIs(old_field_type)) {
2301     DCHECK(Map::GeneralizeFieldType(old_field_type,
2302                                     new_field_type,
2303                                     isolate)->NowIs(old_field_type));
2304     return;
2305   }
2306
2307   // Determine the field owner.
2308   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2309   Handle<DescriptorArray> descriptors(
2310       field_owner->instance_descriptors(), isolate);
2311   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2312   bool old_field_type_was_cleared =
2313       old_field_type->Is(HeapType::None()) && old_representation.IsHeapObject();
2314
2315   // Determine the generalized new field type. Conservatively assume type Any
2316   // for cleared field types because the cleared type could have been a
2317   // deprecated map and there still could be live instances with a non-
2318   // deprecated version of the map.
2319   new_field_type =
2320       old_field_type_was_cleared
2321           ? HeapType::Any(isolate)
2322           : Map::GeneralizeFieldType(old_field_type, new_field_type, isolate);
2323
2324   PropertyDetails details = descriptors->GetDetails(modify_index);
2325   Handle<Name> name(descriptors->GetKey(modify_index));
2326
2327   Handle<Object> wrapped_type(WrapType(new_field_type));
2328   field_owner->UpdateFieldType(modify_index, name, new_representation,
2329                                wrapped_type);
2330   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2331       isolate, DependentCode::kFieldTypeGroup);
2332
2333   if (FLAG_trace_generalization) {
2334     map->PrintGeneralization(
2335         stdout, "field type generalization",
2336         modify_index, map->NumberOfOwnDescriptors(),
2337         map->NumberOfOwnDescriptors(), false,
2338         details.representation(), details.representation(),
2339         *old_field_type, *new_field_type);
2340   }
2341 }
2342
2343
2344 static inline Handle<HeapType> GetFieldType(Isolate* isolate,
2345                                             Handle<DescriptorArray> descriptors,
2346                                             int descriptor,
2347                                             PropertyLocation location,
2348                                             Representation representation) {
2349 #ifdef DEBUG
2350   PropertyDetails details = descriptors->GetDetails(descriptor);
2351   DCHECK_EQ(kData, details.kind());
2352   DCHECK_EQ(details.location(), location);
2353 #endif
2354   if (location == kField) {
2355     return handle(descriptors->GetFieldType(descriptor), isolate);
2356   } else {
2357     return descriptors->GetValue(descriptor)
2358         ->OptimalType(isolate, representation);
2359   }
2360 }
2361
2362
2363 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
2364 // |store_mode| and/or |new_representation|/|new_field_type|.
2365 // If |modify_index| is negative then no properties are reconfigured but the
2366 // map is migrated to the up-to-date non-deprecated state.
2367 //
2368 // This method rewrites or completes the transition tree to reflect the new
2369 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
2370 // on every rewrite the new type is deduced by merging the current type with
2371 // any potential new (partial) version of the type in the transition tree.
2372 // To do this, on each rewrite:
2373 // - Search the root of the transition tree using FindRootMap.
2374 // - Find |target_map|, the newest matching version of this map using the
2375 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
2376 //   |modify_index| is considered to be of |new_kind| and having
2377 //   |new_attributes|) to walk the transition tree.
2378 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
2379 //   descriptor array of the |target_map|.
2380 // - Generalize the |modify_index| descriptor using |new_representation| and
2381 //   |new_field_type|.
2382 // - Walk the tree again starting from the root towards |target_map|. Stop at
2383 //   |split_map|, the first map who's descriptor array does not match the merged
2384 //   descriptor array.
2385 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2386 //   Return it.
2387 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2388 //   replace its transition tree with a new branch for the updated descriptors.
2389 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2390                                      PropertyKind new_kind,
2391                                      PropertyAttributes new_attributes,
2392                                      Representation new_representation,
2393                                      Handle<HeapType> new_field_type,
2394                                      StoreMode store_mode) {
2395   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
2396   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2397   Isolate* isolate = old_map->GetIsolate();
2398
2399   Handle<DescriptorArray> old_descriptors(
2400       old_map->instance_descriptors(), isolate);
2401   int old_nof = old_map->NumberOfOwnDescriptors();
2402
2403   // If it's just a representation generalization case (i.e. property kind and
2404   // attributes stays unchanged) it's fine to transition from None to anything
2405   // but double without any modification to the object, because the default
2406   // uninitialized value for representation None can be overwritten by both
2407   // smi and tagged values. Doubles, however, would require a box allocation.
2408   if (modify_index >= 0 && !new_representation.IsNone() &&
2409       !new_representation.IsDouble()) {
2410     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2411     Representation old_representation = old_details.representation();
2412
2413     if (old_representation.IsNone()) {
2414       DCHECK_EQ(new_kind, old_details.kind());
2415       DCHECK_EQ(new_attributes, old_details.attributes());
2416       DCHECK_EQ(DATA, old_details.type());
2417       if (FLAG_trace_generalization) {
2418         old_map->PrintGeneralization(
2419             stdout, "uninitialized field", modify_index,
2420             old_map->NumberOfOwnDescriptors(),
2421             old_map->NumberOfOwnDescriptors(), false, old_representation,
2422             new_representation, old_descriptors->GetFieldType(modify_index),
2423             *new_field_type);
2424       }
2425       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2426
2427       GeneralizeFieldType(field_owner, modify_index, new_representation,
2428                           new_field_type);
2429       DCHECK(old_descriptors->GetDetails(modify_index)
2430                  .representation()
2431                  .Equals(new_representation));
2432       DCHECK(
2433           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2434       return old_map;
2435     }
2436   }
2437
2438   // Check the state of the root map.
2439   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2440   if (!old_map->EquivalentToForTransition(*root_map)) {
2441     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2442                                             new_kind, new_attributes,
2443                                             "GenAll_NotEquivalent");
2444   }
2445
2446   ElementsKind from_kind = root_map->elements_kind();
2447   ElementsKind to_kind = old_map->elements_kind();
2448   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
2449   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
2450       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
2451       !(IsTransitionableFastElementsKind(from_kind) &&
2452         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2453     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2454                                             new_kind, new_attributes,
2455                                             "GenAll_InvalidElementsTransition");
2456   }
2457   int root_nof = root_map->NumberOfOwnDescriptors();
2458   if (modify_index >= 0 && modify_index < root_nof) {
2459     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2460     if (old_details.kind() != new_kind ||
2461         old_details.attributes() != new_attributes) {
2462       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2463                                               new_kind, new_attributes,
2464                                               "GenAll_RootModification1");
2465     }
2466     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2467         (old_details.type() == DATA &&
2468          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2469           !new_representation.fits_into(old_details.representation())))) {
2470       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2471                                               new_kind, new_attributes,
2472                                               "GenAll_RootModification2");
2473     }
2474   }
2475
2476   // From here on, use the map with correct elements kind as root map.
2477   if (from_kind != to_kind) {
2478     root_map = Map::AsElementsKind(root_map, to_kind);
2479   }
2480
2481   Handle<Map> target_map = root_map;
2482   for (int i = root_nof; i < old_nof; ++i) {
2483     PropertyDetails old_details = old_descriptors->GetDetails(i);
2484     PropertyKind next_kind;
2485     PropertyLocation next_location;
2486     PropertyAttributes next_attributes;
2487     Representation next_representation;
2488     bool property_kind_reconfiguration = false;
2489
2490     if (modify_index == i) {
2491       DCHECK_EQ(FORCE_FIELD, store_mode);
2492       property_kind_reconfiguration = old_details.kind() != new_kind;
2493
2494       next_kind = new_kind;
2495       next_location = kField;
2496       next_attributes = new_attributes;
2497       // If property kind is not reconfigured merge the result with
2498       // representation/field type from the old descriptor.
2499       next_representation = new_representation;
2500       if (!property_kind_reconfiguration) {
2501         next_representation =
2502             next_representation.generalize(old_details.representation());
2503       }
2504
2505     } else {
2506       next_kind = old_details.kind();
2507       next_location = old_details.location();
2508       next_attributes = old_details.attributes();
2509       next_representation = old_details.representation();
2510     }
2511     Map* transition = TransitionArray::SearchTransition(
2512         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2513     if (transition == NULL) break;
2514     Handle<Map> tmp_map(transition, isolate);
2515
2516     Handle<DescriptorArray> tmp_descriptors = handle(
2517         tmp_map->instance_descriptors(), isolate);
2518
2519     // Check if target map is incompatible.
2520     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2521     DCHECK_EQ(next_kind, tmp_details.kind());
2522     DCHECK_EQ(next_attributes, tmp_details.attributes());
2523     if (next_kind == kAccessor &&
2524         !EqualImmutableValues(old_descriptors->GetValue(i),
2525                               tmp_descriptors->GetValue(i))) {
2526       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2527                                               new_kind, new_attributes,
2528                                               "GenAll_Incompatible");
2529     }
2530     if (next_location == kField && tmp_details.location() == kDescriptor) break;
2531
2532     Representation tmp_representation = tmp_details.representation();
2533     if (!next_representation.fits_into(tmp_representation)) break;
2534
2535     PropertyLocation old_location = old_details.location();
2536     PropertyLocation tmp_location = tmp_details.location();
2537     if (tmp_location == kField) {
2538       if (next_kind == kData) {
2539         Handle<HeapType> next_field_type;
2540         if (modify_index == i) {
2541           next_field_type = new_field_type;
2542           if (!property_kind_reconfiguration) {
2543             Handle<HeapType> old_field_type =
2544                 GetFieldType(isolate, old_descriptors, i,
2545                              old_details.location(), tmp_representation);
2546             next_field_type =
2547                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2548           }
2549         } else {
2550           Handle<HeapType> old_field_type =
2551               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2552                            tmp_representation);
2553           next_field_type = old_field_type;
2554         }
2555         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
2556       }
2557     } else if (old_location == kField ||
2558                !EqualImmutableValues(old_descriptors->GetValue(i),
2559                                      tmp_descriptors->GetValue(i))) {
2560       break;
2561     }
2562     DCHECK(!tmp_map->is_deprecated());
2563     target_map = tmp_map;
2564   }
2565
2566   // Directly change the map if the target map is more general.
2567   Handle<DescriptorArray> target_descriptors(
2568       target_map->instance_descriptors(), isolate);
2569   int target_nof = target_map->NumberOfOwnDescriptors();
2570   if (target_nof == old_nof &&
2571       (store_mode != FORCE_FIELD ||
2572        (modify_index >= 0 &&
2573         target_descriptors->GetDetails(modify_index).location() == kField))) {
2574 #ifdef DEBUG
2575     if (modify_index >= 0) {
2576       PropertyDetails details = target_descriptors->GetDetails(modify_index);
2577       DCHECK_EQ(new_kind, details.kind());
2578       DCHECK_EQ(new_attributes, details.attributes());
2579       DCHECK(new_representation.fits_into(details.representation()));
2580       DCHECK(details.location() != kField ||
2581              new_field_type->NowIs(
2582                  target_descriptors->GetFieldType(modify_index)));
2583     }
2584 #endif
2585     if (*target_map != *old_map) {
2586       old_map->NotifyLeafMapLayoutChange();
2587     }
2588     return target_map;
2589   }
2590
2591   // Find the last compatible target map in the transition tree.
2592   for (int i = target_nof; i < old_nof; ++i) {
2593     PropertyDetails old_details = old_descriptors->GetDetails(i);
2594     PropertyKind next_kind;
2595     PropertyAttributes next_attributes;
2596     if (modify_index == i) {
2597       next_kind = new_kind;
2598       next_attributes = new_attributes;
2599     } else {
2600       next_kind = old_details.kind();
2601       next_attributes = old_details.attributes();
2602     }
2603     Map* transition = TransitionArray::SearchTransition(
2604         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2605     if (transition == NULL) break;
2606     Handle<Map> tmp_map(transition, isolate);
2607     Handle<DescriptorArray> tmp_descriptors(
2608         tmp_map->instance_descriptors(), isolate);
2609
2610     // Check if target map is compatible.
2611 #ifdef DEBUG
2612     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2613     DCHECK_EQ(next_kind, tmp_details.kind());
2614     DCHECK_EQ(next_attributes, tmp_details.attributes());
2615 #endif
2616     if (next_kind == kAccessor &&
2617         !EqualImmutableValues(old_descriptors->GetValue(i),
2618                               tmp_descriptors->GetValue(i))) {
2619       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2620                                               new_kind, new_attributes,
2621                                               "GenAll_Incompatible");
2622     }
2623     DCHECK(!tmp_map->is_deprecated());
2624     target_map = tmp_map;
2625   }
2626   target_nof = target_map->NumberOfOwnDescriptors();
2627   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2628
2629   // Allocate a new descriptor array large enough to hold the required
2630   // descriptors, with minimally the exact same size as the old descriptor
2631   // array.
2632   int new_slack = Max(
2633       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2634   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2635       isolate, old_nof, new_slack);
2636   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2637          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2638          new_descriptors->number_of_descriptors() ==
2639          old_descriptors->number_of_descriptors());
2640   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2641
2642   // 0 -> |root_nof|
2643   int current_offset = 0;
2644   for (int i = 0; i < root_nof; ++i) {
2645     PropertyDetails old_details = old_descriptors->GetDetails(i);
2646     if (old_details.location() == kField) {
2647       current_offset += old_details.field_width_in_words();
2648     }
2649     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2650                  handle(old_descriptors->GetValue(i), isolate),
2651                  old_details);
2652     new_descriptors->Set(i, &d);
2653   }
2654
2655   // |root_nof| -> |target_nof|
2656   for (int i = root_nof; i < target_nof; ++i) {
2657     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2658     PropertyDetails old_details = old_descriptors->GetDetails(i);
2659     PropertyDetails target_details = target_descriptors->GetDetails(i);
2660
2661     PropertyKind next_kind;
2662     PropertyAttributes next_attributes;
2663     PropertyLocation next_location;
2664     Representation next_representation;
2665     bool property_kind_reconfiguration = false;
2666
2667     if (modify_index == i) {
2668       DCHECK_EQ(FORCE_FIELD, store_mode);
2669       property_kind_reconfiguration = old_details.kind() != new_kind;
2670
2671       next_kind = new_kind;
2672       next_attributes = new_attributes;
2673       next_location = kField;
2674
2675       // Merge new representation/field type with ones from the target
2676       // descriptor. If property kind is not reconfigured merge the result with
2677       // representation/field type from the old descriptor.
2678       next_representation =
2679           new_representation.generalize(target_details.representation());
2680       if (!property_kind_reconfiguration) {
2681         next_representation =
2682             next_representation.generalize(old_details.representation());
2683       }
2684     } else {
2685       // Merge old_descriptor and target_descriptor entries.
2686       DCHECK_EQ(target_details.kind(), old_details.kind());
2687       next_kind = target_details.kind();
2688       next_attributes = target_details.attributes();
2689       next_location =
2690           old_details.location() == kField ||
2691                   target_details.location() == kField ||
2692                   !EqualImmutableValues(target_descriptors->GetValue(i),
2693                                         old_descriptors->GetValue(i))
2694               ? kField
2695               : kDescriptor;
2696
2697       next_representation = old_details.representation().generalize(
2698           target_details.representation());
2699     }
2700     DCHECK_EQ(next_kind, target_details.kind());
2701     DCHECK_EQ(next_attributes, target_details.attributes());
2702
2703     if (next_location == kField) {
2704       if (next_kind == kData) {
2705         Handle<HeapType> target_field_type =
2706             GetFieldType(isolate, target_descriptors, i,
2707                          target_details.location(), next_representation);
2708
2709         Handle<HeapType> next_field_type;
2710         if (modify_index == i) {
2711           next_field_type =
2712               GeneralizeFieldType(target_field_type, new_field_type, isolate);
2713           if (!property_kind_reconfiguration) {
2714             Handle<HeapType> old_field_type =
2715                 GetFieldType(isolate, old_descriptors, i,
2716                              old_details.location(), next_representation);
2717             next_field_type =
2718                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2719           }
2720         } else {
2721           Handle<HeapType> old_field_type =
2722               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2723                            next_representation);
2724           next_field_type =
2725               GeneralizeFieldType(target_field_type, old_field_type, isolate);
2726         }
2727         Handle<Object> wrapped_type(WrapType(next_field_type));
2728         DataDescriptor d(target_key, current_offset, wrapped_type,
2729                          next_attributes, next_representation);
2730         current_offset += d.GetDetails().field_width_in_words();
2731         new_descriptors->Set(i, &d);
2732       } else {
2733         UNIMPLEMENTED();  // TODO(ishell): implement.
2734       }
2735     } else {
2736       PropertyDetails details(next_attributes, next_kind, next_location,
2737                               next_representation);
2738       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
2739                    details);
2740       new_descriptors->Set(i, &d);
2741     }
2742   }
2743
2744   // |target_nof| -> |old_nof|
2745   for (int i = target_nof; i < old_nof; ++i) {
2746     PropertyDetails old_details = old_descriptors->GetDetails(i);
2747     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2748
2749     // Merge old_descriptor entry and modified details together.
2750     PropertyKind next_kind;
2751     PropertyAttributes next_attributes;
2752     PropertyLocation next_location;
2753     Representation next_representation;
2754     bool property_kind_reconfiguration = false;
2755
2756     if (modify_index == i) {
2757       DCHECK_EQ(FORCE_FIELD, store_mode);
2758       // In case of property kind reconfiguration it is not necessary to
2759       // take into account representation/field type of the old descriptor.
2760       property_kind_reconfiguration = old_details.kind() != new_kind;
2761
2762       next_kind = new_kind;
2763       next_attributes = new_attributes;
2764       next_location = kField;
2765       next_representation = new_representation;
2766       if (!property_kind_reconfiguration) {
2767         next_representation =
2768             next_representation.generalize(old_details.representation());
2769       }
2770     } else {
2771       next_kind = old_details.kind();
2772       next_attributes = old_details.attributes();
2773       next_location = old_details.location();
2774       next_representation = old_details.representation();
2775     }
2776
2777     if (next_location == kField) {
2778       if (next_kind == kData) {
2779         Handle<HeapType> next_field_type;
2780         if (modify_index == i) {
2781           next_field_type = new_field_type;
2782           if (!property_kind_reconfiguration) {
2783             Handle<HeapType> old_field_type =
2784                 GetFieldType(isolate, old_descriptors, i,
2785                              old_details.location(), next_representation);
2786             next_field_type =
2787                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2788           }
2789         } else {
2790           Handle<HeapType> old_field_type =
2791               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2792                            next_representation);
2793           next_field_type = old_field_type;
2794         }
2795
2796         Handle<Object> wrapped_type(WrapType(next_field_type));
2797
2798         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
2799                          next_representation);
2800         current_offset += d.GetDetails().field_width_in_words();
2801         new_descriptors->Set(i, &d);
2802       } else {
2803         UNIMPLEMENTED();  // TODO(ishell): implement.
2804       }
2805     } else {
2806       PropertyDetails details(next_attributes, next_kind, next_location,
2807                               next_representation);
2808       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
2809                    details);
2810       new_descriptors->Set(i, &d);
2811     }
2812   }
2813
2814   new_descriptors->Sort();
2815
2816   DCHECK(store_mode != FORCE_FIELD ||
2817          new_descriptors->GetDetails(modify_index).location() == kField);
2818
2819   Handle<Map> split_map(root_map->FindLastMatchMap(
2820           root_nof, old_nof, *new_descriptors), isolate);
2821   int split_nof = split_map->NumberOfOwnDescriptors();
2822   DCHECK_NE(old_nof, split_nof);
2823
2824   Handle<LayoutDescriptor> new_layout_descriptor =
2825       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
2826
2827   PropertyKind split_kind;
2828   PropertyAttributes split_attributes;
2829   if (modify_index == split_nof) {
2830     split_kind = new_kind;
2831     split_attributes = new_attributes;
2832   } else {
2833     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
2834     split_kind = split_prop_details.kind();
2835     split_attributes = split_prop_details.attributes();
2836   }
2837   bool transition_target_deprecated = split_map->DeprecateTarget(
2838       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2839       *new_descriptors, *new_layout_descriptor);
2840
2841   // If |transition_target_deprecated| is true then the transition array
2842   // already contains entry for given descriptor. This means that the transition
2843   // could be inserted regardless of whether transitions array is full or not.
2844   if (!transition_target_deprecated &&
2845       !TransitionArray::CanHaveMoreTransitions(split_map)) {
2846     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2847                                             new_kind, new_attributes,
2848                                             "GenAll_CantHaveMoreTransitions");
2849   }
2850
2851   old_map->NotifyLeafMapLayoutChange();
2852
2853   if (FLAG_trace_generalization && modify_index >= 0) {
2854     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2855     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2856     Handle<HeapType> old_field_type =
2857         (old_details.type() == DATA)
2858             ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2859             : HeapType::Constant(
2860                   handle(old_descriptors->GetValue(modify_index), isolate),
2861                   isolate);
2862     Handle<HeapType> new_field_type =
2863         (new_details.type() == DATA)
2864             ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2865             : HeapType::Constant(
2866                   handle(new_descriptors->GetValue(modify_index), isolate),
2867                   isolate);
2868     old_map->PrintGeneralization(
2869         stdout, "", modify_index, split_nof, old_nof,
2870         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2871         old_details.representation(), new_details.representation(),
2872         *old_field_type, *new_field_type);
2873   }
2874
2875   // Add missing transitions.
2876   Handle<Map> new_map = split_map;
2877   for (int i = split_nof; i < old_nof; ++i) {
2878     new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2879                                      new_layout_descriptor);
2880   }
2881   new_map->set_owns_descriptors(true);
2882   return new_map;
2883 }
2884
2885
2886 // Generalize the representation of all DATA descriptors.
2887 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2888     Handle<Map> map) {
2889   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2890   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2891     PropertyDetails details = descriptors->GetDetails(i);
2892     if (details.type() == DATA) {
2893       map = ReconfigureProperty(map, i, kData, details.attributes(),
2894                                 Representation::Tagged(),
2895                                 HeapType::Any(map->GetIsolate()), FORCE_FIELD);
2896     }
2897   }
2898   return map;
2899 }
2900
2901
2902 // static
2903 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
2904   DisallowHeapAllocation no_allocation;
2905   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2906
2907   if (!old_map->is_deprecated()) return old_map;
2908
2909   // Check the state of the root map.
2910   Map* root_map = old_map->FindRootMap();
2911   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2912
2913   ElementsKind from_kind = root_map->elements_kind();
2914   ElementsKind to_kind = old_map->elements_kind();
2915   if (from_kind != to_kind) {
2916     // Try to follow existing elements kind transitions.
2917     root_map = root_map->LookupElementsTransitionMap(to_kind);
2918     if (root_map == NULL) return MaybeHandle<Map>();
2919     // From here on, use the map with correct elements kind as root map.
2920   }
2921   int root_nof = root_map->NumberOfOwnDescriptors();
2922
2923   int old_nof = old_map->NumberOfOwnDescriptors();
2924   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2925
2926   Map* new_map = root_map;
2927   for (int i = root_nof; i < old_nof; ++i) {
2928     PropertyDetails old_details = old_descriptors->GetDetails(i);
2929     Map* transition = TransitionArray::SearchTransition(
2930         new_map, old_details.kind(), old_descriptors->GetKey(i),
2931         old_details.attributes());
2932     if (transition == NULL) return MaybeHandle<Map>();
2933     new_map = transition;
2934     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2935
2936     PropertyDetails new_details = new_descriptors->GetDetails(i);
2937     DCHECK_EQ(old_details.kind(), new_details.kind());
2938     DCHECK_EQ(old_details.attributes(), new_details.attributes());
2939     if (!old_details.representation().fits_into(new_details.representation())) {
2940       return MaybeHandle<Map>();
2941     }
2942     switch (new_details.type()) {
2943       case DATA: {
2944         HeapType* new_type = new_descriptors->GetFieldType(i);
2945         PropertyType old_property_type = old_details.type();
2946         if (old_property_type == DATA) {
2947           HeapType* old_type = old_descriptors->GetFieldType(i);
2948           if (!old_type->NowIs(new_type)) {
2949             return MaybeHandle<Map>();
2950           }
2951         } else {
2952           DCHECK(old_property_type == DATA_CONSTANT);
2953           Object* old_value = old_descriptors->GetValue(i);
2954           if (!new_type->NowContains(old_value)) {
2955             return MaybeHandle<Map>();
2956           }
2957         }
2958         break;
2959       }
2960       case ACCESSOR: {
2961 #ifdef DEBUG
2962         HeapType* new_type = new_descriptors->GetFieldType(i);
2963         DCHECK(HeapType::Any()->Is(new_type));
2964 #endif
2965         break;
2966       }
2967
2968       case DATA_CONSTANT:
2969       case ACCESSOR_CONSTANT: {
2970         Object* old_value = old_descriptors->GetValue(i);
2971         Object* new_value = new_descriptors->GetValue(i);
2972         if (old_details.location() == kField || old_value != new_value) {
2973           return MaybeHandle<Map>();
2974         }
2975         break;
2976       }
2977     }
2978   }
2979   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2980   return handle(new_map);
2981 }
2982
2983
2984 // static
2985 Handle<Map> Map::Update(Handle<Map> map) {
2986   if (!map->is_deprecated()) return map;
2987   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
2988                              HeapType::None(map->GetIsolate()),
2989                              ALLOW_IN_DESCRIPTOR);
2990 }
2991
2992
2993 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
2994                                                          Handle<Object> value) {
2995   Isolate* isolate = it->isolate();
2996   // Make sure that the top context does not change when doing callbacks or
2997   // interceptor calls.
2998   AssertNoContextChange ncc(isolate);
2999
3000   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
3001   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
3002   if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
3003
3004   Handle<JSObject> holder = it->GetHolder<JSObject>();
3005   v8::Local<v8::Value> result;
3006   PropertyCallbackArguments args(isolate, interceptor->data(),
3007                                  *it->GetReceiver(), *holder);
3008
3009   if (it->IsElement()) {
3010     uint32_t index = it->index();
3011     v8::IndexedPropertySetterCallback setter =
3012         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
3013     LOG(isolate,
3014         ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
3015     result = args.Call(setter, index, v8::Utils::ToLocal(value));
3016   } else {
3017     Handle<Name> name = it->name();
3018
3019     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
3020       return MaybeHandle<Object>();
3021     }
3022
3023     v8::GenericNamedPropertySetterCallback setter =
3024         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3025             interceptor->setter());
3026     LOG(it->isolate(),
3027         ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3028     result =
3029         args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3030   }
3031
3032   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3033   if (result.IsEmpty()) return MaybeHandle<Object>();
3034 #ifdef DEBUG
3035   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3036   result_internal->VerifyApiCallResultType();
3037 #endif
3038   return value;
3039 }
3040
3041
3042 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3043                                         Handle<Name> name, Handle<Object> value,
3044                                         LanguageMode language_mode,
3045                                         StoreFromKeyed store_mode) {
3046   LookupIterator it(object, name);
3047   return SetProperty(&it, value, language_mode, store_mode);
3048 }
3049
3050
3051 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
3052                                                 Handle<Object> value,
3053                                                 LanguageMode language_mode,
3054                                                 StoreFromKeyed store_mode,
3055                                                 bool* found) {
3056   // Make sure that the top context does not change when doing callbacks or
3057   // interceptor calls.
3058   AssertNoContextChange ncc(it->isolate());
3059
3060   *found = true;
3061
3062   bool done = false;
3063   for (; it->IsFound(); it->Next()) {
3064     switch (it->state()) {
3065       case LookupIterator::NOT_FOUND:
3066         UNREACHABLE();
3067
3068       case LookupIterator::ACCESS_CHECK:
3069         if (it->HasAccess()) break;
3070         // Check whether it makes sense to reuse the lookup iterator. Here it
3071         // might still call into setters up the prototype chain.
3072         return JSObject::SetPropertyWithFailedAccessCheck(it, value);
3073
3074       case LookupIterator::JSPROXY:
3075         if (it->HolderIsReceiverOrHiddenPrototype()) {
3076           return JSProxy::SetPropertyWithHandler(
3077               it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value,
3078               language_mode);
3079         } else {
3080           // TODO(verwaest): Use the MaybeHandle to indicate result.
3081           bool has_result = false;
3082           MaybeHandle<Object> maybe_result =
3083               JSProxy::SetPropertyViaPrototypesWithHandler(
3084                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(),
3085                   value, language_mode, &has_result);
3086           if (has_result) return maybe_result;
3087           done = true;
3088         }
3089         break;
3090
3091       case LookupIterator::INTERCEPTOR:
3092         if (it->HolderIsReceiverOrHiddenPrototype()) {
3093           MaybeHandle<Object> maybe_result =
3094               JSObject::SetPropertyWithInterceptor(it, value);
3095           if (!maybe_result.is_null()) return maybe_result;
3096           if (it->isolate()->has_pending_exception()) return maybe_result;
3097         } else {
3098           Maybe<PropertyAttributes> maybe_attributes =
3099               JSObject::GetPropertyAttributesWithInterceptor(it);
3100           if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3101           done = maybe_attributes.FromJust() != ABSENT;
3102           if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3103             return WriteToReadOnlyProperty(it, value, language_mode);
3104           }
3105         }
3106         break;
3107
3108       case LookupIterator::ACCESSOR: {
3109         if (it->IsReadOnly()) {
3110           return WriteToReadOnlyProperty(it, value, language_mode);
3111         }
3112         Handle<Object> accessors = it->GetAccessors();
3113         if (accessors->IsAccessorInfo() &&
3114             !it->HolderIsReceiverOrHiddenPrototype() &&
3115             AccessorInfo::cast(*accessors)->is_special_data_property()) {
3116           done = true;
3117           break;
3118         }
3119         return SetPropertyWithAccessor(it, value, language_mode);
3120       }
3121       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3122         // TODO(verwaest): We should throw an exception.
3123         return value;
3124
3125       case LookupIterator::DATA:
3126         if (it->IsReadOnly()) {
3127           return WriteToReadOnlyProperty(it, value, language_mode);
3128         }
3129         if (it->HolderIsReceiverOrHiddenPrototype()) {
3130           return SetDataProperty(it, value);
3131         }
3132         done = true;
3133         break;
3134
3135       case LookupIterator::TRANSITION:
3136         done = true;
3137         break;
3138     }
3139
3140     if (done) break;
3141   }
3142
3143   // If the receiver is the JSGlobalObject, the store was contextual. In case
3144   // the property did not exist yet on the global object itself, we have to
3145   // throw a reference error in strict mode.
3146   if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
3147     THROW_NEW_ERROR(it->isolate(),
3148                     NewReferenceError(MessageTemplate::kNotDefined, it->name()),
3149                     Object);
3150   }
3151
3152   *found = false;
3153   return MaybeHandle<Object>();
3154 }
3155
3156
3157 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3158                                         Handle<Object> value,
3159                                         LanguageMode language_mode,
3160                                         StoreFromKeyed store_mode) {
3161   bool found = false;
3162   MaybeHandle<Object> result =
3163       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3164   if (found) return result;
3165   return AddDataProperty(it, value, NONE, language_mode, store_mode);
3166 }
3167
3168
3169 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3170                                              Handle<Object> value,
3171                                              LanguageMode language_mode,
3172                                              StoreFromKeyed store_mode) {
3173   bool found = false;
3174   MaybeHandle<Object> result =
3175       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3176   if (found) return result;
3177
3178   if (!it->GetReceiver()->IsJSReceiver()) {
3179     return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3180                                    it->GetName(), value, language_mode);
3181   }
3182
3183   LookupIterator::Configuration c = LookupIterator::OWN;
3184   LookupIterator own_lookup =
3185       it->IsElement()
3186           ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
3187           : LookupIterator(it->GetReceiver(), it->name(), c);
3188
3189   for (; own_lookup.IsFound(); own_lookup.Next()) {
3190     switch (own_lookup.state()) {
3191       case LookupIterator::ACCESS_CHECK:
3192         if (!own_lookup.HasAccess()) {
3193           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value);
3194         }
3195         break;
3196
3197       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3198         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3199                                                value, language_mode);
3200
3201       case LookupIterator::DATA: {
3202         PropertyDetails details = own_lookup.property_details();
3203         if (details.IsConfigurable() || !details.IsReadOnly()) {
3204           return JSObject::DefineOwnPropertyIgnoreAttributes(
3205               &own_lookup, value, details.attributes());
3206         }
3207         return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3208       }
3209
3210       case LookupIterator::ACCESSOR: {
3211         PropertyDetails details = own_lookup.property_details();
3212         if (details.IsConfigurable()) {
3213           return JSObject::DefineOwnPropertyIgnoreAttributes(
3214               &own_lookup, value, details.attributes());
3215         }
3216
3217         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3218                                                value, language_mode);
3219       }
3220
3221       case LookupIterator::INTERCEPTOR:
3222       case LookupIterator::JSPROXY: {
3223         bool found = false;
3224         MaybeHandle<Object> result = SetPropertyInternal(
3225             &own_lookup, value, language_mode, store_mode, &found);
3226         if (found) return result;
3227         break;
3228       }
3229
3230       case LookupIterator::NOT_FOUND:
3231       case LookupIterator::TRANSITION:
3232         UNREACHABLE();
3233     }
3234   }
3235
3236   return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3237                                    store_mode);
3238 }
3239
3240
3241 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it,
3242                                                LanguageMode language_mode) {
3243   if (is_strong(language_mode)) {
3244     THROW_NEW_ERROR(it->isolate(),
3245                     NewTypeError(MessageTemplate::kStrongPropertyAccess,
3246                                  it->GetName(), it->GetReceiver()),
3247                     Object);
3248   }
3249   return it->isolate()->factory()->undefined_value();
3250 }
3251
3252 MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
3253                                                Handle<Object> receiver,
3254                                                Handle<Object> name,
3255                                                LanguageMode language_mode) {
3256   if (is_strong(language_mode)) {
3257     THROW_NEW_ERROR(
3258         isolate,
3259         NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver),
3260         Object);
3261   }
3262   return isolate->factory()->undefined_value();
3263 }
3264
3265
3266 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3267     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3268   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3269                                  it->GetName(), value, language_mode);
3270 }
3271
3272
3273 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3274     Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3275     Handle<Object> value, LanguageMode language_mode) {
3276   if (is_sloppy(language_mode)) return value;
3277   THROW_NEW_ERROR(
3278       isolate,
3279       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, receiver),
3280       Object);
3281 }
3282
3283
3284 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
3285     Isolate* isolate, Handle<Object> name, Handle<Object> value,
3286     LanguageMode language_mode) {
3287   if (is_sloppy(language_mode)) return value;
3288   THROW_NEW_ERROR(isolate,
3289                   NewTypeError(MessageTemplate::kRedefineDisallowed, name),
3290                   Object);
3291 }
3292
3293
3294 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3295                                             Handle<Object> value) {
3296   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3297   // have own properties.
3298   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3299
3300   // Store on the holder which may be hidden behind the receiver.
3301   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3302
3303   // Old value for the observation change record.
3304   // Fetch before transforming the object since the encoding may become
3305   // incompatible with what's cached in |it|.
3306   bool is_observed = receiver->map()->is_observed() &&
3307                      (it->IsElement() ||
3308                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
3309   MaybeHandle<Object> maybe_old;
3310   if (is_observed) maybe_old = it->GetDataValue();
3311
3312   Handle<Object> to_assign = value;
3313   // Convert the incoming value to a number for storing into typed arrays.
3314   if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
3315     if (!value->IsNumber() && !value->IsUndefined()) {
3316       ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
3317                                  Execution::ToNumber(it->isolate(), value),
3318                                  Object);
3319       // ToNumber above might modify the receiver, causing the cached
3320       // holder_map to mismatch the actual holder->map() after this point.
3321       // Reload the map to be in consistent state. Other cached state cannot
3322       // have been invalidated since typed array elements cannot be reconfigured
3323       // in any way.
3324       it->ReloadHolderMap();
3325     }
3326   }
3327
3328   // Possibly migrate to the most up-to-date map that will be able to store
3329   // |value| under it->name().
3330   it->PrepareForDataProperty(to_assign);
3331
3332   // Write the property value.
3333   it->WriteDataValue(to_assign);
3334
3335   // Send the change record if there are observers.
3336   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3337     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3338                                            receiver, "update", it->GetName(),
3339                                            maybe_old.ToHandleChecked()),
3340                         Object);
3341   }
3342
3343   return value;
3344 }
3345
3346
3347 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
3348     Handle<JSArray> object) {
3349   Isolate* isolate = object->GetIsolate();
3350   HandleScope scope(isolate);
3351   Handle<Object> args[] = {object};
3352
3353   return Execution::Call(
3354       isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
3355       isolate->factory()->undefined_value(), arraysize(args), args);
3356 }
3357
3358
3359 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
3360     Handle<JSArray> object) {
3361   Isolate* isolate = object->GetIsolate();
3362   HandleScope scope(isolate);
3363   Handle<Object> args[] = {object};
3364
3365   return Execution::Call(
3366       isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
3367       isolate->factory()->undefined_value(), arraysize(args), args);
3368 }
3369
3370
3371 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
3372     Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
3373     uint32_t add_count) {
3374   Isolate* isolate = object->GetIsolate();
3375   HandleScope scope(isolate);
3376   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
3377   Handle<Object> add_count_object =
3378       isolate->factory()->NewNumberFromUint(add_count);
3379
3380   Handle<Object> args[] = {object, index_object, deleted, add_count_object};
3381
3382   return Execution::Call(
3383       isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
3384       isolate->factory()->undefined_value(), arraysize(args), args);
3385 }
3386
3387
3388 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3389                                             Handle<Object> value,
3390                                             PropertyAttributes attributes,
3391                                             LanguageMode language_mode,
3392                                             StoreFromKeyed store_mode) {
3393   DCHECK(!it->GetReceiver()->IsJSProxy());
3394   if (!it->GetReceiver()->IsJSObject()) {
3395     // TODO(verwaest): Throw a TypeError with a more specific message.
3396     return WriteToReadOnlyProperty(it, value, language_mode);
3397   }
3398
3399   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
3400
3401   Handle<JSObject> receiver = it->GetStoreTarget();
3402
3403   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3404   // instead. If the prototype is Null, the proxy is detached.
3405   if (receiver->IsJSGlobalProxy()) return value;
3406
3407   Isolate* isolate = it->isolate();
3408
3409   if (!receiver->map()->is_extensible() &&
3410       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
3411     if (is_sloppy(language_mode)) return value;
3412     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible,
3413                                           it->GetName()),
3414                     Object);
3415   }
3416
3417   if (it->IsElement()) {
3418     if (receiver->IsJSArray()) {
3419       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
3420       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
3421         if (is_sloppy(language_mode)) return value;
3422         return JSArray::ReadOnlyLengthError(array);
3423       }
3424
3425       if (FLAG_trace_external_array_abuse &&
3426           array->HasFixedTypedArrayElements()) {
3427         CheckArrayAbuse(array, "typed elements write", it->index(), true);
3428       }
3429
3430       if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
3431         CheckArrayAbuse(array, "elements write", it->index(), false);
3432       }
3433     }
3434
3435     MaybeHandle<Object> result =
3436         JSObject::AddDataElement(receiver, it->index(), value, attributes);
3437     JSObject::ValidateElements(receiver);
3438     return result;
3439   } else {
3440     // Migrate to the most up-to-date map that will be able to store |value|
3441     // under it->name() with |attributes|.
3442     it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3443     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3444     it->ApplyTransitionToDataProperty();
3445
3446     // TODO(verwaest): Encapsulate dictionary handling better.
3447     if (receiver->map()->is_dictionary_map()) {
3448       // TODO(verwaest): Probably should ensure this is done beforehand.
3449       it->InternalizeName();
3450       // TODO(dcarney): just populate TransitionPropertyCell here?
3451       JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3452     } else {
3453       // Write the property value.
3454       it->WriteDataValue(value);
3455     }
3456
3457     // Send the change record if there are observers.
3458     if (receiver->map()->is_observed() &&
3459         !isolate->IsInternallyUsedPropertyName(it->name())) {
3460       RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
3461                                        receiver, "add", it->name(),
3462                                        it->factory()->the_hole_value()),
3463                           Object);
3464     }
3465   }
3466
3467   return value;
3468 }
3469
3470
3471 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3472   // Only supports adding slack to owned descriptors.
3473   DCHECK(map->owns_descriptors());
3474
3475   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3476   int old_size = map->NumberOfOwnDescriptors();
3477   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3478
3479   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3480       descriptors, old_size, slack);
3481
3482   DisallowHeapAllocation no_allocation;
3483   // The descriptors are still the same, so keep the layout descriptor.
3484   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
3485
3486   if (old_size == 0) {
3487     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3488     return;
3489   }
3490
3491   // If the source descriptors had an enum cache we copy it. This ensures
3492   // that the maps to which we push the new descriptor array back can rely
3493   // on a cache always being available once it is set. If the map has more
3494   // enumerated descriptors than available in the original cache, the cache
3495   // will be lazily replaced by the extended cache when needed.
3496   if (descriptors->HasEnumCache()) {
3497     new_descriptors->CopyEnumCacheFrom(*descriptors);
3498   }
3499
3500   // Replace descriptors by new_descriptors in all maps that share it.
3501   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3502
3503   Map* walk_map;
3504   for (Object* current = map->GetBackPointer();
3505        !current->IsUndefined();
3506        current = walk_map->GetBackPointer()) {
3507     walk_map = Map::cast(current);
3508     if (walk_map->instance_descriptors() != *descriptors) break;
3509     walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3510   }
3511
3512   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3513 }
3514
3515
3516 template<class T>
3517 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3518                                  Handle<typename T::Array> array,
3519                                  int valid_descriptors) {
3520   int nof_callbacks = callbacks->length();
3521
3522   Isolate* isolate = array->GetIsolate();
3523   // Ensure the keys are unique names before writing them into the
3524   // instance descriptor. Since it may cause a GC, it has to be done before we
3525   // temporarily put the heap in an invalid state while appending descriptors.
3526   for (int i = 0; i < nof_callbacks; ++i) {
3527     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3528     if (entry->name()->IsUniqueName()) continue;
3529     Handle<String> key =
3530         isolate->factory()->InternalizeString(
3531             Handle<String>(String::cast(entry->name())));
3532     entry->set_name(*key);
3533   }
3534
3535   // Fill in new callback descriptors.  Process the callbacks from
3536   // back to front so that the last callback with a given name takes
3537   // precedence over previously added callbacks with that name.
3538   for (int i = nof_callbacks - 1; i >= 0; i--) {
3539     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3540     Handle<Name> key(Name::cast(entry->name()));
3541     // Check if a descriptor with this name already exists before writing.
3542     if (!T::Contains(key, entry, valid_descriptors, array)) {
3543       T::Insert(key, entry, valid_descriptors, array);
3544       valid_descriptors++;
3545     }
3546   }
3547
3548   return valid_descriptors;
3549 }
3550
3551 struct DescriptorArrayAppender {
3552   typedef DescriptorArray Array;
3553   static bool Contains(Handle<Name> key,
3554                        Handle<AccessorInfo> entry,
3555                        int valid_descriptors,
3556                        Handle<DescriptorArray> array) {
3557     DisallowHeapAllocation no_gc;
3558     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3559   }
3560   static void Insert(Handle<Name> key,
3561                      Handle<AccessorInfo> entry,
3562                      int valid_descriptors,
3563                      Handle<DescriptorArray> array) {
3564     DisallowHeapAllocation no_gc;
3565     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
3566     array->Append(&desc);
3567   }
3568 };
3569
3570
3571 struct FixedArrayAppender {
3572   typedef FixedArray Array;
3573   static bool Contains(Handle<Name> key,
3574                        Handle<AccessorInfo> entry,
3575                        int valid_descriptors,
3576                        Handle<FixedArray> array) {
3577     for (int i = 0; i < valid_descriptors; i++) {
3578       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3579     }
3580     return false;
3581   }
3582   static void Insert(Handle<Name> key,
3583                      Handle<AccessorInfo> entry,
3584                      int valid_descriptors,
3585                      Handle<FixedArray> array) {
3586     DisallowHeapAllocation no_gc;
3587     array->set(valid_descriptors, *entry);
3588   }
3589 };
3590
3591
3592 void Map::AppendCallbackDescriptors(Handle<Map> map,
3593                                     Handle<Object> descriptors) {
3594   int nof = map->NumberOfOwnDescriptors();
3595   Handle<DescriptorArray> array(map->instance_descriptors());
3596   NeanderArray callbacks(descriptors);
3597   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3598   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3599   map->SetNumberOfOwnDescriptors(nof);
3600 }
3601
3602
3603 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3604                                Handle<FixedArray> array,
3605                                int valid_descriptors) {
3606   NeanderArray callbacks(descriptors);
3607   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3608   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3609                                                    array,
3610                                                    valid_descriptors);
3611 }
3612
3613
3614 static bool ContainsMap(MapHandleList* maps, Map* map) {
3615   DCHECK_NOT_NULL(map);
3616   for (int i = 0; i < maps->length(); ++i) {
3617     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
3618   }
3619   return false;
3620 }
3621
3622
3623 Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
3624                                      MapHandleList* candidates) {
3625   ElementsKind kind = map->elements_kind();
3626   bool packed = IsFastPackedElementsKind(kind);
3627
3628   Map* transition = nullptr;
3629   if (IsTransitionableFastElementsKind(kind)) {
3630     for (Map* current = map->ElementsTransitionMap();
3631          current != nullptr && current->has_fast_elements();
3632          current = current->ElementsTransitionMap()) {
3633       if (ContainsMap(candidates, current) &&
3634           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
3635         transition = current;
3636         packed = packed && IsFastPackedElementsKind(current->elements_kind());
3637       }
3638     }
3639   }
3640   return transition == nullptr ? Handle<Map>() : handle(transition);
3641 }
3642
3643
3644 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3645   Map* current_map = map;
3646
3647   ElementsKind kind = map->elements_kind();
3648   while (kind != to_kind) {
3649     Map* next_map = current_map->ElementsTransitionMap();
3650     if (next_map == nullptr) return current_map;
3651     kind = next_map->elements_kind();
3652     current_map = next_map;
3653   }
3654
3655   DCHECK_EQ(to_kind, current_map->elements_kind());
3656   return current_map;
3657 }
3658
3659
3660 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3661   Map* to_map = FindClosestElementsTransition(this, to_kind);
3662   if (to_map->elements_kind() == to_kind) return to_map;
3663   return nullptr;
3664 }
3665
3666
3667 bool Map::IsMapInArrayPrototypeChain() {
3668   Isolate* isolate = GetIsolate();
3669   if (isolate->initial_array_prototype()->map() == this) {
3670     return true;
3671   }
3672
3673   if (isolate->initial_object_prototype()->map() == this) {
3674     return true;
3675   }
3676
3677   return false;
3678 }
3679
3680
3681 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
3682   Isolate* isolate = map->GetIsolate();
3683   if (map->weak_cell_cache()->IsWeakCell()) {
3684     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
3685   }
3686   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
3687   map->set_weak_cell_cache(*weak_cell);
3688   return weak_cell;
3689 }
3690
3691
3692 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3693                                                  ElementsKind to_kind) {
3694   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3695
3696   Handle<Map> current_map = map;
3697
3698   ElementsKind kind = map->elements_kind();
3699   TransitionFlag flag;
3700   if (map->is_prototype_map()) {
3701     flag = OMIT_TRANSITION;
3702   } else {
3703     flag = INSERT_TRANSITION;
3704     if (IsFastElementsKind(kind)) {
3705       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3706         kind = GetNextTransitionElementsKind(kind);
3707         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
3708       }
3709     }
3710   }
3711
3712   // In case we are exiting the fast elements kind system, just add the map in
3713   // the end.
3714   if (kind != to_kind) {
3715     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
3716   }
3717
3718   DCHECK(current_map->elements_kind() == to_kind);
3719   return current_map;
3720 }
3721
3722
3723 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3724                                       ElementsKind to_kind) {
3725   ElementsKind from_kind = map->elements_kind();
3726   if (from_kind == to_kind) return map;
3727
3728   Isolate* isolate = map->GetIsolate();
3729   Context* native_context = isolate->context()->native_context();
3730   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
3731     if (*map == native_context->fast_aliased_arguments_map()) {
3732       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3733       return handle(native_context->slow_aliased_arguments_map());
3734     }
3735   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
3736     if (*map == native_context->slow_aliased_arguments_map()) {
3737       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3738       return handle(native_context->fast_aliased_arguments_map());
3739     }
3740   } else {
3741     Object* maybe_array_maps = map->is_strong()
3742                                    ? native_context->js_array_strong_maps()
3743                                    : native_context->js_array_maps();
3744     if (maybe_array_maps->IsFixedArray()) {
3745       DisallowHeapAllocation no_gc;
3746       FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3747       if (array_maps->get(from_kind) == *map) {
3748         Object* maybe_transitioned_map = array_maps->get(to_kind);
3749         if (maybe_transitioned_map->IsMap()) {
3750           return handle(Map::cast(maybe_transitioned_map));
3751         }
3752       }
3753     }
3754   }
3755
3756   DCHECK(!map->IsUndefined());
3757   bool allow_store_transition = IsTransitionElementsKind(from_kind);
3758   // Only store fast element maps in ascending generality.
3759   if (IsFastElementsKind(to_kind)) {
3760     allow_store_transition =
3761         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
3762         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3763   }
3764
3765   if (!allow_store_transition) {
3766     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3767   }
3768
3769   return Map::AsElementsKind(map, to_kind);
3770 }
3771
3772
3773 // static
3774 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3775   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3776
3777   if (closest_map->elements_kind() == kind) {
3778     return closest_map;
3779   }
3780
3781   return AddMissingElementsTransitions(closest_map, kind);
3782 }
3783
3784
3785 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3786                                                ElementsKind to_kind) {
3787   Handle<Map> map(object->map());
3788   return Map::TransitionElementsTo(map, to_kind);
3789 }
3790
3791
3792 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3793                                             Handle<Name> name) {
3794   Isolate* isolate = proxy->GetIsolate();
3795
3796   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3797   if (name->IsSymbol()) return Just(false);
3798
3799   Handle<Object> args[] = { name };
3800   Handle<Object> result;
3801   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3802       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3803                                 arraysize(args), args),
3804       Nothing<bool>());
3805
3806   return Just(result->BooleanValue());
3807 }
3808
3809
3810 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3811     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3812     Handle<Object> value, LanguageMode language_mode) {
3813   Isolate* isolate = proxy->GetIsolate();
3814
3815   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3816   if (name->IsSymbol()) return value;
3817
3818   Handle<Object> args[] = { receiver, name, value };
3819   RETURN_ON_EXCEPTION(
3820       isolate,
3821       CallTrap(proxy,
3822                "set",
3823                isolate->derived_set_trap(),
3824                arraysize(args),
3825                args),
3826       Object);
3827
3828   return value;
3829 }
3830
3831
3832 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3833     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3834     Handle<Object> value, LanguageMode language_mode, bool* done) {
3835   Isolate* isolate = proxy->GetIsolate();
3836   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3837
3838   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3839   if (name->IsSymbol()) {
3840     *done = false;
3841     return isolate->factory()->the_hole_value();
3842   }
3843
3844   *done = true;  // except where redefined...
3845   Handle<Object> args[] = { name };
3846   Handle<Object> result;
3847   ASSIGN_RETURN_ON_EXCEPTION(
3848       isolate, result,
3849       CallTrap(proxy,
3850                "getPropertyDescriptor",
3851                Handle<Object>(),
3852                arraysize(args),
3853                args),
3854       Object);
3855
3856   if (result->IsUndefined()) {
3857     *done = false;
3858     return isolate->factory()->the_hole_value();
3859   }
3860
3861   // Emulate [[GetProperty]] semantics for proxies.
3862   Handle<Object> argv[] = { result };
3863   Handle<Object> desc;
3864   ASSIGN_RETURN_ON_EXCEPTION(
3865       isolate, desc,
3866       Execution::Call(isolate,
3867                       isolate->to_complete_property_descriptor(),
3868                       result,
3869                       arraysize(argv),
3870                       argv),
3871       Object);
3872
3873   // [[GetProperty]] requires to check that all properties are configurable.
3874   Handle<String> configurable_name =
3875       isolate->factory()->InternalizeOneByteString(
3876           STATIC_CHAR_VECTOR("configurable_"));
3877   Handle<Object> configurable =
3878       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3879   DCHECK(configurable->IsBoolean());
3880   if (configurable->IsFalse()) {
3881     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3882         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3883     THROW_NEW_ERROR(isolate,
3884                     NewTypeError(MessageTemplate::kProxyPropNotConfigurable,
3885                                  handler, name, trap),
3886                     Object);
3887   }
3888   DCHECK(configurable->IsTrue());
3889
3890   // Check for DataDescriptor.
3891   Handle<String> hasWritable_name =
3892       isolate->factory()->InternalizeOneByteString(
3893           STATIC_CHAR_VECTOR("hasWritable_"));
3894   Handle<Object> hasWritable =
3895       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3896   DCHECK(hasWritable->IsBoolean());
3897   if (hasWritable->IsTrue()) {
3898     Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3899         STATIC_CHAR_VECTOR("writable_"));
3900     Handle<Object> writable =
3901         Object::GetProperty(desc, writable_name).ToHandleChecked();
3902     DCHECK(writable->IsBoolean());
3903     *done = writable->IsFalse();
3904     if (!*done) return isolate->factory()->the_hole_value();
3905     return WriteToReadOnlyProperty(isolate, receiver, name, value,
3906                                    language_mode);
3907   }
3908
3909   // We have an AccessorDescriptor.
3910   Handle<String> set_name =
3911       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3912   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3913   if (!setter->IsUndefined()) {
3914     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3915     return SetPropertyWithDefinedSetter(
3916         receiver, Handle<JSReceiver>::cast(setter), value);
3917   }
3918
3919   if (is_sloppy(language_mode)) return value;
3920   THROW_NEW_ERROR(
3921       isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy),
3922       Object);
3923 }
3924
3925
3926 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3927     Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) {
3928   Isolate* isolate = proxy->GetIsolate();
3929
3930   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3931   if (name->IsSymbol()) return isolate->factory()->false_value();
3932
3933   Handle<Object> args[] = { name };
3934   Handle<Object> result;
3935   ASSIGN_RETURN_ON_EXCEPTION(
3936       isolate, result,
3937       CallTrap(proxy,
3938                "delete",
3939                Handle<Object>(),
3940                arraysize(args),
3941                args),
3942       Object);
3943
3944   bool result_bool = result->BooleanValue();
3945   if (is_strict(language_mode) && !result_bool) {
3946     Handle<Object> handler(proxy->handler(), isolate);
3947     THROW_NEW_ERROR(
3948         isolate,
3949         NewTypeError(MessageTemplate::kProxyHandlerDeleteFailed, handler),
3950         Object);
3951   }
3952   return isolate->factory()->ToBoolean(result_bool);
3953 }
3954
3955
3956 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3957     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3958   Isolate* isolate = proxy->GetIsolate();
3959   HandleScope scope(isolate);
3960
3961   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3962   if (name->IsSymbol()) return Just(ABSENT);
3963
3964   Handle<Object> args[] = { name };
3965   Handle<Object> result;
3966   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3967       isolate, result, proxy->CallTrap(proxy, "getPropertyDescriptor",
3968                                        Handle<Object>(), arraysize(args), args),
3969       Nothing<PropertyAttributes>());
3970
3971   if (result->IsUndefined()) return Just(ABSENT);
3972
3973   Handle<Object> argv[] = { result };
3974   Handle<Object> desc;
3975   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3976       isolate, desc,
3977       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3978                       result, arraysize(argv), argv),
3979       Nothing<PropertyAttributes>());
3980
3981   // Convert result to PropertyAttributes.
3982   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3983       STATIC_CHAR_VECTOR("enumerable_"));
3984   Handle<Object> enumerable;
3985   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3986                                    Object::GetProperty(desc, enum_n),
3987                                    Nothing<PropertyAttributes>());
3988   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3989       STATIC_CHAR_VECTOR("configurable_"));
3990   Handle<Object> configurable;
3991   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3992                                    Object::GetProperty(desc, conf_n),
3993                                    Nothing<PropertyAttributes>());
3994   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3995       STATIC_CHAR_VECTOR("writable_"));
3996   Handle<Object> writable;
3997   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3998                                    Object::GetProperty(desc, writ_n),
3999                                    Nothing<PropertyAttributes>());
4000   if (!writable->BooleanValue()) {
4001     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
4002         STATIC_CHAR_VECTOR("set_"));
4003     Handle<Object> setter;
4004     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
4005                                      Object::GetProperty(desc, set_n),
4006                                      Nothing<PropertyAttributes>());
4007     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
4008   }
4009
4010   if (configurable->IsFalse()) {
4011     Handle<Object> handler(proxy->handler(), isolate);
4012     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
4013         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
4014     Handle<Object> error = isolate->factory()->NewTypeError(
4015         MessageTemplate::kProxyPropNotConfigurable, handler, name, trap);
4016     isolate->Throw(*error);
4017     return Nothing<PropertyAttributes>();
4018   }
4019
4020   int attributes = NONE;
4021   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
4022   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
4023   if (!writable->BooleanValue()) attributes |= READ_ONLY;
4024   return Just(static_cast<PropertyAttributes>(attributes));
4025 }
4026
4027
4028 void JSProxy::Fix(Handle<JSProxy> proxy) {
4029   Isolate* isolate = proxy->GetIsolate();
4030
4031   // Save identity hash.
4032   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4033
4034   if (proxy->IsJSFunctionProxy()) {
4035     isolate->factory()->BecomeJSFunction(proxy);
4036     // Code will be set on the JavaScript side.
4037   } else {
4038     isolate->factory()->BecomeJSObject(proxy);
4039   }
4040   DCHECK(proxy->IsJSObject());
4041
4042   // Inherit identity, if it was present.
4043   if (hash->IsSmi()) {
4044     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
4045                               Handle<Smi>::cast(hash));
4046   }
4047 }
4048
4049
4050 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
4051                                       const char* name,
4052                                       Handle<Object> derived,
4053                                       int argc,
4054                                       Handle<Object> argv[]) {
4055   Isolate* isolate = proxy->GetIsolate();
4056   Handle<Object> handler(proxy->handler(), isolate);
4057
4058   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
4059   Handle<Object> trap;
4060   ASSIGN_RETURN_ON_EXCEPTION(
4061       isolate, trap,
4062       Object::GetPropertyOrElement(handler, trap_name),
4063       Object);
4064
4065   if (trap->IsUndefined()) {
4066     if (derived.is_null()) {
4067       THROW_NEW_ERROR(isolate,
4068                       NewTypeError(MessageTemplate::kProxyHandlerTrapMissing,
4069                                    handler, trap_name),
4070                       Object);
4071     }
4072     trap = Handle<Object>(derived);
4073   }
4074
4075   return Execution::Call(isolate, trap, handler, argc, argv);
4076 }
4077
4078
4079 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
4080   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
4081   ElementsKind obj_kind = object->map()->elements_kind();
4082   ElementsKind map_kind = map->elements_kind();
4083   if (map_kind != obj_kind) {
4084     ElementsKind to_kind = map_kind;
4085     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
4086         IsDictionaryElementsKind(obj_kind)) {
4087       to_kind = obj_kind;
4088     }
4089     if (IsDictionaryElementsKind(to_kind)) {
4090       NormalizeElements(object);
4091     } else {
4092       TransitionElementsKind(object, to_kind);
4093     }
4094     map = Map::AsElementsKind(map, to_kind);
4095   }
4096   JSObject::MigrateToMap(object, map);
4097 }
4098
4099
4100 void JSObject::MigrateInstance(Handle<JSObject> object) {
4101   Handle<Map> original_map(object->map());
4102   Handle<Map> map = Map::Update(original_map);
4103   map->set_migration_target(true);
4104   MigrateToMap(object, map);
4105   if (FLAG_trace_migration) {
4106     object->PrintInstanceMigration(stdout, *original_map, *map);
4107   }
4108 }
4109
4110
4111 // static
4112 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
4113   Isolate* isolate = object->GetIsolate();
4114   DisallowDeoptimization no_deoptimization(isolate);
4115   Handle<Map> original_map(object->map(), isolate);
4116   Handle<Map> new_map;
4117   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
4118     return false;
4119   }
4120   JSObject::MigrateToMap(object, new_map);
4121   if (FLAG_trace_migration) {
4122     object->PrintInstanceMigration(stdout, *original_map, object->map());
4123   }
4124   return true;
4125 }
4126
4127
4128 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4129                            Handle<Object> value,
4130                            PropertyAttributes attributes) {
4131   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4132   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
4133 #ifdef DEBUG
4134   uint32_t index;
4135   DCHECK(!object->IsJSProxy());
4136   DCHECK(!name->AsArrayIndex(&index));
4137   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4138   DCHECK(maybe.IsJust());
4139   DCHECK(!it.IsFound());
4140   DCHECK(object->map()->is_extensible() ||
4141          it.isolate()->IsInternallyUsedPropertyName(name));
4142 #endif
4143   AddDataProperty(&it, value, attributes, STRICT,
4144                   CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4145 }
4146
4147
4148 // static
4149 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
4150   Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr);
4151   info->set_setter(*object);
4152 }
4153
4154
4155 // Reconfigures a property to a data property with attributes, even if it is not
4156 // reconfigurable.
4157 // Requires a LookupIterator that does not look at the prototype chain beyond
4158 // hidden prototypes.
4159 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
4160     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
4161     ExecutableAccessorInfoHandling handling) {
4162   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
4163   bool is_observed = object->map()->is_observed() &&
4164                      (it->IsElement() ||
4165                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4166
4167   for (; it->IsFound(); it->Next()) {
4168     switch (it->state()) {
4169       case LookupIterator::JSPROXY:
4170       case LookupIterator::NOT_FOUND:
4171       case LookupIterator::TRANSITION:
4172         UNREACHABLE();
4173
4174       case LookupIterator::ACCESS_CHECK:
4175         if (!it->HasAccess()) {
4176           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
4177           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
4178           return value;
4179         }
4180         break;
4181
4182       // If there's an interceptor, try to store the property with the
4183       // interceptor.
4184       // In case of success, the attributes will have been reset to the default
4185       // attributes of the interceptor, rather than the incoming attributes.
4186       //
4187       // TODO(verwaest): JSProxy afterwards verify the attributes that the
4188       // JSProxy claims it has, and verifies that they are compatible. If not,
4189       // they throw. Here we should do the same.
4190       case LookupIterator::INTERCEPTOR:
4191         if (handling == DONT_FORCE_FIELD) {
4192           MaybeHandle<Object> maybe_result =
4193               JSObject::SetPropertyWithInterceptor(it, value);
4194           if (!maybe_result.is_null()) return maybe_result;
4195           if (it->isolate()->has_pending_exception()) return maybe_result;
4196         }
4197         break;
4198
4199       case LookupIterator::ACCESSOR: {
4200         Handle<Object> accessors = it->GetAccessors();
4201
4202         // Special handling for ExecutableAccessorInfo, which behaves like a
4203         // data property.
4204         if (accessors->IsExecutableAccessorInfo() &&
4205             handling == DONT_FORCE_FIELD) {
4206           PropertyDetails details = it->property_details();
4207           // Ensure the context isn't changed after calling into accessors.
4208           AssertNoContextChange ncc(it->isolate());
4209
4210           Handle<Object> result;
4211           ASSIGN_RETURN_ON_EXCEPTION(
4212               it->isolate(), result,
4213               JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4214           DCHECK(result->SameValue(*value));
4215
4216           if (details.attributes() == attributes) return value;
4217
4218           // Reconfigure the accessor if attributes mismatch.
4219           Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4220               it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4221           new_data->set_property_attributes(attributes);
4222           // By clearing the setter we don't have to introduce a lookup to
4223           // the setter, simply make it unavailable to reflect the
4224           // attributes.
4225           if (attributes & READ_ONLY) {
4226             ExecutableAccessorInfo::ClearSetter(new_data);
4227           }
4228
4229           it->TransitionToAccessorPair(new_data, attributes);
4230         } else {
4231           it->ReconfigureDataProperty(value, attributes);
4232           it->WriteDataValue(value);
4233         }
4234
4235         if (is_observed) {
4236           RETURN_ON_EXCEPTION(
4237               it->isolate(),
4238               EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4239                                   it->factory()->the_hole_value()),
4240               Object);
4241         }
4242
4243         return value;
4244       }
4245       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4246         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4247                                                value, STRICT);
4248
4249       case LookupIterator::DATA: {
4250         PropertyDetails details = it->property_details();
4251         Handle<Object> old_value = it->factory()->the_hole_value();
4252         // Regular property update if the attributes match.
4253         if (details.attributes() == attributes) {
4254           return SetDataProperty(it, value);
4255         }
4256
4257         // Special case: properties of typed arrays cannot be reconfigured to
4258         // non-writable nor to non-enumerable.
4259         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
4260           return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4261                                                  value, STRICT);
4262         }
4263
4264         // Reconfigure the data property if the attributes mismatch.
4265         if (is_observed) old_value = it->GetDataValue();
4266
4267         it->ReconfigureDataProperty(value, attributes);
4268         it->WriteDataValue(value);
4269
4270         if (is_observed) {
4271           if (old_value->SameValue(*value)) {
4272             old_value = it->factory()->the_hole_value();
4273           }
4274           RETURN_ON_EXCEPTION(it->isolate(),
4275                               EnqueueChangeRecord(object, "reconfigure",
4276                                                   it->GetName(), old_value),
4277                               Object);
4278         }
4279         return value;
4280       }
4281     }
4282   }
4283
4284   return AddDataProperty(it, value, attributes, STRICT,
4285                          CERTAINLY_NOT_STORE_FROM_KEYED);
4286 }
4287
4288
4289 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4290     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4291     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4292   DCHECK(!value->IsTheHole());
4293   LookupIterator it(object, name, LookupIterator::OWN);
4294   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4295 }
4296
4297
4298 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
4299     Handle<JSObject> object, uint32_t index, Handle<Object> value,
4300     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4301   Isolate* isolate = object->GetIsolate();
4302   LookupIterator it(isolate, object, index, LookupIterator::OWN);
4303   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4304 }
4305
4306
4307 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
4308     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4309     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4310   Isolate* isolate = object->GetIsolate();
4311   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
4312                                                         LookupIterator::OWN);
4313   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4314 }
4315
4316
4317 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
4318                                          Handle<Object> value) {
4319   DCHECK(it->GetReceiver()->IsJSObject());
4320   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it);
4321   if (maybe.IsNothing()) return Nothing<bool>();
4322
4323   if (it->IsFound()) {
4324     if (!it->IsConfigurable()) return Just(false);
4325   } else {
4326     if (!JSObject::cast(*it->GetReceiver())->IsExtensible()) return Just(false);
4327   }
4328
4329   RETURN_ON_EXCEPTION_VALUE(
4330       it->isolate(),
4331       DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD),
4332       Nothing<bool>());
4333
4334   return Just(true);
4335 }
4336
4337
4338 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4339     LookupIterator* it) {
4340   Isolate* isolate = it->isolate();
4341   // Make sure that the top context does not change when doing
4342   // callbacks or interceptor calls.
4343   AssertNoContextChange ncc(isolate);
4344   HandleScope scope(isolate);
4345
4346   Handle<JSObject> holder = it->GetHolder<JSObject>();
4347   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
4348   if (!it->IsElement() && it->name()->IsSymbol() &&
4349       !interceptor->can_intercept_symbols()) {
4350     return Just(ABSENT);
4351   }
4352   PropertyCallbackArguments args(isolate, interceptor->data(),
4353                                  *it->GetReceiver(), *holder);
4354   if (!interceptor->query()->IsUndefined()) {
4355     v8::Local<v8::Integer> result;
4356     if (it->IsElement()) {
4357       uint32_t index = it->index();
4358       v8::IndexedPropertyQueryCallback query =
4359           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4360       LOG(isolate,
4361           ApiIndexedPropertyAccess("interceptor-indexed-has", *holder, index));
4362       result = args.Call(query, index);
4363     } else {
4364       Handle<Name> name = it->name();
4365       v8::GenericNamedPropertyQueryCallback query =
4366           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
4367               interceptor->query());
4368       LOG(isolate,
4369           ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4370       result = args.Call(query, v8::Utils::ToLocal(name));
4371     }
4372     if (!result.IsEmpty()) {
4373       DCHECK(result->IsInt32());
4374       return Just(static_cast<PropertyAttributes>(
4375           result->Int32Value(reinterpret_cast<v8::Isolate*>(isolate)
4376                                  ->GetCurrentContext()).FromJust()));
4377     }
4378   } else if (!interceptor->getter()->IsUndefined()) {
4379     // TODO(verwaest): Use GetPropertyWithInterceptor?
4380     v8::Local<v8::Value> result;
4381     if (it->IsElement()) {
4382       uint32_t index = it->index();
4383       v8::IndexedPropertyGetterCallback getter =
4384           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4385       LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-get-has",
4386                                             *holder, index));
4387       result = args.Call(getter, index);
4388     } else {
4389       Handle<Name> name = it->name();
4390
4391       v8::GenericNamedPropertyGetterCallback getter =
4392           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
4393               interceptor->getter());
4394       LOG(isolate,
4395           ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4396       result = args.Call(getter, v8::Utils::ToLocal(name));
4397     }
4398     if (!result.IsEmpty()) return Just(DONT_ENUM);
4399   }
4400
4401   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
4402   return Just(ABSENT);
4403 }
4404
4405
4406 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4407     LookupIterator* it) {
4408   for (; it->IsFound(); it->Next()) {
4409     switch (it->state()) {
4410       case LookupIterator::NOT_FOUND:
4411       case LookupIterator::TRANSITION:
4412         UNREACHABLE();
4413       case LookupIterator::JSPROXY:
4414         return JSProxy::GetPropertyAttributesWithHandler(
4415             it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
4416       case LookupIterator::INTERCEPTOR: {
4417         Maybe<PropertyAttributes> result =
4418             JSObject::GetPropertyAttributesWithInterceptor(it);
4419         if (!result.IsJust()) return result;
4420         if (result.FromJust() != ABSENT) return result;
4421         break;
4422       }
4423       case LookupIterator::ACCESS_CHECK:
4424         if (it->HasAccess()) break;
4425         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4426       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4427         return Just(ABSENT);
4428       case LookupIterator::ACCESSOR:
4429       case LookupIterator::DATA:
4430         return Just(it->property_details().attributes());
4431     }
4432   }
4433   return Just(ABSENT);
4434 }
4435
4436
4437 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4438   Handle<FixedArray> array(
4439       isolate->factory()->NewFixedArray(kEntries, TENURED));
4440   return Handle<NormalizedMapCache>::cast(array);
4441 }
4442
4443
4444 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4445                                          PropertyNormalizationMode mode) {
4446   DisallowHeapAllocation no_gc;
4447   Object* value = FixedArray::get(GetIndex(fast_map));
4448   if (!value->IsMap() ||
4449       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4450     return MaybeHandle<Map>();
4451   }
4452   return handle(Map::cast(value));
4453 }
4454
4455
4456 void NormalizedMapCache::Set(Handle<Map> fast_map,
4457                              Handle<Map> normalized_map) {
4458   DisallowHeapAllocation no_gc;
4459   DCHECK(normalized_map->is_dictionary_map());
4460   FixedArray::set(GetIndex(fast_map), *normalized_map);
4461 }
4462
4463
4464 void NormalizedMapCache::Clear() {
4465   int entries = length();
4466   for (int i = 0; i != entries; i++) {
4467     set_undefined(i);
4468   }
4469 }
4470
4471
4472 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4473                                     Handle<Name> name,
4474                                     Handle<Code> code) {
4475   Handle<Map> map(object->map());
4476   Map::UpdateCodeCache(map, name, code);
4477 }
4478
4479
4480 void JSObject::NormalizeProperties(Handle<JSObject> object,
4481                                    PropertyNormalizationMode mode,
4482                                    int expected_additional_properties,
4483                                    const char* reason) {
4484   if (!object->HasFastProperties()) return;
4485
4486   Handle<Map> map(object->map());
4487   Handle<Map> new_map = Map::Normalize(map, mode, reason);
4488
4489   MigrateToMap(object, new_map, expected_additional_properties);
4490 }
4491
4492
4493 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4494                                  Handle<Map> new_map,
4495                                  int expected_additional_properties) {
4496   // The global object is always normalized.
4497   DCHECK(!object->IsGlobalObject());
4498   // JSGlobalProxy must never be normalized
4499   DCHECK(!object->IsJSGlobalProxy());
4500
4501   Isolate* isolate = object->GetIsolate();
4502   HandleScope scope(isolate);
4503   Handle<Map> map(object->map());
4504
4505   // Allocate new content.
4506   int real_size = map->NumberOfOwnDescriptors();
4507   int property_count = real_size;
4508   if (expected_additional_properties > 0) {
4509     property_count += expected_additional_properties;
4510   } else {
4511     property_count += 2;  // Make space for two more properties.
4512   }
4513   Handle<NameDictionary> dictionary =
4514       NameDictionary::New(isolate, property_count);
4515
4516   Handle<DescriptorArray> descs(map->instance_descriptors());
4517   for (int i = 0; i < real_size; i++) {
4518     PropertyDetails details = descs->GetDetails(i);
4519     Handle<Name> key(descs->GetKey(i));
4520     switch (details.type()) {
4521       case DATA_CONSTANT: {
4522         Handle<Object> value(descs->GetConstant(i), isolate);
4523         PropertyDetails d(details.attributes(), DATA, i + 1,
4524                           PropertyCellType::kNoCell);
4525         dictionary = NameDictionary::Add(dictionary, key, value, d);
4526         break;
4527       }
4528       case DATA: {
4529         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4530         Handle<Object> value;
4531         if (object->IsUnboxedDoubleField(index)) {
4532           double old_value = object->RawFastDoublePropertyAt(index);
4533           value = isolate->factory()->NewHeapNumber(old_value);
4534         } else {
4535           value = handle(object->RawFastPropertyAt(index), isolate);
4536           if (details.representation().IsDouble()) {
4537             DCHECK(value->IsMutableHeapNumber());
4538             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4539             value = isolate->factory()->NewHeapNumber(old->value());
4540           }
4541         }
4542         PropertyDetails d(details.attributes(), DATA, i + 1,
4543                           PropertyCellType::kNoCell);
4544         dictionary = NameDictionary::Add(dictionary, key, value, d);
4545         break;
4546       }
4547       case ACCESSOR: {
4548         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4549         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
4550         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4551                           PropertyCellType::kNoCell);
4552         dictionary = NameDictionary::Add(dictionary, key, value, d);
4553         break;
4554       }
4555       case ACCESSOR_CONSTANT: {
4556         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4557         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4558                           PropertyCellType::kNoCell);
4559         dictionary = NameDictionary::Add(dictionary, key, value, d);
4560         break;
4561       }
4562     }
4563   }
4564
4565   // Copy the next enumeration index from instance descriptor.
4566   dictionary->SetNextEnumerationIndex(real_size + 1);
4567
4568   // From here on we cannot fail and we shouldn't GC anymore.
4569   DisallowHeapAllocation no_allocation;
4570
4571   // Resize the object in the heap if necessary.
4572   int new_instance_size = new_map->instance_size();
4573   int instance_size_delta = map->instance_size() - new_instance_size;
4574   DCHECK(instance_size_delta >= 0);
4575
4576   if (instance_size_delta > 0) {
4577     Heap* heap = isolate->heap();
4578     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4579                                instance_size_delta);
4580     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4581                           Heap::CONCURRENT_TO_SWEEPER);
4582   }
4583
4584   // We are storing the new map using release store after creating a filler for
4585   // the left-over space to avoid races with the sweeper thread.
4586   object->synchronized_set_map(*new_map);
4587
4588   object->set_properties(*dictionary);
4589
4590   // Ensure that in-object space of slow-mode object does not contain random
4591   // garbage.
4592   int inobject_properties = new_map->inobject_properties();
4593   for (int i = 0; i < inobject_properties; i++) {
4594     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4595     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
4596   }
4597
4598   isolate->counters()->props_to_dictionary()->Increment();
4599
4600 #ifdef DEBUG
4601   if (FLAG_trace_normalization) {
4602     OFStream os(stdout);
4603     os << "Object properties have been normalized:\n";
4604     object->Print(os);
4605   }
4606 #endif
4607 }
4608
4609
4610 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4611                                  int unused_property_fields,
4612                                  const char* reason) {
4613   if (object->HasFastProperties()) return;
4614   DCHECK(!object->IsGlobalObject());
4615   Isolate* isolate = object->GetIsolate();
4616   Factory* factory = isolate->factory();
4617   Handle<NameDictionary> dictionary(object->property_dictionary());
4618
4619   // Make sure we preserve dictionary representation if there are too many
4620   // descriptors.
4621   int number_of_elements = dictionary->NumberOfElements();
4622   if (number_of_elements > kMaxNumberOfDescriptors) return;
4623
4624   Handle<FixedArray> iteration_order;
4625   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4626     iteration_order =
4627         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4628   } else {
4629     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
4630   }
4631
4632   int instance_descriptor_length = iteration_order->length();
4633   int number_of_fields = 0;
4634
4635   // Compute the length of the instance descriptor.
4636   for (int i = 0; i < instance_descriptor_length; i++) {
4637     int index = Smi::cast(iteration_order->get(i))->value();
4638     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
4639
4640     Object* value = dictionary->ValueAt(index);
4641     PropertyType type = dictionary->DetailsAt(index).type();
4642     if (type == DATA && !value->IsJSFunction()) {
4643       number_of_fields += 1;
4644     }
4645   }
4646
4647   int inobject_props = object->map()->inobject_properties();
4648
4649   // Allocate new map.
4650   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4651   new_map->set_dictionary_map(false);
4652
4653   if (object->map()->is_prototype_map()) {
4654     DCHECK(new_map->is_prototype_map());
4655     new_map->set_prototype_info(object->map()->prototype_info());
4656     object->map()->set_prototype_info(Smi::FromInt(0));
4657     if (FLAG_trace_prototype_users) {
4658       PrintF("Moving prototype_info %p from map %p to map %p.\n",
4659              reinterpret_cast<void*>(new_map->prototype_info()),
4660              reinterpret_cast<void*>(object->map()),
4661              reinterpret_cast<void*>(*new_map));
4662     }
4663   }
4664
4665 #if TRACE_MAPS
4666   if (FLAG_trace_maps) {
4667     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
4668            reinterpret_cast<void*>(object->map()),
4669            reinterpret_cast<void*>(*new_map), reason);
4670   }
4671 #endif
4672
4673   if (instance_descriptor_length == 0) {
4674     DisallowHeapAllocation no_gc;
4675     DCHECK_LE(unused_property_fields, inobject_props);
4676     // Transform the object.
4677     new_map->set_unused_property_fields(inobject_props);
4678     object->synchronized_set_map(*new_map);
4679     object->set_properties(isolate->heap()->empty_fixed_array());
4680     // Check that it really works.
4681     DCHECK(object->HasFastProperties());
4682     return;
4683   }
4684
4685   // Allocate the instance descriptor.
4686   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4687       isolate, instance_descriptor_length);
4688
4689   int number_of_allocated_fields =
4690       number_of_fields + unused_property_fields - inobject_props;
4691   if (number_of_allocated_fields < 0) {
4692     // There is enough inobject space for all fields (including unused).
4693     number_of_allocated_fields = 0;
4694     unused_property_fields = inobject_props - number_of_fields;
4695   }
4696
4697   // Allocate the fixed array for the fields.
4698   Handle<FixedArray> fields = factory->NewFixedArray(
4699       number_of_allocated_fields);
4700
4701   // Fill in the instance descriptor and the fields.
4702   int current_offset = 0;
4703   for (int i = 0; i < instance_descriptor_length; i++) {
4704     int index = Smi::cast(iteration_order->get(i))->value();
4705     Object* k = dictionary->KeyAt(index);
4706     DCHECK(dictionary->IsKey(k));
4707
4708     Object* value = dictionary->ValueAt(index);
4709     Handle<Name> key;
4710     if (k->IsSymbol()) {
4711       key = handle(Symbol::cast(k));
4712     } else {
4713       // Ensure the key is a unique name before writing into the
4714       // instance descriptor.
4715       key = factory->InternalizeString(handle(String::cast(k)));
4716     }
4717
4718     PropertyDetails details = dictionary->DetailsAt(index);
4719     int enumeration_index = details.dictionary_index();
4720     PropertyType type = details.type();
4721
4722     if (value->IsJSFunction()) {
4723       DataConstantDescriptor d(key, handle(value, isolate),
4724                                details.attributes());
4725       descriptors->Set(enumeration_index - 1, &d);
4726     } else if (type == DATA) {
4727       if (current_offset < inobject_props) {
4728         object->InObjectPropertyAtPut(current_offset, value,
4729                                       UPDATE_WRITE_BARRIER);
4730       } else {
4731         int offset = current_offset - inobject_props;
4732         fields->set(offset, value);
4733       }
4734       DataDescriptor d(key, current_offset, details.attributes(),
4735                        // TODO(verwaest): value->OptimalRepresentation();
4736                        Representation::Tagged());
4737       current_offset += d.GetDetails().field_width_in_words();
4738       descriptors->Set(enumeration_index - 1, &d);
4739     } else if (type == ACCESSOR_CONSTANT) {
4740       AccessorConstantDescriptor d(key, handle(value, isolate),
4741                                    details.attributes());
4742       descriptors->Set(enumeration_index - 1, &d);
4743     } else {
4744       UNREACHABLE();
4745     }
4746   }
4747   DCHECK(current_offset == number_of_fields);
4748
4749   descriptors->Sort();
4750
4751   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
4752       new_map, descriptors, descriptors->number_of_descriptors());
4753
4754   DisallowHeapAllocation no_gc;
4755   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
4756   new_map->set_unused_property_fields(unused_property_fields);
4757
4758   // Transform the object.
4759   object->synchronized_set_map(*new_map);
4760
4761   object->set_properties(*fields);
4762   DCHECK(object->IsJSObject());
4763
4764   // Check that it really works.
4765   DCHECK(object->HasFastProperties());
4766 }
4767
4768
4769 void JSObject::ResetElements(Handle<JSObject> object) {
4770   Isolate* isolate = object->GetIsolate();
4771   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4772   if (object->map()->has_dictionary_elements()) {
4773     Handle<SeededNumberDictionary> new_elements =
4774         SeededNumberDictionary::New(isolate, 0);
4775     object->set_elements(*new_elements);
4776   } else {
4777     object->set_elements(object->map()->GetInitialElements());
4778   }
4779 }
4780
4781
4782 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4783     Handle<FixedArrayBase> array,
4784     int length,
4785     Handle<SeededNumberDictionary> dictionary) {
4786   Isolate* isolate = array->GetIsolate();
4787   Factory* factory = isolate->factory();
4788   bool has_double_elements = array->IsFixedDoubleArray();
4789   for (int i = 0; i < length; i++) {
4790     Handle<Object> value;
4791     if (has_double_elements) {
4792       Handle<FixedDoubleArray> double_array =
4793           Handle<FixedDoubleArray>::cast(array);
4794       if (double_array->is_the_hole(i)) {
4795         value = factory->the_hole_value();
4796       } else {
4797         value = factory->NewHeapNumber(double_array->get_scalar(i));
4798       }
4799     } else {
4800       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4801     }
4802     if (!value->IsTheHole()) {
4803       PropertyDetails details = PropertyDetails::Empty();
4804       dictionary =
4805           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4806     }
4807   }
4808   return dictionary;
4809 }
4810
4811
4812 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
4813   if (dictionary->requires_slow_elements()) return;
4814   dictionary->set_requires_slow_elements();
4815   // TODO(verwaest): Remove this hack.
4816   if (map()->is_prototype_map()) {
4817     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
4818   }
4819 }
4820
4821
4822 Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
4823     Handle<JSObject> object, Handle<FixedArrayBase> elements) {
4824   DCHECK(!object->HasDictionaryElements());
4825   DCHECK(!object->HasSlowArgumentsElements());
4826   Isolate* isolate = object->GetIsolate();
4827   // Ensure that notifications fire if the array or object prototypes are
4828   // normalizing.
4829   isolate->UpdateArrayProtectorOnNormalizeElements(object);
4830   int length = object->IsJSArray()
4831                    ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4832                    : elements->length();
4833   int used = object->GetFastElementsUsage();
4834   Handle<SeededNumberDictionary> dictionary =
4835       SeededNumberDictionary::New(isolate, used);
4836   return CopyFastElementsToDictionary(elements, length, dictionary);
4837 }
4838
4839
4840 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4841     Handle<JSObject> object) {
4842   DCHECK(!object->HasFixedTypedArrayElements());
4843   Isolate* isolate = object->GetIsolate();
4844
4845   // Find the backing store.
4846   Handle<FixedArrayBase> elements(object->elements(), isolate);
4847   bool is_arguments = object->HasSloppyArgumentsElements();
4848   if (is_arguments) {
4849     FixedArray* parameter_map = FixedArray::cast(*elements);
4850     elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
4851   }
4852
4853   if (elements->IsDictionary()) {
4854     return Handle<SeededNumberDictionary>::cast(elements);
4855   }
4856
4857   DCHECK(object->HasFastSmiOrObjectElements() ||
4858          object->HasFastDoubleElements() ||
4859          object->HasFastArgumentsElements());
4860
4861   Handle<SeededNumberDictionary> dictionary =
4862       GetNormalizedElementDictionary(object, elements);
4863
4864   // Switch to using the dictionary as the backing storage for elements.
4865   ElementsKind target_kind =
4866       is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
4867   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
4868   // Set the new map first to satify the elements type assert in set_elements().
4869   JSObject::MigrateToMap(object, new_map);
4870
4871   if (is_arguments) {
4872     FixedArray::cast(object->elements())->set(1, *dictionary);
4873   } else {
4874     object->set_elements(*dictionary);
4875   }
4876
4877   isolate->counters()->elements_to_dictionary()->Increment();
4878
4879 #ifdef DEBUG
4880   if (FLAG_trace_normalization) {
4881     OFStream os(stdout);
4882     os << "Object elements have been normalized:\n";
4883     object->Print(os);
4884   }
4885 #endif
4886
4887   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
4888   return dictionary;
4889 }
4890
4891
4892 static Smi* GenerateIdentityHash(Isolate* isolate) {
4893   int hash_value;
4894   int attempts = 0;
4895   do {
4896     // Generate a random 32-bit hash value but limit range to fit
4897     // within a smi.
4898     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4899     attempts++;
4900   } while (hash_value == 0 && attempts < 30);
4901   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4902
4903   return Smi::FromInt(hash_value);
4904 }
4905
4906
4907 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4908   DCHECK(!object->IsJSGlobalProxy());
4909   Isolate* isolate = object->GetIsolate();
4910   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4911   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4912 }
4913
4914
4915 template<typename ProxyType>
4916 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4917   Isolate* isolate = proxy->GetIsolate();
4918
4919   Handle<Object> maybe_hash(proxy->hash(), isolate);
4920   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4921
4922   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4923   proxy->set_hash(*hash);
4924   return hash;
4925 }
4926
4927
4928 Object* JSObject::GetIdentityHash() {
4929   DisallowHeapAllocation no_gc;
4930   Isolate* isolate = GetIsolate();
4931   if (IsJSGlobalProxy()) {
4932     return JSGlobalProxy::cast(this)->hash();
4933   }
4934   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4935   Handle<Object> stored_value =
4936       Object::GetPropertyOrElement(Handle<Object>(this, isolate),
4937                                    hash_code_symbol).ToHandleChecked();
4938   return stored_value->IsSmi() ? *stored_value
4939                                : isolate->heap()->undefined_value();
4940 }
4941
4942
4943 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4944   if (object->IsJSGlobalProxy()) {
4945     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4946   }
4947
4948   Isolate* isolate = object->GetIsolate();
4949
4950   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4951   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4952
4953   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4954   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4955   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4956   return hash;
4957 }
4958
4959
4960 Object* JSProxy::GetIdentityHash() {
4961   return this->hash();
4962 }
4963
4964
4965 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4966   return GetOrCreateIdentityHashHelper(proxy);
4967 }
4968
4969
4970 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4971   DisallowHeapAllocation no_gc;
4972   DCHECK(key->IsUniqueName());
4973   if (IsJSGlobalProxy()) {
4974     // For a proxy, use the prototype as target object.
4975     PrototypeIterator iter(GetIsolate(), this);
4976     // If the proxy is detached, return undefined.
4977     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4978     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4979     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4980   }
4981   DCHECK(!IsJSGlobalProxy());
4982   Object* inline_value = GetHiddenPropertiesHashTable();
4983
4984   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4985
4986   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4987   Object* entry = hashtable->Lookup(key);
4988   return entry;
4989 }
4990
4991
4992 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
4993                                            Handle<Name> key,
4994                                            Handle<Object> value) {
4995   Isolate* isolate = object->GetIsolate();
4996
4997   DCHECK(key->IsUniqueName());
4998   if (object->IsJSGlobalProxy()) {
4999     // For a proxy, use the prototype as target object.
5000     PrototypeIterator iter(isolate, object);
5001     // If the proxy is detached, return undefined.
5002     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
5003     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5004     return SetHiddenProperty(
5005         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
5006         value);
5007   }
5008   DCHECK(!object->IsJSGlobalProxy());
5009
5010   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5011
5012   Handle<ObjectHashTable> hashtable =
5013       GetOrCreateHiddenPropertiesHashtable(object);
5014
5015   // If it was found, check if the key is already in the dictionary.
5016   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5017                                                            value);
5018   if (*new_table != *hashtable) {
5019     // If adding the key expanded the dictionary (i.e., Add returned a new
5020     // dictionary), store it back to the object.
5021     SetHiddenPropertiesHashTable(object, new_table);
5022   }
5023
5024   // Return this to mark success.
5025   return object;
5026 }
5027
5028
5029 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5030   Isolate* isolate = object->GetIsolate();
5031   DCHECK(key->IsUniqueName());
5032
5033   if (object->IsJSGlobalProxy()) {
5034     PrototypeIterator iter(isolate, object);
5035     if (iter.IsAtEnd()) return;
5036     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5037     return DeleteHiddenProperty(
5038         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5039   }
5040
5041   Object* inline_value = object->GetHiddenPropertiesHashTable();
5042
5043   if (inline_value->IsUndefined()) return;
5044
5045   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5046   bool was_present = false;
5047   ObjectHashTable::Remove(hashtable, key, &was_present);
5048 }
5049
5050
5051 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5052   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5053   LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
5054   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5055   // Cannot get an exception since the hidden_string isn't accessible to JS.
5056   DCHECK(maybe.IsJust());
5057   return maybe.FromJust() != ABSENT;
5058 }
5059
5060
5061 Object* JSObject::GetHiddenPropertiesHashTable() {
5062   DCHECK(!IsJSGlobalProxy());
5063   if (HasFastProperties()) {
5064     // If the object has fast properties, check whether the first slot
5065     // in the descriptor array matches the hidden string. Since the
5066     // hidden strings hash code is zero (and no other name has hash
5067     // code zero) it will always occupy the first entry if present.
5068     DescriptorArray* descriptors = this->map()->instance_descriptors();
5069     if (descriptors->number_of_descriptors() > 0) {
5070       int sorted_index = descriptors->GetSortedKeyIndex(0);
5071       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5072           sorted_index < map()->NumberOfOwnDescriptors()) {
5073         DCHECK(descriptors->GetType(sorted_index) == DATA);
5074         DCHECK(descriptors->GetDetails(sorted_index).representation().
5075                IsCompatibleForLoad(Representation::Tagged()));
5076         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5077                                                      sorted_index);
5078         return this->RawFastPropertyAt(index);
5079       } else {
5080         return GetHeap()->undefined_value();
5081       }
5082     } else {
5083       return GetHeap()->undefined_value();
5084     }
5085   } else {
5086     Isolate* isolate = GetIsolate();
5087     LookupIterator it(handle(this), isolate->factory()->hidden_string(),
5088                       LookupIterator::OWN_SKIP_INTERCEPTOR);
5089     // Access check is always skipped for the hidden string anyways.
5090     return *GetDataProperty(&it);
5091   }
5092 }
5093
5094 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5095     Handle<JSObject> object) {
5096   Isolate* isolate = object->GetIsolate();
5097
5098   static const int kInitialCapacity = 4;
5099   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5100   if (inline_value->IsHashTable()) {
5101     return Handle<ObjectHashTable>::cast(inline_value);
5102   }
5103
5104   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5105       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5106
5107   DCHECK(inline_value->IsUndefined());
5108   SetHiddenPropertiesHashTable(object, hashtable);
5109   return hashtable;
5110 }
5111
5112
5113 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5114                                                       Handle<Object> value) {
5115   DCHECK(!object->IsJSGlobalProxy());
5116   Isolate* isolate = object->GetIsolate();
5117   Handle<Name> name = isolate->factory()->hidden_string();
5118   SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
5119   return object;
5120 }
5121
5122
5123 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5124     LookupIterator* it) {
5125   Isolate* isolate = it->isolate();
5126   // Make sure that the top context does not change when doing callbacks or
5127   // interceptor calls.
5128   AssertNoContextChange ncc(isolate);
5129
5130   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
5131   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
5132   if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
5133
5134   Handle<JSObject> holder = it->GetHolder<JSObject>();
5135
5136   PropertyCallbackArguments args(isolate, interceptor->data(),
5137                                  *it->GetReceiver(), *holder);
5138   v8::Local<v8::Boolean> result;
5139   if (it->IsElement()) {
5140     uint32_t index = it->index();
5141     v8::IndexedPropertyDeleterCallback deleter =
5142         v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5143     LOG(isolate,
5144         ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index));
5145     result = args.Call(deleter, index);
5146   } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
5147     return MaybeHandle<Object>();
5148   } else {
5149     Handle<Name> name = it->name();
5150     v8::GenericNamedPropertyDeleterCallback deleter =
5151         v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
5152             interceptor->deleter());
5153     LOG(isolate,
5154         ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
5155     result = args.Call(deleter, v8::Utils::ToLocal(name));
5156   }
5157
5158   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5159   if (result.IsEmpty()) return MaybeHandle<Object>();
5160
5161   DCHECK(result->IsBoolean());
5162   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5163   result_internal->VerifyApiCallResultType();
5164   // Rebox CustomArguments::kReturnValueOffset before returning.
5165   return handle(*result_internal, isolate);
5166 }
5167
5168
5169 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
5170                                         Handle<Name> name, int entry) {
5171   DCHECK(!object->HasFastProperties());
5172   Isolate* isolate = object->GetIsolate();
5173
5174   if (object->IsGlobalObject()) {
5175     // If we have a global object, invalidate the cell and swap in a new one.
5176     Handle<GlobalDictionary> dictionary(object->global_dictionary());
5177     DCHECK_NE(GlobalDictionary::kNotFound, entry);
5178
5179     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
5180     cell->set_value(isolate->heap()->the_hole_value());
5181     // TODO(ishell): InvalidateForDelete
5182     cell->set_property_details(
5183         cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
5184   } else {
5185     Handle<NameDictionary> dictionary(object->property_dictionary());
5186     DCHECK_NE(NameDictionary::kNotFound, entry);
5187
5188     NameDictionary::DeleteProperty(dictionary, entry);
5189     Handle<NameDictionary> new_properties =
5190         NameDictionary::Shrink(dictionary, name);
5191     object->set_properties(*new_properties);
5192   }
5193 }
5194
5195
5196 // ECMA-262, 3rd, 8.6.2.5
5197 MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it,
5198                                                LanguageMode language_mode) {
5199   Isolate* isolate = it->isolate();
5200   if (it->state() == LookupIterator::JSPROXY) {
5201     return JSProxy::DeletePropertyWithHandler(it->GetHolder<JSProxy>(),
5202                                               it->GetName(), language_mode);
5203   }
5204
5205   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
5206
5207   bool is_observed =
5208       receiver->map()->is_observed() &&
5209       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()));
5210
5211   Handle<Object> old_value = it->factory()->the_hole_value();
5212
5213   for (; it->IsFound(); it->Next()) {
5214     switch (it->state()) {
5215       case LookupIterator::JSPROXY:
5216       case LookupIterator::NOT_FOUND:
5217       case LookupIterator::TRANSITION:
5218         UNREACHABLE();
5219       case LookupIterator::ACCESS_CHECK:
5220         if (it->HasAccess()) break;
5221         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
5222         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5223         return it->factory()->false_value();
5224       case LookupIterator::INTERCEPTOR: {
5225         MaybeHandle<Object> maybe_result =
5226             JSObject::DeletePropertyWithInterceptor(it);
5227         // Delete with interceptor succeeded. Return result.
5228         if (!maybe_result.is_null()) return maybe_result;
5229         // An exception was thrown in the interceptor. Propagate.
5230         if (isolate->has_pending_exception()) return maybe_result;
5231         break;
5232       }
5233       case LookupIterator::INTEGER_INDEXED_EXOTIC:
5234         return it->factory()->true_value();
5235       case LookupIterator::DATA:
5236         if (is_observed) {
5237           old_value = it->GetDataValue();
5238         }
5239       // Fall through.
5240       case LookupIterator::ACCESSOR: {
5241         if (!it->IsConfigurable() || receiver->map()->is_strong()) {
5242           // Fail if the property is not configurable, or on a strong object.
5243           if (is_strict(language_mode)) {
5244             MessageTemplate::Template templ =
5245                 receiver->map()->is_strong()
5246                     ? MessageTemplate::kStrongDeleteProperty
5247                     : MessageTemplate::kStrictDeleteProperty;
5248             THROW_NEW_ERROR(
5249                 isolate, NewTypeError(templ, it->GetName(), receiver), Object);
5250           }
5251           return it->factory()->false_value();
5252         }
5253
5254         it->Delete();
5255
5256         if (is_observed) {
5257           RETURN_ON_EXCEPTION(isolate,
5258                               JSObject::EnqueueChangeRecord(
5259                                   receiver, "delete", it->GetName(), old_value),
5260                               Object);
5261         }
5262
5263         return it->factory()->true_value();
5264       }
5265     }
5266   }
5267
5268   return it->factory()->true_value();
5269 }
5270
5271
5272 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5273                                               uint32_t index,
5274                                               LanguageMode language_mode) {
5275   LookupIterator it(object->GetIsolate(), object, index,
5276                     LookupIterator::HIDDEN);
5277   return DeleteProperty(&it, language_mode);
5278 }
5279
5280
5281 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5282                                                Handle<Name> name,
5283                                                LanguageMode language_mode) {
5284   LookupIterator it(object, name, LookupIterator::HIDDEN);
5285   return JSObject::DeleteProperty(&it, language_mode);
5286 }
5287
5288
5289 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement(
5290     Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) {
5291   LookupIterator it = LookupIterator::PropertyOrElement(
5292       name->GetIsolate(), object, name, LookupIterator::HIDDEN);
5293   return JSObject::DeleteProperty(&it, language_mode);
5294 }
5295
5296
5297 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5298                                             ElementsKind kind,
5299                                             Object* object) {
5300   DCHECK(IsFastObjectElementsKind(kind) ||
5301          kind == DICTIONARY_ELEMENTS);
5302   if (IsFastObjectElementsKind(kind)) {
5303     int length = IsJSArray()
5304         ? Smi::cast(JSArray::cast(this)->length())->value()
5305         : elements->length();
5306     for (int i = 0; i < length; ++i) {
5307       Object* element = elements->get(i);
5308       if (!element->IsTheHole() && element == object) return true;
5309     }
5310   } else {
5311     Object* key =
5312         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5313     if (!key->IsUndefined()) return true;
5314   }
5315   return false;
5316 }
5317
5318
5319 // Check whether this object references another object.
5320 bool JSObject::ReferencesObject(Object* obj) {
5321   Map* map_of_this = map();
5322   Heap* heap = GetHeap();
5323   DisallowHeapAllocation no_allocation;
5324
5325   // Is the object the constructor for this object?
5326   if (map_of_this->GetConstructor() == obj) {
5327     return true;
5328   }
5329
5330   // Is the object the prototype for this object?
5331   if (map_of_this->prototype() == obj) {
5332     return true;
5333   }
5334
5335   // Check if the object is among the named properties.
5336   Object* key = SlowReverseLookup(obj);
5337   if (!key->IsUndefined()) {
5338     return true;
5339   }
5340
5341   // Check if the object is among the indexed properties.
5342   ElementsKind kind = GetElementsKind();
5343   switch (kind) {
5344     // Raw pixels and external arrays do not reference other
5345     // objects.
5346 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5347     case TYPE##_ELEMENTS:                                                      \
5348       break;
5349
5350     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5351 #undef TYPED_ARRAY_CASE
5352
5353     case FAST_DOUBLE_ELEMENTS:
5354     case FAST_HOLEY_DOUBLE_ELEMENTS:
5355       break;
5356     case FAST_SMI_ELEMENTS:
5357     case FAST_HOLEY_SMI_ELEMENTS:
5358       break;
5359     case FAST_ELEMENTS:
5360     case FAST_HOLEY_ELEMENTS:
5361     case DICTIONARY_ELEMENTS: {
5362       FixedArray* elements = FixedArray::cast(this->elements());
5363       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5364       break;
5365     }
5366     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5367     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
5368       FixedArray* parameter_map = FixedArray::cast(elements());
5369       // Check the mapped parameters.
5370       int length = parameter_map->length();
5371       for (int i = 2; i < length; ++i) {
5372         Object* value = parameter_map->get(i);
5373         if (!value->IsTheHole() && value == obj) return true;
5374       }
5375       // Check the arguments.
5376       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5377       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5378           FAST_HOLEY_ELEMENTS;
5379       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5380       break;
5381     }
5382   }
5383
5384   // For functions check the context.
5385   if (IsJSFunction()) {
5386     // Get the constructor function for arguments array.
5387     Map* arguments_map =
5388         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5389     JSFunction* arguments_function =
5390         JSFunction::cast(arguments_map->GetConstructor());
5391
5392     // Get the context and don't check if it is the native context.
5393     JSFunction* f = JSFunction::cast(this);
5394     Context* context = f->context();
5395     if (context->IsNativeContext()) {
5396       return false;
5397     }
5398
5399     // Check the non-special context slots.
5400     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5401       // Only check JS objects.
5402       if (context->get(i)->IsJSObject()) {
5403         JSObject* ctxobj = JSObject::cast(context->get(i));
5404         // If it is an arguments array check the content.
5405         if (ctxobj->map()->GetConstructor() == arguments_function) {
5406           if (ctxobj->ReferencesObject(obj)) {
5407             return true;
5408           }
5409         } else if (ctxobj == obj) {
5410           return true;
5411         }
5412       }
5413     }
5414
5415     // Check the context extension (if any) if it can have references.
5416     if (context->has_extension() && !context->IsCatchContext()) {
5417       // With harmony scoping, a JSFunction may have a global context.
5418       // TODO(mvstanton): walk into the ScopeInfo.
5419       if (context->IsScriptContext()) {
5420         return false;
5421       }
5422
5423       return JSObject::cast(context->extension())->ReferencesObject(obj);
5424     }
5425   }
5426
5427   // No references to object.
5428   return false;
5429 }
5430
5431
5432 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5433   if (!object->map()->is_extensible()) return object;
5434
5435   if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
5436     return PreventExtensionsWithTransition<NONE>(object);
5437   }
5438
5439   Isolate* isolate = object->GetIsolate();
5440
5441   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5442     isolate->ReportFailedAccessCheck(object);
5443     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5444     return isolate->factory()->false_value();
5445   }
5446
5447   if (object->IsJSGlobalProxy()) {
5448     PrototypeIterator iter(isolate, object);
5449     if (iter.IsAtEnd()) return object;
5450     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5451     return PreventExtensions(
5452         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5453   }
5454
5455   // It's not possible to seal objects with external array elements
5456   if (object->HasFixedTypedArrayElements()) {
5457     THROW_NEW_ERROR(
5458         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5459         Object);
5460   }
5461
5462   // If there are fast elements we normalize.
5463   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5464   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
5465
5466   // Make sure that we never go back to fast case.
5467   object->RequireSlowElements(*dictionary);
5468
5469   // Do a map transition, other objects with this map may still
5470   // be extensible.
5471   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5472   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
5473
5474   new_map->set_is_extensible(false);
5475   JSObject::MigrateToMap(object, new_map);
5476   DCHECK(!object->map()->is_extensible());
5477
5478   if (object->map()->is_observed()) {
5479     RETURN_ON_EXCEPTION(
5480         isolate,
5481         EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5482                             isolate->factory()->the_hole_value()),
5483         Object);
5484   }
5485   return object;
5486 }
5487
5488
5489 bool JSObject::IsExtensible() {
5490   if (IsJSGlobalProxy()) {
5491     PrototypeIterator iter(GetIsolate(), this);
5492     if (iter.IsAtEnd()) return false;
5493     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
5494     return JSObject::cast(iter.GetCurrent())->map()->is_extensible();
5495   }
5496   return map()->is_extensible();
5497 }
5498
5499
5500 template <typename Dictionary>
5501 static void ApplyAttributesToDictionary(Dictionary* dictionary,
5502                                         const PropertyAttributes attributes) {
5503   int capacity = dictionary->Capacity();
5504   for (int i = 0; i < capacity; i++) {
5505     Object* k = dictionary->KeyAt(i);
5506     if (dictionary->IsKey(k) &&
5507         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5508       PropertyDetails details = dictionary->DetailsAt(i);
5509       int attrs = attributes;
5510       // READ_ONLY is an invalid attribute for JS setters/getters.
5511       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
5512         Object* v = dictionary->ValueAt(i);
5513         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5514         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
5515       }
5516       details = details.CopyAddAttributes(
5517           static_cast<PropertyAttributes>(attrs));
5518       dictionary->DetailsAtPut(i, details);
5519     }
5520   }
5521 }
5522
5523
5524 template <PropertyAttributes attrs>
5525 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
5526     Handle<JSObject> object) {
5527   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
5528
5529   // Sealing/freezing sloppy arguments should be handled elsewhere.
5530   DCHECK(!object->HasSloppyArgumentsElements());
5531   DCHECK(!object->map()->is_observed());
5532
5533   Isolate* isolate = object->GetIsolate();
5534   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5535     isolate->ReportFailedAccessCheck(object);
5536     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5537     return isolate->factory()->false_value();
5538   }
5539
5540   if (object->IsJSGlobalProxy()) {
5541     PrototypeIterator iter(isolate, object);
5542     if (iter.IsAtEnd()) return object;
5543     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5544     return PreventExtensionsWithTransition<attrs>(
5545         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5546   }
5547
5548   // It's not possible to seal or freeze objects with external array elements
5549   if (object->HasFixedTypedArrayElements()) {
5550     THROW_NEW_ERROR(
5551         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5552         Object);
5553   }
5554
5555   Handle<SeededNumberDictionary> new_element_dictionary;
5556   if (!object->HasDictionaryElements()) {
5557     int length =
5558         object->IsJSArray()
5559             ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5560             : object->elements()->length();
5561     new_element_dictionary =
5562         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
5563                     : GetNormalizedElementDictionary(
5564                           object, handle(object->elements()));
5565   }
5566
5567   Handle<Symbol> transition_marker;
5568   if (attrs == NONE) {
5569     transition_marker = isolate->factory()->nonextensible_symbol();
5570   } else if (attrs == SEALED) {
5571     transition_marker = isolate->factory()->sealed_symbol();
5572   } else {
5573     DCHECK(attrs == FROZEN);
5574     transition_marker = isolate->factory()->frozen_symbol();
5575   }
5576
5577   Handle<Map> old_map(object->map(), isolate);
5578   Map* transition =
5579       TransitionArray::SearchSpecial(*old_map, *transition_marker);
5580   if (transition != NULL) {
5581     Handle<Map> transition_map(transition, isolate);
5582     DCHECK(transition_map->has_dictionary_elements());
5583     DCHECK(!transition_map->is_extensible());
5584     JSObject::MigrateToMap(object, transition_map);
5585   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5586     // Create a new descriptor array with the appropriate property attributes
5587     Handle<Map> new_map = Map::CopyForPreventExtensions(
5588         old_map, attrs, transition_marker, "CopyForPreventExtensions");
5589     JSObject::MigrateToMap(object, new_map);
5590   } else {
5591     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5592     // Slow path: need to normalize properties for safety
5593     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5594                         "SlowPreventExtensions");
5595
5596     // Create a new map, since other objects with this map may be extensible.
5597     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5598     Handle<Map> new_map =
5599         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5600     new_map->set_is_extensible(false);
5601     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5602     JSObject::MigrateToMap(object, new_map);
5603
5604     if (attrs != NONE) {
5605       if (object->IsGlobalObject()) {
5606         ApplyAttributesToDictionary(object->global_dictionary(), attrs);
5607       } else {
5608         ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5609       }
5610     }
5611   }
5612
5613   DCHECK(object->map()->has_dictionary_elements());
5614   if (!new_element_dictionary.is_null()) {
5615     object->set_elements(*new_element_dictionary);
5616   }
5617
5618   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5619     SeededNumberDictionary* dictionary = object->element_dictionary();
5620     // Make sure we never go back to the fast case
5621     object->RequireSlowElements(dictionary);
5622     if (attrs != NONE) {
5623       ApplyAttributesToDictionary(dictionary, attrs);
5624     }
5625   }
5626
5627   return object;
5628 }
5629
5630
5631 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5632   return PreventExtensionsWithTransition<FROZEN>(object);
5633 }
5634
5635
5636 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
5637   return PreventExtensionsWithTransition<SEALED>(object);
5638 }
5639
5640
5641 void JSObject::SetObserved(Handle<JSObject> object) {
5642   DCHECK(!object->IsJSGlobalProxy());
5643   DCHECK(!object->IsJSGlobalObject());
5644   Isolate* isolate = object->GetIsolate();
5645   Handle<Map> new_map;
5646   Handle<Map> old_map(object->map(), isolate);
5647   DCHECK(!old_map->is_observed());
5648   Map* transition = TransitionArray::SearchSpecial(
5649       *old_map, isolate->heap()->observed_symbol());
5650   if (transition != NULL) {
5651     new_map = handle(transition, isolate);
5652     DCHECK(new_map->is_observed());
5653   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5654     new_map = Map::CopyForObserved(old_map);
5655   } else {
5656     new_map = Map::Copy(old_map, "SlowObserved");
5657     new_map->set_is_observed();
5658   }
5659   JSObject::MigrateToMap(object, new_map);
5660 }
5661
5662
5663 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5664                                         Representation representation,
5665                                         FieldIndex index) {
5666   Isolate* isolate = object->GetIsolate();
5667   if (object->IsUnboxedDoubleField(index)) {
5668     double value = object->RawFastDoublePropertyAt(index);
5669     return isolate->factory()->NewHeapNumber(value);
5670   }
5671   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5672   return Object::WrapForRead(isolate, raw_value, representation);
5673 }
5674
5675
5676 template<class ContextObject>
5677 class JSObjectWalkVisitor {
5678  public:
5679   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5680                       JSObject::DeepCopyHints hints)
5681     : site_context_(site_context),
5682       copying_(copying),
5683       hints_(hints) {}
5684
5685   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5686
5687  protected:
5688   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5689       Handle<JSObject> object,
5690       Handle<JSObject> value) {
5691     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5692     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5693     site_context()->ExitScope(current_site, value);
5694     return copy_of_value;
5695   }
5696
5697   inline ContextObject* site_context() { return site_context_; }
5698   inline Isolate* isolate() { return site_context()->isolate(); }
5699
5700   inline bool copying() const { return copying_; }
5701
5702  private:
5703   ContextObject* site_context_;
5704   const bool copying_;
5705   const JSObject::DeepCopyHints hints_;
5706 };
5707
5708
5709 template <class ContextObject>
5710 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5711     Handle<JSObject> object) {
5712   Isolate* isolate = this->isolate();
5713   bool copying = this->copying();
5714   bool shallow = hints_ == JSObject::kObjectIsShallow;
5715
5716   if (!shallow) {
5717     StackLimitCheck check(isolate);
5718
5719     if (check.HasOverflowed()) {
5720       isolate->StackOverflow();
5721       return MaybeHandle<JSObject>();
5722     }
5723   }
5724
5725   if (object->map()->is_deprecated()) {
5726     JSObject::MigrateInstance(object);
5727   }
5728
5729   Handle<JSObject> copy;
5730   if (copying) {
5731     Handle<AllocationSite> site_to_pass;
5732     if (site_context()->ShouldCreateMemento(object)) {
5733       site_to_pass = site_context()->current();
5734     }
5735     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5736         object, site_to_pass);
5737   } else {
5738     copy = object;
5739   }
5740
5741   DCHECK(copying || copy.is_identical_to(object));
5742
5743   ElementsKind kind = copy->GetElementsKind();
5744   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5745       FixedArray::cast(copy->elements())->map() ==
5746         isolate->heap()->fixed_cow_array_map()) {
5747     isolate->counters()->cow_arrays_created_runtime()->Increment();
5748   }
5749
5750   if (!shallow) {
5751     HandleScope scope(isolate);
5752
5753     // Deep copy own properties.
5754     if (copy->HasFastProperties()) {
5755       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5756       int limit = copy->map()->NumberOfOwnDescriptors();
5757       for (int i = 0; i < limit; i++) {
5758         PropertyDetails details = descriptors->GetDetails(i);
5759         if (details.type() != DATA) continue;
5760         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5761         if (object->IsUnboxedDoubleField(index)) {
5762           if (copying) {
5763             double value = object->RawFastDoublePropertyAt(index);
5764             copy->RawFastDoublePropertyAtPut(index, value);
5765           }
5766         } else {
5767           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5768           if (value->IsJSObject()) {
5769             ASSIGN_RETURN_ON_EXCEPTION(
5770                 isolate, value,
5771                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5772                 JSObject);
5773             if (copying) {
5774               copy->FastPropertyAtPut(index, *value);
5775             }
5776           } else {
5777             if (copying) {
5778               Representation representation = details.representation();
5779               value = Object::NewStorageFor(isolate, value, representation);
5780               copy->FastPropertyAtPut(index, *value);
5781             }
5782           }
5783         }
5784       }
5785     } else {
5786       Handle<FixedArray> names =
5787           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5788       copy->GetOwnPropertyNames(*names, 0);
5789       for (int i = 0; i < names->length(); i++) {
5790         DCHECK(names->get(i)->IsString());
5791         Handle<String> key_string(String::cast(names->get(i)));
5792         Maybe<PropertyAttributes> maybe =
5793             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5794         DCHECK(maybe.IsJust());
5795         PropertyAttributes attributes = maybe.FromJust();
5796         // Only deep copy fields from the object literal expression.
5797         // In particular, don't try to copy the length attribute of
5798         // an array.
5799         if (attributes != NONE) continue;
5800         Handle<Object> value =
5801             Object::GetProperty(copy, key_string).ToHandleChecked();
5802         if (value->IsJSObject()) {
5803           Handle<JSObject> result;
5804           ASSIGN_RETURN_ON_EXCEPTION(
5805               isolate, result,
5806               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5807               JSObject);
5808           if (copying) {
5809             // Creating object copy for literals. No strict mode needed.
5810             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5811           }
5812         }
5813       }
5814     }
5815
5816     // Deep copy own elements.
5817     // Pixel elements cannot be created using an object literal.
5818     DCHECK(!copy->HasFixedTypedArrayElements());
5819     switch (kind) {
5820       case FAST_SMI_ELEMENTS:
5821       case FAST_ELEMENTS:
5822       case FAST_HOLEY_SMI_ELEMENTS:
5823       case FAST_HOLEY_ELEMENTS: {
5824         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5825         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5826 #ifdef DEBUG
5827           for (int i = 0; i < elements->length(); i++) {
5828             DCHECK(!elements->get(i)->IsJSObject());
5829           }
5830 #endif
5831         } else {
5832           for (int i = 0; i < elements->length(); i++) {
5833             Handle<Object> value(elements->get(i), isolate);
5834             DCHECK(value->IsSmi() ||
5835                    value->IsTheHole() ||
5836                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5837             if (value->IsJSObject()) {
5838               Handle<JSObject> result;
5839               ASSIGN_RETURN_ON_EXCEPTION(
5840                   isolate, result,
5841                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5842                   JSObject);
5843               if (copying) {
5844                 elements->set(i, *result);
5845               }
5846             }
5847           }
5848         }
5849         break;
5850       }
5851       case DICTIONARY_ELEMENTS: {
5852         Handle<SeededNumberDictionary> element_dictionary(
5853             copy->element_dictionary());
5854         int capacity = element_dictionary->Capacity();
5855         for (int i = 0; i < capacity; i++) {
5856           Object* k = element_dictionary->KeyAt(i);
5857           if (element_dictionary->IsKey(k)) {
5858             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5859             if (value->IsJSObject()) {
5860               Handle<JSObject> result;
5861               ASSIGN_RETURN_ON_EXCEPTION(
5862                   isolate, result,
5863                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5864                   JSObject);
5865               if (copying) {
5866                 element_dictionary->ValueAtPut(i, *result);
5867               }
5868             }
5869           }
5870         }
5871         break;
5872       }
5873       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5874       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
5875         UNIMPLEMENTED();
5876         break;
5877
5878
5879 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5880       case TYPE##_ELEMENTS:                                                    \
5881
5882       TYPED_ARRAYS(TYPED_ARRAY_CASE)
5883 #undef TYPED_ARRAY_CASE
5884
5885       case FAST_DOUBLE_ELEMENTS:
5886       case FAST_HOLEY_DOUBLE_ELEMENTS:
5887         // No contained objects, nothing to do.
5888         break;
5889     }
5890   }
5891
5892   return copy;
5893 }
5894
5895
5896 MaybeHandle<JSObject> JSObject::DeepWalk(
5897     Handle<JSObject> object,
5898     AllocationSiteCreationContext* site_context) {
5899   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
5900                                                        kNoHints);
5901   MaybeHandle<JSObject> result = v.StructureWalk(object);
5902   Handle<JSObject> for_assert;
5903   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
5904   return result;
5905 }
5906
5907
5908 MaybeHandle<JSObject> JSObject::DeepCopy(
5909     Handle<JSObject> object,
5910     AllocationSiteUsageContext* site_context,
5911     DeepCopyHints hints) {
5912   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5913   MaybeHandle<JSObject> copy = v.StructureWalk(object);
5914   Handle<JSObject> for_assert;
5915   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
5916   return copy;
5917 }
5918
5919
5920 // Tests for the fast common case for property enumeration:
5921 // - This object and all prototypes has an enum cache (which means that
5922 //   it is no proxy, has no interceptors and needs no access checks).
5923 // - This object has no elements.
5924 // - No prototype has enumerable properties/elements.
5925 bool JSReceiver::IsSimpleEnum() {
5926   for (PrototypeIterator iter(GetIsolate(), this,
5927                               PrototypeIterator::START_AT_RECEIVER);
5928        !iter.IsAtEnd(); iter.Advance()) {
5929     if (!iter.GetCurrent()->IsJSObject()) return false;
5930     JSObject* curr = JSObject::cast(iter.GetCurrent());
5931     int enum_length = curr->map()->EnumLength();
5932     if (enum_length == kInvalidEnumCacheSentinel) return false;
5933     if (curr->IsAccessCheckNeeded()) return false;
5934     DCHECK(!curr->HasNamedInterceptor());
5935     DCHECK(!curr->HasIndexedInterceptor());
5936     if (curr->NumberOfEnumElements() > 0) return false;
5937     if (curr != this && enum_length != 0) return false;
5938   }
5939   return true;
5940 }
5941
5942
5943 static bool FilterKey(Object* key, PropertyAttributes filter) {
5944   if ((filter & SYMBOLIC) && key->IsSymbol()) {
5945     return true;
5946   }
5947
5948   if ((filter & PRIVATE_SYMBOL) &&
5949       key->IsSymbol() && Symbol::cast(key)->is_private()) {
5950     return true;
5951   }
5952
5953   if ((filter & STRING) && !key->IsSymbol()) {
5954     return true;
5955   }
5956
5957   return false;
5958 }
5959
5960
5961 int Map::NumberOfDescribedProperties(DescriptorFlag which,
5962                                      PropertyAttributes filter) {
5963   int result = 0;
5964   DescriptorArray* descs = instance_descriptors();
5965   int limit = which == ALL_DESCRIPTORS
5966       ? descs->number_of_descriptors()
5967       : NumberOfOwnDescriptors();
5968   for (int i = 0; i < limit; i++) {
5969     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
5970         !FilterKey(descs->GetKey(i), filter)) {
5971       result++;
5972     }
5973   }
5974   return result;
5975 }
5976
5977
5978 int Map::NextFreePropertyIndex() {
5979   int free_index = 0;
5980   int number_of_own_descriptors = NumberOfOwnDescriptors();
5981   DescriptorArray* descs = instance_descriptors();
5982   for (int i = 0; i < number_of_own_descriptors; i++) {
5983     PropertyDetails details = descs->GetDetails(i);
5984     if (details.location() == kField) {
5985       int candidate = details.field_index() + details.field_width_in_words();
5986       if (candidate > free_index) free_index = candidate;
5987     }
5988   }
5989   return free_index;
5990 }
5991
5992
5993 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
5994   int len = array->length();
5995   for (int i = 0; i < len; i++) {
5996     Object* e = array->get(i);
5997     if (!(e->IsName() || e->IsNumber())) return false;
5998   }
5999   return true;
6000 }
6001
6002
6003 static Handle<FixedArray> ReduceFixedArrayTo(
6004     Handle<FixedArray> array, int length) {
6005   DCHECK(array->length() >= length);
6006   if (array->length() == length) return array;
6007
6008   Handle<FixedArray> new_array =
6009       array->GetIsolate()->factory()->NewFixedArray(length);
6010   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6011   return new_array;
6012 }
6013
6014
6015 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
6016                                                  bool cache_result) {
6017   Isolate* isolate = object->GetIsolate();
6018   if (object->HasFastProperties()) {
6019     int own_property_count = object->map()->EnumLength();
6020     // If the enum length of the given map is set to kInvalidEnumCache, this
6021     // means that the map itself has never used the present enum cache. The
6022     // first step to using the cache is to set the enum length of the map by
6023     // counting the number of own descriptors that are not DONT_ENUM or
6024     // SYMBOLIC.
6025     if (own_property_count == kInvalidEnumCacheSentinel) {
6026       own_property_count = object->map()->NumberOfDescribedProperties(
6027           OWN_DESCRIPTORS, DONT_SHOW);
6028     } else {
6029       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6030           OWN_DESCRIPTORS, DONT_SHOW));
6031     }
6032
6033     if (object->map()->instance_descriptors()->HasEnumCache()) {
6034       DescriptorArray* desc = object->map()->instance_descriptors();
6035       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6036
6037       // In case the number of properties required in the enum are actually
6038       // present, we can reuse the enum cache. Otherwise, this means that the
6039       // enum cache was generated for a previous (smaller) version of the
6040       // Descriptor Array. In that case we regenerate the enum cache.
6041       if (own_property_count <= keys->length()) {
6042         if (cache_result) object->map()->SetEnumLength(own_property_count);
6043         isolate->counters()->enum_cache_hits()->Increment();
6044         return ReduceFixedArrayTo(keys, own_property_count);
6045       }
6046     }
6047
6048     Handle<Map> map(object->map());
6049
6050     if (map->instance_descriptors()->IsEmpty()) {
6051       isolate->counters()->enum_cache_hits()->Increment();
6052       if (cache_result) map->SetEnumLength(0);
6053       return isolate->factory()->empty_fixed_array();
6054     }
6055
6056     isolate->counters()->enum_cache_misses()->Increment();
6057
6058     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6059         own_property_count);
6060     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6061         own_property_count);
6062
6063     Handle<DescriptorArray> descs =
6064         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6065
6066     int size = map->NumberOfOwnDescriptors();
6067     int index = 0;
6068
6069     for (int i = 0; i < size; i++) {
6070       PropertyDetails details = descs->GetDetails(i);
6071       Object* key = descs->GetKey(i);
6072       if (!(details.IsDontEnum() || key->IsSymbol())) {
6073         storage->set(index, key);
6074         if (!indices.is_null()) {
6075           if (details.type() != DATA) {
6076             indices = Handle<FixedArray>();
6077           } else {
6078             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6079             int load_by_field_index = field_index.GetLoadByFieldIndex();
6080             indices->set(index, Smi::FromInt(load_by_field_index));
6081           }
6082         }
6083         index++;
6084       }
6085     }
6086     DCHECK(index == storage->length());
6087
6088     Handle<FixedArray> bridge_storage =
6089         isolate->factory()->NewFixedArray(
6090             DescriptorArray::kEnumCacheBridgeLength);
6091     DescriptorArray* desc = object->map()->instance_descriptors();
6092     desc->SetEnumCache(*bridge_storage,
6093                        *storage,
6094                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6095                                          : Object::cast(*indices));
6096     if (cache_result) {
6097       object->map()->SetEnumLength(own_property_count);
6098     }
6099     return storage;
6100   } else if (object->IsGlobalObject()) {
6101     Handle<GlobalDictionary> dictionary(object->global_dictionary());
6102     int length = dictionary->NumberOfEnumElements();
6103     if (length == 0) {
6104       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6105     }
6106     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6107     dictionary->CopyEnumKeysTo(*storage);
6108     return storage;
6109   } else {
6110     Handle<NameDictionary> dictionary(object->property_dictionary());
6111     int length = dictionary->NumberOfEnumElements();
6112     if (length == 0) {
6113       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6114     }
6115     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6116     dictionary->CopyEnumKeysTo(*storage);
6117     return storage;
6118   }
6119 }
6120
6121
6122 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6123                                             KeyCollectionType type) {
6124   USE(ContainsOnlyValidKeys);
6125   Isolate* isolate = object->GetIsolate();
6126   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6127   Handle<JSFunction> arguments_function(
6128       JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6129
6130   PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6131                                           ? PrototypeIterator::END_AT_NON_HIDDEN
6132                                           : PrototypeIterator::END_AT_NULL;
6133   // Only collect keys if access is permitted.
6134   for (PrototypeIterator iter(isolate, object,
6135                               PrototypeIterator::START_AT_RECEIVER);
6136        !iter.IsAtEnd(end); iter.Advance()) {
6137     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6138       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6139                             isolate);
6140       Handle<Object> args[] = { proxy };
6141       Handle<Object> names;
6142       ASSIGN_RETURN_ON_EXCEPTION(
6143           isolate, names,
6144           Execution::Call(isolate,
6145                           isolate->proxy_enumerate(),
6146                           object,
6147                           arraysize(args),
6148                           args),
6149           FixedArray);
6150       ASSIGN_RETURN_ON_EXCEPTION(
6151           isolate, content,
6152           FixedArray::AddKeysFromArrayLike(
6153               content, Handle<JSObject>::cast(names)),
6154           FixedArray);
6155       break;
6156     }
6157
6158     Handle<JSObject> current =
6159         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6160
6161     // Check access rights if required.
6162     if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6163       if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6164         isolate->ReportFailedAccessCheck(current);
6165         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6166       }
6167       break;
6168     }
6169
6170     // Compute the element keys.
6171     Handle<FixedArray> element_keys =
6172         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6173     current->GetEnumElementKeys(*element_keys);
6174     ASSIGN_RETURN_ON_EXCEPTION(
6175         isolate, content,
6176         FixedArray::UnionOfKeys(content, element_keys),
6177         FixedArray);
6178     DCHECK(ContainsOnlyValidKeys(content));
6179
6180     // Add the element keys from the interceptor.
6181     if (current->HasIndexedInterceptor()) {
6182       Handle<JSObject> result;
6183       if (JSObject::GetKeysForIndexedInterceptor(
6184               current, object).ToHandle(&result)) {
6185         ASSIGN_RETURN_ON_EXCEPTION(
6186             isolate, content,
6187             FixedArray::AddKeysFromArrayLike(content, result),
6188             FixedArray);
6189       }
6190       DCHECK(ContainsOnlyValidKeys(content));
6191     }
6192
6193     // We can cache the computed property keys if access checks are
6194     // not needed and no interceptors are involved.
6195     //
6196     // We do not use the cache if the object has elements and
6197     // therefore it does not make sense to cache the property names
6198     // for arguments objects.  Arguments objects will always have
6199     // elements.
6200     // Wrapped strings have elements, but don't have an elements
6201     // array or dictionary.  So the fast inline test for whether to
6202     // use the cache says yes, so we should not create a cache.
6203     bool cache_enum_keys =
6204         ((current->map()->GetConstructor() != *arguments_function) &&
6205          !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6206          !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6207     // Compute the property keys and cache them if possible.
6208     ASSIGN_RETURN_ON_EXCEPTION(
6209         isolate, content,
6210         FixedArray::UnionOfKeys(
6211             content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)),
6212         FixedArray);
6213     DCHECK(ContainsOnlyValidKeys(content));
6214
6215     // Add the non-symbol property keys from the interceptor.
6216     if (current->HasNamedInterceptor()) {
6217       Handle<JSObject> result;
6218       if (JSObject::GetKeysForNamedInterceptor(
6219               current, object).ToHandle(&result)) {
6220         ASSIGN_RETURN_ON_EXCEPTION(
6221             isolate, content, FixedArray::AddKeysFromArrayLike(
6222                                   content, result, FixedArray::NON_SYMBOL_KEYS),
6223             FixedArray);
6224       }
6225       DCHECK(ContainsOnlyValidKeys(content));
6226     }
6227   }
6228   return content;
6229 }
6230
6231
6232 bool Map::DictionaryElementsInPrototypeChainOnly() {
6233   if (IsDictionaryElementsKind(elements_kind())) {
6234     return false;
6235   }
6236
6237   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6238     // Be conservative, don't walk into proxies.
6239     if (iter.GetCurrent()->IsJSProxy()) return true;
6240     // String wrappers have non-configurable, non-writable elements.
6241     if (iter.GetCurrent()->IsStringWrapper()) return true;
6242     JSObject* current = JSObject::cast(iter.GetCurrent());
6243
6244     if (current->HasDictionaryElements() &&
6245         current->element_dictionary()->requires_slow_elements()) {
6246       return true;
6247     }
6248
6249     if (current->HasSlowArgumentsElements()) {
6250       FixedArray* parameter_map = FixedArray::cast(current->elements());
6251       Object* arguments = parameter_map->get(1);
6252       if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
6253         return true;
6254       }
6255     }
6256   }
6257
6258   return false;
6259 }
6260
6261
6262 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6263                                              Handle<Name> name,
6264                                              Handle<Object> getter,
6265                                              Handle<Object> setter,
6266                                              PropertyAttributes attributes) {
6267   Isolate* isolate = object->GetIsolate();
6268
6269   LookupIterator it = LookupIterator::PropertyOrElement(
6270       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6271
6272   if (it.state() == LookupIterator::ACCESS_CHECK) {
6273     if (!it.HasAccess()) {
6274       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6275       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6276       return isolate->factory()->undefined_value();
6277     }
6278     it.Next();
6279   }
6280
6281   // Ignore accessors on typed arrays.
6282   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
6283     return it.factory()->undefined_value();
6284   }
6285
6286   Handle<Object> old_value = isolate->factory()->the_hole_value();
6287   bool is_observed = object->map()->is_observed() &&
6288                      !isolate->IsInternallyUsedPropertyName(name);
6289   bool preexists = false;
6290   if (is_observed) {
6291     CHECK(GetPropertyAttributes(&it).IsJust());
6292     preexists = it.IsFound();
6293     if (preexists && (it.state() == LookupIterator::DATA ||
6294                       it.GetAccessors()->IsAccessorInfo())) {
6295       old_value = GetProperty(&it).ToHandleChecked();
6296     }
6297   }
6298
6299   DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || getter->IsNull());
6300   DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || setter->IsNull());
6301   // At least one of the accessors needs to be a new value.
6302   DCHECK(!getter->IsNull() || !setter->IsNull());
6303   if (!getter->IsNull()) {
6304     it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6305   }
6306   if (!setter->IsNull()) {
6307     it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6308   }
6309
6310   if (is_observed) {
6311     // Make sure the top context isn't changed.
6312     AssertNoContextChange ncc(isolate);
6313     const char* type = preexists ? "reconfigure" : "add";
6314     RETURN_ON_EXCEPTION(
6315         isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
6316   }
6317
6318   return isolate->factory()->undefined_value();
6319 }
6320
6321
6322 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6323                                           Handle<AccessorInfo> info) {
6324   Isolate* isolate = object->GetIsolate();
6325   Handle<Name> name(Name::cast(info->name()), isolate);
6326
6327   LookupIterator it = LookupIterator::PropertyOrElement(
6328       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6329
6330   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
6331   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
6332   //
6333   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
6334   // remove reliance on default return values.
6335   if (it.state() == LookupIterator::ACCESS_CHECK) {
6336     if (!it.HasAccess()) {
6337       isolate->ReportFailedAccessCheck(object);
6338       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6339       return it.factory()->undefined_value();
6340     }
6341     it.Next();
6342   }
6343
6344   // Ignore accessors on typed arrays.
6345   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
6346     return it.factory()->undefined_value();
6347   }
6348
6349   CHECK(GetPropertyAttributes(&it).IsJust());
6350
6351   // ES5 forbids turning a property into an accessor if it's not
6352   // configurable. See 8.6.1 (Table 5).
6353   if (it.IsFound() && !it.IsConfigurable()) {
6354     return it.factory()->undefined_value();
6355   }
6356
6357   it.TransitionToAccessorPair(info, info->property_attributes());
6358
6359   return object;
6360 }
6361
6362
6363 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6364                                           Handle<Name> name,
6365                                           AccessorComponent component) {
6366   Isolate* isolate = object->GetIsolate();
6367
6368   // Make sure that the top context does not change when doing callbacks or
6369   // interceptor calls.
6370   AssertNoContextChange ncc(isolate);
6371
6372   LookupIterator it = LookupIterator::PropertyOrElement(
6373       isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6374
6375   for (; it.IsFound(); it.Next()) {
6376     switch (it.state()) {
6377       case LookupIterator::INTERCEPTOR:
6378       case LookupIterator::NOT_FOUND:
6379       case LookupIterator::TRANSITION:
6380         UNREACHABLE();
6381
6382       case LookupIterator::ACCESS_CHECK:
6383         if (it.HasAccess()) continue;
6384         isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6385         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6386         return isolate->factory()->undefined_value();
6387
6388       case LookupIterator::JSPROXY:
6389         return isolate->factory()->undefined_value();
6390
6391       case LookupIterator::INTEGER_INDEXED_EXOTIC:
6392         return isolate->factory()->undefined_value();
6393       case LookupIterator::DATA:
6394         continue;
6395       case LookupIterator::ACCESSOR: {
6396         Handle<Object> maybe_pair = it.GetAccessors();
6397         if (maybe_pair->IsAccessorPair()) {
6398           return handle(
6399               AccessorPair::cast(*maybe_pair)->GetComponent(component),
6400               isolate);
6401         }
6402       }
6403     }
6404   }
6405
6406   return isolate->factory()->undefined_value();
6407 }
6408
6409
6410 Object* JSObject::SlowReverseLookup(Object* value) {
6411   if (HasFastProperties()) {
6412     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6413     DescriptorArray* descs = map()->instance_descriptors();
6414     bool value_is_number = value->IsNumber();
6415     for (int i = 0; i < number_of_own_descriptors; i++) {
6416       if (descs->GetType(i) == DATA) {
6417         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
6418         if (IsUnboxedDoubleField(field_index)) {
6419           if (value_is_number) {
6420             double property = RawFastDoublePropertyAt(field_index);
6421             if (property == value->Number()) {
6422               return descs->GetKey(i);
6423             }
6424           }
6425         } else {
6426           Object* property = RawFastPropertyAt(field_index);
6427           if (field_index.is_double()) {
6428             DCHECK(property->IsMutableHeapNumber());
6429             if (value_is_number && property->Number() == value->Number()) {
6430               return descs->GetKey(i);
6431             }
6432           } else if (property == value) {
6433             return descs->GetKey(i);
6434           }
6435         }
6436       } else if (descs->GetType(i) == DATA_CONSTANT) {
6437         if (descs->GetConstant(i) == value) {
6438           return descs->GetKey(i);
6439         }
6440       }
6441     }
6442     return GetHeap()->undefined_value();
6443   } else if (IsGlobalObject()) {
6444     return global_dictionary()->SlowReverseLookup(value);
6445   } else {
6446     return property_dictionary()->SlowReverseLookup(value);
6447   }
6448 }
6449
6450
6451 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6452   Isolate* isolate = map->GetIsolate();
6453   Handle<Map> result =
6454       isolate->factory()->NewMap(map->instance_type(), instance_size);
6455   Handle<Object> prototype(map->prototype(), isolate);
6456   Map::SetPrototype(result, prototype);
6457   result->set_constructor_or_backpointer(map->GetConstructor());
6458   result->set_bit_field(map->bit_field());
6459   result->set_bit_field2(map->bit_field2());
6460   int new_bit_field3 = map->bit_field3();
6461   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6462   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6463   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6464                                           kInvalidEnumCacheSentinel);
6465   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6466   if (!map->is_dictionary_map()) {
6467     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6468   }
6469   new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
6470   result->set_bit_field3(new_bit_field3);
6471   return result;
6472 }
6473
6474
6475 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
6476                            const char* reason) {
6477   DCHECK(!fast_map->is_dictionary_map());
6478
6479   Isolate* isolate = fast_map->GetIsolate();
6480   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6481                              isolate);
6482   bool use_cache = !fast_map->is_prototype_map() && !maybe_cache->IsUndefined();
6483   Handle<NormalizedMapCache> cache;
6484   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6485
6486   Handle<Map> new_map;
6487   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6488 #ifdef VERIFY_HEAP
6489     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6490 #endif
6491 #ifdef ENABLE_SLOW_DCHECKS
6492     if (FLAG_enable_slow_asserts) {
6493       // The cached map should match newly created normalized map bit-by-bit,
6494       // except for the code cache, which can contain some ics which can be
6495       // applied to the shared map, dependent code and weak cell cache.
6496       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6497
6498       if (new_map->is_prototype_map()) {
6499         // For prototype maps, the PrototypeInfo is not copied.
6500         DCHECK(memcmp(fresh->address(), new_map->address(),
6501                       kTransitionsOrPrototypeInfoOffset) == 0);
6502         DCHECK(fresh->raw_transitions() == Smi::FromInt(0));
6503         STATIC_ASSERT(kDescriptorsOffset ==
6504                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
6505         DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
6506                       HeapObject::RawField(*new_map, kDescriptorsOffset),
6507                       kCodeCacheOffset - kDescriptorsOffset) == 0);
6508       } else {
6509         DCHECK(memcmp(fresh->address(), new_map->address(),
6510                       Map::kCodeCacheOffset) == 0);
6511       }
6512       STATIC_ASSERT(Map::kDependentCodeOffset ==
6513                     Map::kCodeCacheOffset + kPointerSize);
6514       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
6515                     Map::kDependentCodeOffset + kPointerSize);
6516       int offset = Map::kWeakCellCacheOffset + kPointerSize;
6517       DCHECK(memcmp(fresh->address() + offset,
6518                     new_map->address() + offset,
6519                     Map::kSize - offset) == 0);
6520     }
6521 #endif
6522   } else {
6523     new_map = Map::CopyNormalized(fast_map, mode);
6524     if (use_cache) {
6525       cache->Set(fast_map, new_map);
6526       isolate->counters()->normalized_maps()->Increment();
6527     }
6528 #if TRACE_MAPS
6529     if (FLAG_trace_maps) {
6530       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
6531              reinterpret_cast<void*>(*fast_map),
6532              reinterpret_cast<void*>(*new_map), reason);
6533     }
6534 #endif
6535   }
6536   fast_map->NotifyLeafMapLayoutChange();
6537   return new_map;
6538 }
6539
6540
6541 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6542                                 PropertyNormalizationMode mode) {
6543   int new_instance_size = map->instance_size();
6544   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6545     new_instance_size -= map->inobject_properties() * kPointerSize;
6546   }
6547
6548   Handle<Map> result = RawCopy(map, new_instance_size);
6549
6550   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6551     result->set_inobject_properties(map->inobject_properties());
6552   }
6553
6554   result->set_dictionary_map(true);
6555   result->set_migration_target(false);
6556
6557 #ifdef VERIFY_HEAP
6558   if (FLAG_verify_heap) result->DictionaryMapVerify();
6559 #endif
6560
6561   return result;
6562 }
6563
6564
6565 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6566   Handle<Map> result = RawCopy(map, map->instance_size());
6567
6568   // Please note instance_type and instance_size are set when allocated.
6569   result->set_inobject_properties(map->inobject_properties());
6570   result->set_unused_property_fields(map->unused_property_fields());
6571
6572   result->ClearCodeCache(map->GetHeap());
6573   map->NotifyLeafMapLayoutChange();
6574   return result;
6575 }
6576
6577
6578 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6579                                  Handle<DescriptorArray> descriptors,
6580                                  Descriptor* descriptor) {
6581   // Sanity check. This path is only to be taken if the map owns its descriptor
6582   // array, implying that its NumberOfOwnDescriptors equals the number of
6583   // descriptors in the descriptor array.
6584   DCHECK(map->NumberOfOwnDescriptors() ==
6585          map->instance_descriptors()->number_of_descriptors());
6586
6587   Handle<Map> result = CopyDropDescriptors(map);
6588   Handle<Name> name = descriptor->GetKey();
6589
6590   // Ensure there's space for the new descriptor in the shared descriptor array.
6591   if (descriptors->NumberOfSlackDescriptors() == 0) {
6592     int old_size = descriptors->number_of_descriptors();
6593     if (old_size == 0) {
6594       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6595     } else {
6596       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
6597       EnsureDescriptorSlack(map, slack);
6598       descriptors = handle(map->instance_descriptors());
6599     }
6600   }
6601
6602   Handle<LayoutDescriptor> layout_descriptor =
6603       FLAG_unbox_double_fields
6604           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
6605           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
6606
6607   {
6608     DisallowHeapAllocation no_gc;
6609     descriptors->Append(descriptor);
6610     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6611   }
6612
6613   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6614   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6615
6616   return result;
6617 }
6618
6619
6620 #if TRACE_MAPS
6621
6622 // static
6623 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
6624   if (FLAG_trace_maps) {
6625     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
6626            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
6627     name->NameShortPrint();
6628     PrintF(" ]\n");
6629   }
6630 }
6631
6632
6633 // static
6634 void Map::TraceAllTransitions(Map* map) {
6635   Object* transitions = map->raw_transitions();
6636   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
6637   for (int i = -0; i < num_transitions; ++i) {
6638     Map* target = TransitionArray::GetTarget(transitions, i);
6639     Name* key = TransitionArray::GetKey(transitions, i);
6640     Map::TraceTransition("Transition", map, target, key);
6641     Map::TraceAllTransitions(target);
6642   }
6643 }
6644
6645 #endif  // TRACE_MAPS
6646
6647
6648 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
6649                             Handle<Name> name, SimpleTransitionFlag flag) {
6650   parent->set_owns_descriptors(false);
6651   if (parent->is_prototype_map()) {
6652     DCHECK(child->is_prototype_map());
6653 #if TRACE_MAPS
6654     Map::TraceTransition("NoTransition", *parent, *child, *name);
6655 #endif
6656   } else {
6657     TransitionArray::Insert(parent, name, child, flag);
6658 #if TRACE_MAPS
6659     Map::TraceTransition("Transition", *parent, *child, *name);
6660 #endif
6661   }
6662 }
6663
6664
6665 Handle<Map> Map::CopyReplaceDescriptors(
6666     Handle<Map> map, Handle<DescriptorArray> descriptors,
6667     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
6668     MaybeHandle<Name> maybe_name, const char* reason,
6669     SimpleTransitionFlag simple_flag) {
6670   DCHECK(descriptors->IsSortedNoDuplicates());
6671
6672   Handle<Map> result = CopyDropDescriptors(map);
6673
6674   if (!map->is_prototype_map()) {
6675     if (flag == INSERT_TRANSITION &&
6676         TransitionArray::CanHaveMoreTransitions(map)) {
6677       result->InitializeDescriptors(*descriptors, *layout_descriptor);
6678
6679       Handle<Name> name;
6680       CHECK(maybe_name.ToHandle(&name));
6681       ConnectTransition(map, result, name, simple_flag);
6682     } else {
6683       int length = descriptors->number_of_descriptors();
6684       for (int i = 0; i < length; i++) {
6685         descriptors->SetRepresentation(i, Representation::Tagged());
6686         if (descriptors->GetDetails(i).type() == DATA) {
6687           descriptors->SetValue(i, HeapType::Any());
6688         }
6689       }
6690       result->InitializeDescriptors(*descriptors,
6691                                     LayoutDescriptor::FastPointerLayout());
6692     }
6693   } else {
6694     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6695   }
6696 #if TRACE_MAPS
6697   if (FLAG_trace_maps &&
6698       // Mirror conditions above that did not call ConnectTransition().
6699       (map->is_prototype_map() ||
6700        !(flag == INSERT_TRANSITION &&
6701          TransitionArray::CanHaveMoreTransitions(map)))) {
6702     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
6703            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
6704            reason);
6705   }
6706 #endif
6707
6708   return result;
6709 }
6710
6711
6712 // Since this method is used to rewrite an existing transition tree, it can
6713 // always insert transitions without checking.
6714 Handle<Map> Map::CopyInstallDescriptors(
6715     Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
6716     Handle<LayoutDescriptor> full_layout_descriptor) {
6717   DCHECK(descriptors->IsSortedNoDuplicates());
6718
6719   Handle<Map> result = CopyDropDescriptors(map);
6720
6721   result->set_instance_descriptors(*descriptors);
6722   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6723
6724   int unused_property_fields = map->unused_property_fields();
6725   PropertyDetails details = descriptors->GetDetails(new_descriptor);
6726   if (details.location() == kField) {
6727     unused_property_fields = map->unused_property_fields() - 1;
6728     if (unused_property_fields < 0) {
6729       unused_property_fields += JSObject::kFieldsAdded;
6730     }
6731   }
6732   result->set_unused_property_fields(unused_property_fields);
6733
6734   if (FLAG_unbox_double_fields) {
6735     Handle<LayoutDescriptor> layout_descriptor =
6736         LayoutDescriptor::AppendIfFastOrUseFull(map, details,
6737                                                 full_layout_descriptor);
6738     result->set_layout_descriptor(*layout_descriptor);
6739 #ifdef VERIFY_HEAP
6740     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
6741     if (FLAG_verify_heap) {
6742       CHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6743     }
6744 #else
6745     SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6746 #endif
6747     result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
6748   }
6749
6750   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6751   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6752
6753   return result;
6754 }
6755
6756
6757 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
6758                                     TransitionFlag flag) {
6759   Map* maybe_elements_transition_map = NULL;
6760   if (flag == INSERT_TRANSITION) {
6761     maybe_elements_transition_map = map->ElementsTransitionMap();
6762     DCHECK(maybe_elements_transition_map == NULL ||
6763            (maybe_elements_transition_map->elements_kind() ==
6764                 DICTIONARY_ELEMENTS &&
6765             kind == DICTIONARY_ELEMENTS));
6766     DCHECK(!IsFastElementsKind(kind) ||
6767            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
6768     DCHECK(kind != map->elements_kind());
6769   }
6770
6771   bool insert_transition = flag == INSERT_TRANSITION &&
6772                            TransitionArray::CanHaveMoreTransitions(map) &&
6773                            maybe_elements_transition_map == NULL;
6774
6775   if (insert_transition) {
6776     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
6777     new_map->set_elements_kind(kind);
6778
6779     Isolate* isolate = map->GetIsolate();
6780     Handle<Name> name = isolate->factory()->elements_transition_symbol();
6781     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6782     return new_map;
6783   }
6784
6785   // Create a new free-floating map only if we are not allowed to store it.
6786   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
6787   new_map->set_elements_kind(kind);
6788   return new_map;
6789 }
6790
6791
6792 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
6793   DCHECK(!map->is_observed());
6794
6795   Isolate* isolate = map->GetIsolate();
6796
6797   bool insert_transition =
6798       TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
6799
6800   if (insert_transition) {
6801     Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
6802     new_map->set_is_observed();
6803
6804     Handle<Name> name = isolate->factory()->observed_symbol();
6805     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6806     return new_map;
6807   }
6808
6809   // Create a new free-floating map only if we are not allowed to store it.
6810   Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
6811   new_map->set_is_observed();
6812   return new_map;
6813 }
6814
6815
6816 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
6817   DCHECK(!map->is_prototype_map());
6818   Handle<Map> new_map = CopyDropDescriptors(map);
6819
6820   if (map->owns_descriptors()) {
6821     // In case the map owned its own descriptors, share the descriptors and
6822     // transfer ownership to the new map.
6823     // The properties did not change, so reuse descriptors.
6824     new_map->InitializeDescriptors(map->instance_descriptors(),
6825                                    map->GetLayoutDescriptor());
6826   } else {
6827     // In case the map did not own its own descriptors, a split is forced by
6828     // copying the map; creating a new descriptor array cell.
6829     Handle<DescriptorArray> descriptors(map->instance_descriptors());
6830     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6831     Handle<DescriptorArray> new_descriptors =
6832         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6833     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6834                                                    map->GetIsolate());
6835     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
6836   }
6837
6838 #if TRACE_MAPS
6839   if (FLAG_trace_maps) {
6840     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
6841            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
6842            reason);
6843   }
6844 #endif
6845
6846   return new_map;
6847 }
6848
6849
6850 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
6851   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6852   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6853   Handle<DescriptorArray> new_descriptors =
6854       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6855   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6856                                                  map->GetIsolate());
6857   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
6858                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
6859                                 SPECIAL_TRANSITION);
6860 }
6861
6862
6863 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
6864   Handle<Map> copy =
6865       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
6866
6867   // Check that we do not overflow the instance size when adding the extra
6868   // inobject properties. If the instance size overflows, we allocate as many
6869   // properties as we can as inobject properties.
6870   int max_extra_properties =
6871       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
6872
6873   if (inobject_properties > max_extra_properties) {
6874     inobject_properties = max_extra_properties;
6875   }
6876
6877   int new_instance_size =
6878       JSObject::kHeaderSize + kPointerSize * inobject_properties;
6879
6880   // Adjust the map with the extra inobject properties.
6881   copy->set_inobject_properties(inobject_properties);
6882   copy->set_unused_property_fields(inobject_properties);
6883   copy->set_instance_size(new_instance_size);
6884   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
6885   return copy;
6886 }
6887
6888
6889 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
6890                                           PropertyAttributes attrs_to_add,
6891                                           Handle<Symbol> transition_marker,
6892                                           const char* reason) {
6893   int num_descriptors = map->NumberOfOwnDescriptors();
6894   Isolate* isolate = map->GetIsolate();
6895   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
6896       handle(map->instance_descriptors(), isolate), num_descriptors,
6897       attrs_to_add);
6898   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6899                                                  isolate);
6900   Handle<Map> new_map = CopyReplaceDescriptors(
6901       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
6902       transition_marker, reason, SPECIAL_TRANSITION);
6903   new_map->set_is_extensible(false);
6904   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6905   return new_map;
6906 }
6907
6908
6909 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) {
6910   DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
6911   DCHECK(map->IsJSProxyMap());
6912
6913   Isolate* isolate = map->GetIsolate();
6914
6915   // Allocate fresh map.
6916   // TODO(rossberg): Once we optimize proxies, cache these maps.
6917   Handle<Map> new_map = isolate->factory()->NewMap(type, size);
6918
6919   Handle<Object> prototype(map->prototype(), isolate);
6920   Map::SetPrototype(new_map, prototype);
6921
6922   map->NotifyLeafMapLayoutChange();
6923
6924   return new_map;
6925 }
6926
6927
6928 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
6929   PropertyDetails details = GetDetails(descriptor);
6930   switch (details.type()) {
6931     case DATA:
6932       return value->FitsRepresentation(details.representation()) &&
6933              GetFieldType(descriptor)->NowContains(value);
6934
6935     case DATA_CONSTANT:
6936       DCHECK(GetConstant(descriptor) != value ||
6937              value->FitsRepresentation(details.representation()));
6938       return GetConstant(descriptor) == value;
6939
6940     case ACCESSOR:
6941     case ACCESSOR_CONSTANT:
6942       return false;
6943   }
6944
6945   UNREACHABLE();
6946   return false;
6947 }
6948
6949
6950 // static
6951 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
6952                                         Handle<Object> value) {
6953   // Dictionaries can store any property value.
6954   if (map->is_dictionary_map()) return map;
6955
6956   // Migrate to the newest map before storing the property.
6957   map = Update(map);
6958
6959   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6960
6961   if (descriptors->CanHoldValue(descriptor, *value)) return map;
6962
6963   Isolate* isolate = map->GetIsolate();
6964   PropertyAttributes attributes =
6965       descriptors->GetDetails(descriptor).attributes();
6966   Representation representation = value->OptimalRepresentation();
6967   Handle<HeapType> type = value->OptimalType(isolate, representation);
6968
6969   return ReconfigureProperty(map, descriptor, kData, attributes, representation,
6970                              type, FORCE_FIELD);
6971 }
6972
6973
6974 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
6975                                           Handle<Object> value,
6976                                           PropertyAttributes attributes,
6977                                           StoreFromKeyed store_mode) {
6978   // Dictionary maps can always have additional data properties.
6979   if (map->is_dictionary_map()) return map;
6980
6981   // Migrate to the newest map before storing the property.
6982   map = Update(map);
6983
6984   Map* maybe_transition =
6985       TransitionArray::SearchTransition(*map, kData, *name, attributes);
6986   if (maybe_transition != NULL) {
6987     Handle<Map> transition(maybe_transition);
6988     int descriptor = transition->LastAdded();
6989
6990     DCHECK_EQ(attributes, transition->instance_descriptors()
6991                               ->GetDetails(descriptor)
6992                               .attributes());
6993
6994     return Map::PrepareForDataProperty(transition, descriptor, value);
6995   }
6996
6997   TransitionFlag flag = INSERT_TRANSITION;
6998   MaybeHandle<Map> maybe_map;
6999   if (value->IsJSFunction()) {
7000     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7001   } else if (!map->TooManyFastProperties(store_mode)) {
7002     Isolate* isolate = name->GetIsolate();
7003     Representation representation = value->OptimalRepresentation();
7004     Handle<HeapType> type = value->OptimalType(isolate, representation);
7005     maybe_map =
7006         Map::CopyWithField(map, name, type, attributes, representation, flag);
7007   }
7008
7009   Handle<Map> result;
7010   if (!maybe_map.ToHandle(&result)) {
7011 #if TRACE_MAPS
7012     if (FLAG_trace_maps) {
7013       Vector<char> name_buffer = Vector<char>::New(100);
7014       name->NameShortPrint(name_buffer);
7015       Vector<char> buffer = Vector<char>::New(128);
7016       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
7017       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
7018     }
7019 #endif
7020     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
7021                           "TooManyFastProperties");
7022   }
7023
7024   return result;
7025 }
7026
7027
7028 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
7029                                              PropertyKind kind,
7030                                              PropertyAttributes attributes) {
7031   // Dictionaries have to be reconfigured in-place.
7032   DCHECK(!map->is_dictionary_map());
7033
7034   if (!map->GetBackPointer()->IsMap()) {
7035     // There is no benefit from reconstructing transition tree for maps without
7036     // back pointers.
7037     return CopyGeneralizeAllRepresentations(
7038         map, descriptor, FORCE_FIELD, kind, attributes,
7039         "GenAll_AttributesMismatchProtoMap");
7040   }
7041
7042   if (FLAG_trace_generalization) {
7043     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
7044   }
7045
7046   Isolate* isolate = map->GetIsolate();
7047   Handle<Map> new_map = ReconfigureProperty(
7048       map, descriptor, kind, attributes, Representation::None(),
7049       HeapType::None(isolate), FORCE_FIELD);
7050   return new_map;
7051 }
7052
7053
7054 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
7055                                               Handle<Name> name,
7056                                               AccessorComponent component,
7057                                               Handle<Object> accessor,
7058                                               PropertyAttributes attributes) {
7059   Isolate* isolate = name->GetIsolate();
7060
7061   // Dictionary maps can always have additional data properties.
7062   if (map->is_dictionary_map()) return map;
7063
7064   // Migrate to the newest map before transitioning to the new property.
7065   map = Update(map);
7066
7067   PropertyNormalizationMode mode = map->is_prototype_map()
7068                                        ? KEEP_INOBJECT_PROPERTIES
7069                                        : CLEAR_INOBJECT_PROPERTIES;
7070
7071   Map* maybe_transition =
7072       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
7073   if (maybe_transition != NULL) {
7074     Handle<Map> transition(maybe_transition, isolate);
7075     DescriptorArray* descriptors = transition->instance_descriptors();
7076     int descriptor = transition->LastAdded();
7077     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7078
7079     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7080     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7081
7082     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7083     if (!maybe_pair->IsAccessorPair()) {
7084       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
7085     }
7086
7087     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
7088     if (pair->get(component) != *accessor) {
7089       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
7090     }
7091
7092     return transition;
7093   }
7094
7095   Handle<AccessorPair> pair;
7096   DescriptorArray* old_descriptors = map->instance_descriptors();
7097   int descriptor = old_descriptors->SearchWithCache(*name, *map);
7098   if (descriptor != DescriptorArray::kNotFound) {
7099     if (descriptor != map->LastAdded()) {
7100       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
7101     }
7102     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
7103     if (old_details.type() != ACCESSOR_CONSTANT) {
7104       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
7105     }
7106
7107     if (old_details.attributes() != attributes) {
7108       return Map::Normalize(map, mode, "AccessorsWithAttributes");
7109     }
7110
7111     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
7112     if (!maybe_pair->IsAccessorPair()) {
7113       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
7114     }
7115
7116     Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
7117     if (current == *accessor) return map;
7118
7119     if (!current->IsTheHole()) {
7120       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
7121     }
7122
7123     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
7124   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
7125              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
7126     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
7127   } else {
7128     pair = isolate->factory()->NewAccessorPair();
7129   }
7130
7131   pair->set(component, *accessor);
7132   TransitionFlag flag = INSERT_TRANSITION;
7133   AccessorConstantDescriptor new_desc(name, pair, attributes);
7134   return Map::CopyInsertDescriptor(map, &new_desc, flag);
7135 }
7136
7137
7138 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7139                                    Descriptor* descriptor,
7140                                    TransitionFlag flag) {
7141   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7142
7143   // Ensure the key is unique.
7144   descriptor->KeyToUniqueName();
7145
7146   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
7147       TransitionArray::CanHaveMoreTransitions(map)) {
7148     return ShareDescriptor(map, descriptors, descriptor);
7149   }
7150
7151   int nof = map->NumberOfOwnDescriptors();
7152   Handle<DescriptorArray> new_descriptors =
7153       DescriptorArray::CopyUpTo(descriptors, nof, 1);
7154   new_descriptors->Append(descriptor);
7155
7156   Handle<LayoutDescriptor> new_layout_descriptor =
7157       FLAG_unbox_double_fields
7158           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
7159           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
7160
7161   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7162                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
7163                                 SIMPLE_PROPERTY_TRANSITION);
7164 }
7165
7166
7167 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7168                                       Descriptor* descriptor,
7169                                       TransitionFlag flag) {
7170   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7171
7172   // Ensure the key is unique.
7173   descriptor->KeyToUniqueName();
7174
7175   // We replace the key if it is already present.
7176   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7177   if (index != DescriptorArray::kNotFound) {
7178     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7179   }
7180   return CopyAddDescriptor(map, descriptor, flag);
7181 }
7182
7183
7184 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7185     Handle<DescriptorArray> desc,
7186     int enumeration_index,
7187     int slack) {
7188   return DescriptorArray::CopyUpToAddAttributes(
7189       desc, enumeration_index, NONE, slack);
7190 }
7191
7192
7193 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7194     Handle<DescriptorArray> desc,
7195     int enumeration_index,
7196     PropertyAttributes attributes,
7197     int slack) {
7198   if (enumeration_index + slack == 0) {
7199     return desc->GetIsolate()->factory()->empty_descriptor_array();
7200   }
7201
7202   int size = enumeration_index;
7203
7204   Handle<DescriptorArray> descriptors =
7205       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7206   DescriptorArray::WhitenessWitness witness(*descriptors);
7207
7208   if (attributes != NONE) {
7209     for (int i = 0; i < size; ++i) {
7210       Object* value = desc->GetValue(i);
7211       Name* key = desc->GetKey(i);
7212       PropertyDetails details = desc->GetDetails(i);
7213       // Bulk attribute changes never affect private properties.
7214       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7215         int mask = DONT_DELETE | DONT_ENUM;
7216         // READ_ONLY is an invalid attribute for JS setters/getters.
7217         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
7218           mask |= READ_ONLY;
7219         }
7220         details = details.CopyAddAttributes(
7221             static_cast<PropertyAttributes>(attributes & mask));
7222       }
7223       Descriptor inner_desc(
7224           handle(key), handle(value, desc->GetIsolate()), details);
7225       descriptors->Set(i, &inner_desc, witness);
7226     }
7227   } else {
7228     for (int i = 0; i < size; ++i) {
7229       descriptors->CopyFrom(i, *desc, witness);
7230     }
7231   }
7232
7233   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7234
7235   return descriptors;
7236 }
7237
7238
7239 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7240                                        Handle<DescriptorArray> descriptors,
7241                                        Descriptor* descriptor,
7242                                        int insertion_index,
7243                                        TransitionFlag flag) {
7244   // Ensure the key is unique.
7245   descriptor->KeyToUniqueName();
7246
7247   Handle<Name> key = descriptor->GetKey();
7248   DCHECK(*key == descriptors->GetKey(insertion_index));
7249
7250   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7251       descriptors, map->NumberOfOwnDescriptors());
7252
7253   new_descriptors->Replace(insertion_index, descriptor);
7254   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
7255       map, new_descriptors, new_descriptors->number_of_descriptors());
7256
7257   SimpleTransitionFlag simple_flag =
7258       (insertion_index == descriptors->number_of_descriptors() - 1)
7259           ? SIMPLE_PROPERTY_TRANSITION
7260           : PROPERTY_TRANSITION;
7261   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7262                                 flag, key, "CopyReplaceDescriptor",
7263                                 simple_flag);
7264 }
7265
7266
7267 void Map::UpdateCodeCache(Handle<Map> map,
7268                           Handle<Name> name,
7269                           Handle<Code> code) {
7270   Isolate* isolate = map->GetIsolate();
7271   HandleScope scope(isolate);
7272   // Allocate the code cache if not present.
7273   if (map->code_cache()->IsFixedArray()) {
7274     Handle<Object> result = isolate->factory()->NewCodeCache();
7275     map->set_code_cache(*result);
7276   }
7277
7278   // Update the code cache.
7279   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7280   CodeCache::Update(code_cache, name, code);
7281 }
7282
7283
7284 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7285   // Do a lookup if a code cache exists.
7286   if (!code_cache()->IsFixedArray()) {
7287     return CodeCache::cast(code_cache())->Lookup(name, flags);
7288   } else {
7289     return GetHeap()->undefined_value();
7290   }
7291 }
7292
7293
7294 int Map::IndexInCodeCache(Object* name, Code* code) {
7295   // Get the internal index if a code cache exists.
7296   if (!code_cache()->IsFixedArray()) {
7297     return CodeCache::cast(code_cache())->GetIndex(name, code);
7298   }
7299   return -1;
7300 }
7301
7302
7303 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7304   // No GC is supposed to happen between a call to IndexInCodeCache and
7305   // RemoveFromCodeCache so the code cache must be there.
7306   DCHECK(!code_cache()->IsFixedArray());
7307   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7308 }
7309
7310
7311 void CodeCache::Update(
7312     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7313   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7314   // a large number and therefore they need to go into a hash table. They are
7315   // used to load global properties from cells.
7316   if (code->type() == Code::NORMAL) {
7317     // Make sure that a hash table is allocated for the normal load code cache.
7318     if (code_cache->normal_type_cache()->IsUndefined()) {
7319       Handle<Object> result =
7320           CodeCacheHashTable::New(code_cache->GetIsolate(),
7321                                   CodeCacheHashTable::kInitialSize);
7322       code_cache->set_normal_type_cache(*result);
7323     }
7324     UpdateNormalTypeCache(code_cache, name, code);
7325   } else {
7326     DCHECK(code_cache->default_cache()->IsFixedArray());
7327     UpdateDefaultCache(code_cache, name, code);
7328   }
7329 }
7330
7331
7332 void CodeCache::UpdateDefaultCache(
7333     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7334   // When updating the default code cache we disregard the type encoded in the
7335   // flags. This allows call constant stubs to overwrite call field
7336   // stubs, etc.
7337   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7338
7339   // First check whether we can update existing code cache without
7340   // extending it.
7341   Handle<FixedArray> cache = handle(code_cache->default_cache());
7342   int length = cache->length();
7343   {
7344     DisallowHeapAllocation no_alloc;
7345     int deleted_index = -1;
7346     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7347       Object* key = cache->get(i);
7348       if (key->IsNull()) {
7349         if (deleted_index < 0) deleted_index = i;
7350         continue;
7351       }
7352       if (key->IsUndefined()) {
7353         if (deleted_index >= 0) i = deleted_index;
7354         cache->set(i + kCodeCacheEntryNameOffset, *name);
7355         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7356         return;
7357       }
7358       if (name->Equals(Name::cast(key))) {
7359         Code::Flags found =
7360             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7361         if (Code::RemoveTypeFromFlags(found) == flags) {
7362           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7363           return;
7364         }
7365       }
7366     }
7367
7368     // Reached the end of the code cache.  If there were deleted
7369     // elements, reuse the space for the first of them.
7370     if (deleted_index >= 0) {
7371       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7372       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7373       return;
7374     }
7375   }
7376
7377   // Extend the code cache with some new entries (at least one). Must be a
7378   // multiple of the entry size.
7379   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7380   new_length = new_length - new_length % kCodeCacheEntrySize;
7381   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7382   cache = FixedArray::CopySize(cache, new_length);
7383
7384   // Add the (name, code) pair to the new cache.
7385   cache->set(length + kCodeCacheEntryNameOffset, *name);
7386   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7387   code_cache->set_default_cache(*cache);
7388 }
7389
7390
7391 void CodeCache::UpdateNormalTypeCache(
7392     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7393   // Adding a new entry can cause a new cache to be allocated.
7394   Handle<CodeCacheHashTable> cache(
7395       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7396   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7397   code_cache->set_normal_type_cache(*new_cache);
7398 }
7399
7400
7401 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7402   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7403   if (result->IsCode()) {
7404     if (Code::cast(result)->flags() == flags) return result;
7405     return GetHeap()->undefined_value();
7406   }
7407   return LookupNormalTypeCache(name, flags);
7408 }
7409
7410
7411 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7412   FixedArray* cache = default_cache();
7413   int length = cache->length();
7414   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7415     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7416     // Skip deleted elements.
7417     if (key->IsNull()) continue;
7418     if (key->IsUndefined()) return key;
7419     if (name->Equals(Name::cast(key))) {
7420       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7421       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7422         return code;
7423       }
7424     }
7425   }
7426   return GetHeap()->undefined_value();
7427 }
7428
7429
7430 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7431   if (!normal_type_cache()->IsUndefined()) {
7432     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7433     return cache->Lookup(name, flags);
7434   } else {
7435     return GetHeap()->undefined_value();
7436   }
7437 }
7438
7439
7440 int CodeCache::GetIndex(Object* name, Code* code) {
7441   if (code->type() == Code::NORMAL) {
7442     if (normal_type_cache()->IsUndefined()) return -1;
7443     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7444     return cache->GetIndex(Name::cast(name), code->flags());
7445   }
7446
7447   FixedArray* array = default_cache();
7448   int len = array->length();
7449   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7450     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7451   }
7452   return -1;
7453 }
7454
7455
7456 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7457   if (code->type() == Code::NORMAL) {
7458     DCHECK(!normal_type_cache()->IsUndefined());
7459     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7460     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7461     cache->RemoveByIndex(index);
7462   } else {
7463     FixedArray* array = default_cache();
7464     DCHECK(array->length() >= index && array->get(index)->IsCode());
7465     // Use null instead of undefined for deleted elements to distinguish
7466     // deleted elements from unused elements.  This distinction is used
7467     // when looking up in the cache and when updating the cache.
7468     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7469     array->set_null(index - 1);  // Name.
7470     array->set_null(index);  // Code.
7471   }
7472 }
7473
7474
7475 // The key in the code cache hash table consists of the property name and the
7476 // code object. The actual match is on the name and the code flags. If a key
7477 // is created using the flags and not a code object it can only be used for
7478 // lookup not to create a new entry.
7479 class CodeCacheHashTableKey : public HashTableKey {
7480  public:
7481   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7482       : name_(name), flags_(flags), code_() { }
7483
7484   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7485       : name_(name), flags_(code->flags()), code_(code) { }
7486
7487   bool IsMatch(Object* other) override {
7488     if (!other->IsFixedArray()) return false;
7489     FixedArray* pair = FixedArray::cast(other);
7490     Name* name = Name::cast(pair->get(0));
7491     Code::Flags flags = Code::cast(pair->get(1))->flags();
7492     if (flags != flags_) {
7493       return false;
7494     }
7495     return name_->Equals(name);
7496   }
7497
7498   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7499     return name->Hash() ^ flags;
7500   }
7501
7502   uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
7503
7504   uint32_t HashForObject(Object* obj) override {
7505     FixedArray* pair = FixedArray::cast(obj);
7506     Name* name = Name::cast(pair->get(0));
7507     Code* code = Code::cast(pair->get(1));
7508     return NameFlagsHashHelper(name, code->flags());
7509   }
7510
7511   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7512     Handle<Code> code = code_.ToHandleChecked();
7513     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7514     pair->set(0, *name_);
7515     pair->set(1, *code);
7516     return pair;
7517   }
7518
7519  private:
7520   Handle<Name> name_;
7521   Code::Flags flags_;
7522   // TODO(jkummerow): We should be able to get by without this.
7523   MaybeHandle<Code> code_;
7524 };
7525
7526
7527 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7528   DisallowHeapAllocation no_alloc;
7529   CodeCacheHashTableKey key(handle(name), flags);
7530   int entry = FindEntry(&key);
7531   if (entry == kNotFound) return GetHeap()->undefined_value();
7532   return get(EntryToIndex(entry) + 1);
7533 }
7534
7535
7536 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
7537     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
7538   CodeCacheHashTableKey key(name, code);
7539
7540   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7541
7542   int entry = new_cache->FindInsertionEntry(key.Hash());
7543   Handle<Object> k = key.AsHandle(cache->GetIsolate());
7544
7545   new_cache->set(EntryToIndex(entry), *k);
7546   new_cache->set(EntryToIndex(entry) + 1, *code);
7547   new_cache->ElementAdded();
7548   return new_cache;
7549 }
7550
7551
7552 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7553   DisallowHeapAllocation no_alloc;
7554   CodeCacheHashTableKey key(handle(name), flags);
7555   int entry = FindEntry(&key);
7556   return (entry == kNotFound) ? -1 : entry;
7557 }
7558
7559
7560 void CodeCacheHashTable::RemoveByIndex(int index) {
7561   DCHECK(index >= 0);
7562   Heap* heap = GetHeap();
7563   set(EntryToIndex(index), heap->the_hole_value());
7564   set(EntryToIndex(index) + 1, heap->the_hole_value());
7565   ElementRemoved();
7566 }
7567
7568
7569 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
7570                                   MapHandleList* maps,
7571                                   Code::Flags flags,
7572                                   Handle<Code> code) {
7573   Isolate* isolate = code_cache->GetIsolate();
7574   if (code_cache->cache()->IsUndefined()) {
7575     Handle<PolymorphicCodeCacheHashTable> result =
7576         PolymorphicCodeCacheHashTable::New(
7577             isolate,
7578             PolymorphicCodeCacheHashTable::kInitialSize);
7579     code_cache->set_cache(*result);
7580   } else {
7581     // This entry shouldn't be contained in the cache yet.
7582     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7583                ->Lookup(maps, flags)->IsUndefined());
7584   }
7585   Handle<PolymorphicCodeCacheHashTable> hash_table =
7586       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7587   Handle<PolymorphicCodeCacheHashTable> new_cache =
7588       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7589   code_cache->set_cache(*new_cache);
7590 }
7591
7592
7593 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7594                                             Code::Flags flags) {
7595   if (!cache()->IsUndefined()) {
7596     PolymorphicCodeCacheHashTable* hash_table =
7597         PolymorphicCodeCacheHashTable::cast(cache());
7598     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7599   } else {
7600     return GetIsolate()->factory()->undefined_value();
7601   }
7602 }
7603
7604
7605 // Despite their name, object of this class are not stored in the actual
7606 // hash table; instead they're temporarily used for lookups. It is therefore
7607 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7608 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7609  public:
7610   // Callers must ensure that |maps| outlives the newly constructed object.
7611   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7612       : maps_(maps),
7613         code_flags_(code_flags) {}
7614
7615   bool IsMatch(Object* other) override {
7616     MapHandleList other_maps(kDefaultListAllocationSize);
7617     int other_flags;
7618     FromObject(other, &other_flags, &other_maps);
7619     if (code_flags_ != other_flags) return false;
7620     if (maps_->length() != other_maps.length()) return false;
7621     // Compare just the hashes first because it's faster.
7622     int this_hash = MapsHashHelper(maps_, code_flags_);
7623     int other_hash = MapsHashHelper(&other_maps, other_flags);
7624     if (this_hash != other_hash) return false;
7625
7626     // Full comparison: for each map in maps_, look for an equivalent map in
7627     // other_maps. This implementation is slow, but probably good enough for
7628     // now because the lists are short (<= 4 elements currently).
7629     for (int i = 0; i < maps_->length(); ++i) {
7630       bool match_found = false;
7631       for (int j = 0; j < other_maps.length(); ++j) {
7632         if (*(maps_->at(i)) == *(other_maps.at(j))) {
7633           match_found = true;
7634           break;
7635         }
7636       }
7637       if (!match_found) return false;
7638     }
7639     return true;
7640   }
7641
7642   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7643     uint32_t hash = code_flags;
7644     for (int i = 0; i < maps->length(); ++i) {
7645       hash ^= maps->at(i)->Hash();
7646     }
7647     return hash;
7648   }
7649
7650   uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
7651
7652   uint32_t HashForObject(Object* obj) override {
7653     MapHandleList other_maps(kDefaultListAllocationSize);
7654     int other_flags;
7655     FromObject(obj, &other_flags, &other_maps);
7656     return MapsHashHelper(&other_maps, other_flags);
7657   }
7658
7659   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7660     // The maps in |maps_| must be copied to a newly allocated FixedArray,
7661     // both because the referenced MapList is short-lived, and because C++
7662     // objects can't be stored in the heap anyway.
7663     Handle<FixedArray> list =
7664         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
7665     list->set(0, Smi::FromInt(code_flags_));
7666     for (int i = 0; i < maps_->length(); ++i) {
7667       list->set(i + 1, *maps_->at(i));
7668     }
7669     return list;
7670   }
7671
7672  private:
7673   static MapHandleList* FromObject(Object* obj,
7674                                    int* code_flags,
7675                                    MapHandleList* maps) {
7676     FixedArray* list = FixedArray::cast(obj);
7677     maps->Rewind(0);
7678     *code_flags = Smi::cast(list->get(0))->value();
7679     for (int i = 1; i < list->length(); ++i) {
7680       maps->Add(Handle<Map>(Map::cast(list->get(i))));
7681     }
7682     return maps;
7683   }
7684
7685   MapHandleList* maps_;  // weak.
7686   int code_flags_;
7687   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7688 };
7689
7690
7691 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
7692                                               int code_kind) {
7693   DisallowHeapAllocation no_alloc;
7694   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7695   int entry = FindEntry(&key);
7696   if (entry == kNotFound) return GetHeap()->undefined_value();
7697   return get(EntryToIndex(entry) + 1);
7698 }
7699
7700
7701 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
7702       Handle<PolymorphicCodeCacheHashTable> hash_table,
7703       MapHandleList* maps,
7704       int code_kind,
7705       Handle<Code> code) {
7706   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7707   Handle<PolymorphicCodeCacheHashTable> cache =
7708       EnsureCapacity(hash_table, 1, &key);
7709   int entry = cache->FindInsertionEntry(key.Hash());
7710
7711   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
7712   cache->set(EntryToIndex(entry), *obj);
7713   cache->set(EntryToIndex(entry) + 1, *code);
7714   cache->ElementAdded();
7715   return cache;
7716 }
7717
7718
7719 void FixedArray::Shrink(int new_length) {
7720   DCHECK(0 <= new_length && new_length <= length());
7721   if (new_length < length()) {
7722     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
7723         this, length() - new_length);
7724   }
7725 }
7726
7727
7728 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
7729     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
7730   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
7731   ElementsAccessor* accessor = array->GetElementsAccessor();
7732   Handle<FixedArray> result =
7733       accessor->AddElementsToFixedArray(array, content, filter);
7734
7735 #ifdef ENABLE_SLOW_DCHECKS
7736   if (FLAG_enable_slow_asserts) {
7737     DisallowHeapAllocation no_allocation;
7738     for (int i = 0; i < result->length(); i++) {
7739       Object* current = result->get(i);
7740       DCHECK(current->IsNumber() || current->IsName());
7741     }
7742   }
7743 #endif
7744   return result;
7745 }
7746
7747
7748 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
7749                                                 Handle<FixedArray> second) {
7750   if (second->length() == 0) return first;
7751   if (first->length() == 0) return second;
7752   Isolate* isolate = first->GetIsolate();
7753   Handle<FixedArray> result =
7754       isolate->factory()->NewFixedArray(first->length() + second->length());
7755   for (int i = 0; i < first->length(); i++) {
7756     result->set(i, first->get(i));
7757   }
7758   int pos = first->length();
7759   for (int j = 0; j < second->length(); j++) {
7760     Object* current = second->get(j);
7761     int i;
7762     for (i = 0; i < first->length(); i++) {
7763       if (current->KeyEquals(first->get(i))) break;
7764     }
7765     if (i == first->length()) {
7766       result->set(pos++, current);
7767     }
7768   }
7769
7770   result->Shrink(pos);
7771   return result;
7772 }
7773
7774
7775 Handle<FixedArray> FixedArray::CopySize(
7776     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
7777   Isolate* isolate = array->GetIsolate();
7778   if (new_length == 0) return isolate->factory()->empty_fixed_array();
7779   Handle<FixedArray> result =
7780       isolate->factory()->NewFixedArray(new_length, pretenure);
7781   // Copy the content
7782   DisallowHeapAllocation no_gc;
7783   int len = array->length();
7784   if (new_length < len) len = new_length;
7785   // We are taking the map from the old fixed array so the map is sure to
7786   // be an immortal immutable object.
7787   result->set_map_no_write_barrier(array->map());
7788   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7789   for (int i = 0; i < len; i++) {
7790     result->set(i, array->get(i), mode);
7791   }
7792   return result;
7793 }
7794
7795
7796 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7797   DisallowHeapAllocation no_gc;
7798   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7799   for (int index = 0; index < len; index++) {
7800     dest->set(dest_pos+index, get(pos+index), mode);
7801   }
7802 }
7803
7804
7805 #ifdef DEBUG
7806 bool FixedArray::IsEqualTo(FixedArray* other) {
7807   if (length() != other->length()) return false;
7808   for (int i = 0 ; i < length(); ++i) {
7809     if (get(i) != other->get(i)) return false;
7810   }
7811   return true;
7812 }
7813 #endif
7814
7815
7816 // static
7817 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
7818                          Handle<HeapObject> value) {
7819   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
7820   Handle<WeakCell> cell =
7821       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
7822                      : array->GetIsolate()->factory()->NewWeakCell(value);
7823   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
7824   if (FLAG_trace_weak_arrays) {
7825     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
7826   }
7827   array->set_last_used_index(index);
7828 }
7829
7830
7831 // static
7832 Handle<WeakFixedArray> WeakFixedArray::Add(
7833     Handle<Object> maybe_array, Handle<HeapObject> value,
7834     SearchForDuplicates search_for_duplicates, bool* was_present) {
7835   Handle<WeakFixedArray> array =
7836       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
7837           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
7838           : Handle<WeakFixedArray>::cast(maybe_array);
7839   if (was_present != NULL) *was_present = false;
7840   if (search_for_duplicates == kAddIfNotFound) {
7841     for (int i = 0; i < array->Length(); ++i) {
7842       if (array->Get(i) == *value) {
7843         if (was_present != NULL) *was_present = true;
7844         return array;
7845       }
7846     }
7847 #if 0  // Enable this if you want to check your search_for_duplicates flags.
7848   } else {
7849     for (int i = 0; i < array->Length(); ++i) {
7850       DCHECK_NE(*value, array->Get(i));
7851     }
7852 #endif
7853   }
7854
7855   // Try to store the new entry if there's room. Optimize for consecutive
7856   // accesses.
7857   int first_index = array->last_used_index();
7858   if (array->Length() > 0) {
7859     for (int i = first_index;;) {
7860       if (array->IsEmptySlot((i))) {
7861         WeakFixedArray::Set(array, i, value);
7862         return array;
7863       }
7864       if (FLAG_trace_weak_arrays) {
7865         PrintF("[WeakFixedArray: searching for free slot]\n");
7866       }
7867       i = (i + 1) % array->Length();
7868       if (i == first_index) break;
7869     }
7870   }
7871
7872   // No usable slot found, grow the array.
7873   int new_length =
7874       array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4;
7875   Handle<WeakFixedArray> new_array =
7876       Allocate(array->GetIsolate(), new_length, array);
7877   if (FLAG_trace_weak_arrays) {
7878     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
7879   }
7880   WeakFixedArray::Set(new_array, array->Length(), value);
7881   return new_array;
7882 }
7883
7884
7885 void WeakFixedArray::Compact() {
7886   FixedArray* array = FixedArray::cast(this);
7887   int new_length = kFirstIndex;
7888   for (int i = kFirstIndex; i < array->length(); i++) {
7889     Object* element = array->get(i);
7890     if (element->IsSmi()) continue;
7891     if (WeakCell::cast(element)->cleared()) continue;
7892     array->set(new_length++, element);
7893   }
7894   array->Shrink(new_length);
7895   set_last_used_index(0);
7896 }
7897
7898
7899 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
7900   if (Length() == 0) return false;
7901   // Optimize for the most recently added element to be removed again.
7902   int first_index = last_used_index();
7903   for (int i = first_index;;) {
7904     if (Get(i) == *value) {
7905       Clear(i);
7906       // Users of WeakFixedArray should make sure that there are no duplicates,
7907       // they can use Add(..., kAddIfNotFound) if necessary.
7908       return true;
7909     }
7910     i = (i + 1) % Length();
7911     if (i == first_index) return false;
7912   }
7913   UNREACHABLE();
7914 }
7915
7916
7917 // static
7918 Handle<WeakFixedArray> WeakFixedArray::Allocate(
7919     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
7920   DCHECK(0 <= size);
7921   Handle<FixedArray> result =
7922       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
7923   Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
7924   if (initialize_from.is_null()) {
7925     for (int i = 0; i < result->length(); ++i) {
7926       result->set(i, Smi::FromInt(0));
7927     }
7928   } else {
7929     DCHECK(initialize_from->Length() <= size);
7930     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
7931     int target_index = kFirstIndex;
7932     for (int source_index = kFirstIndex; source_index < raw_source->length();
7933          ++source_index) {
7934       // The act of allocating might have caused entries in the source array
7935       // to be cleared. Copy only what's needed.
7936       if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
7937       result->set(target_index++, raw_source->get(source_index));
7938     }
7939     casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
7940     for (; target_index < result->length(); ++target_index) {
7941       result->set(target_index, Smi::FromInt(0));
7942     }
7943   }
7944   return casted_result;
7945 }
7946
7947
7948 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
7949                                  AddMode mode) {
7950   int length = array->Length();
7951   array = EnsureSpace(array, length + 1);
7952   if (mode == kReloadLengthAfterAllocation) {
7953     DCHECK(array->Length() <= length);
7954     length = array->Length();
7955   }
7956   array->Set(length, *obj);
7957   array->SetLength(length + 1);
7958   return array;
7959 }
7960
7961
7962 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
7963                                  Handle<Object> obj2, AddMode mode) {
7964   int length = array->Length();
7965   array = EnsureSpace(array, length + 2);
7966   if (mode == kReloadLengthAfterAllocation) {
7967     length = array->Length();
7968   }
7969   array->Set(length, *obj1);
7970   array->Set(length + 1, *obj2);
7971   array->SetLength(length + 2);
7972   return array;
7973 }
7974
7975
7976 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
7977   int capacity = array->length();
7978   bool empty = (capacity == 0);
7979   if (capacity < kFirstIndex + length) {
7980     capacity = kFirstIndex + length;
7981     capacity = capacity + Max(capacity / 2, 2);
7982     array = Handle<ArrayList>::cast(FixedArray::CopySize(array, capacity));
7983     if (empty) array->SetLength(0);
7984   }
7985   return array;
7986 }
7987
7988
7989 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
7990                                                   int number_of_descriptors,
7991                                                   int slack) {
7992   DCHECK(0 <= number_of_descriptors);
7993   Factory* factory = isolate->factory();
7994   // Do not use DescriptorArray::cast on incomplete object.
7995   int size = number_of_descriptors + slack;
7996   if (size == 0) return factory->empty_descriptor_array();
7997   // Allocate the array of keys.
7998   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
7999
8000   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8001   result->set(kEnumCacheIndex, Smi::FromInt(0));
8002   return Handle<DescriptorArray>::cast(result);
8003 }
8004
8005
8006 void DescriptorArray::ClearEnumCache() {
8007   set(kEnumCacheIndex, Smi::FromInt(0));
8008 }
8009
8010
8011 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8012   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8013   Set(index, descriptor);
8014 }
8015
8016
8017 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8018                                    FixedArray* new_cache,
8019                                    Object* new_index_cache) {
8020   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8021   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8022   DCHECK(!IsEmpty());
8023   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8024   FixedArray::cast(bridge_storage)->
8025     set(kEnumCacheBridgeCacheIndex, new_cache);
8026   FixedArray::cast(bridge_storage)->
8027     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8028   set(kEnumCacheIndex, bridge_storage);
8029 }
8030
8031
8032 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8033                                const WhitenessWitness& witness) {
8034   Object* value = src->GetValue(index);
8035   PropertyDetails details = src->GetDetails(index);
8036   Descriptor desc(handle(src->GetKey(index)),
8037                   handle(value, src->GetIsolate()),
8038                   details);
8039   Set(index, &desc, witness);
8040 }
8041
8042
8043 // We need the whiteness witness since sort will reshuffle the entries in the
8044 // descriptor array. If the descriptor array were to be black, the shuffling
8045 // would move a slot that was already recorded as pointing into an evacuation
8046 // candidate. This would result in missing updates upon evacuation.
8047 void DescriptorArray::Sort() {
8048   // In-place heap sort.
8049   int len = number_of_descriptors();
8050   // Reset sorting since the descriptor array might contain invalid pointers.
8051   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8052   // Bottom-up max-heap construction.
8053   // Index of the last node with children
8054   const int max_parent_index = (len / 2) - 1;
8055   for (int i = max_parent_index; i >= 0; --i) {
8056     int parent_index = i;
8057     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8058     while (parent_index <= max_parent_index) {
8059       int child_index = 2 * parent_index + 1;
8060       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8061       if (child_index + 1 < len) {
8062         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8063         if (right_child_hash > child_hash) {
8064           child_index++;
8065           child_hash = right_child_hash;
8066         }
8067       }
8068       if (child_hash <= parent_hash) break;
8069       SwapSortedKeys(parent_index, child_index);
8070       // Now element at child_index could be < its children.
8071       parent_index = child_index;  // parent_hash remains correct.
8072     }
8073   }
8074
8075   // Extract elements and create sorted array.
8076   for (int i = len - 1; i > 0; --i) {
8077     // Put max element at the back of the array.
8078     SwapSortedKeys(0, i);
8079     // Shift down the new top element.
8080     int parent_index = 0;
8081     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8082     const int max_parent_index = (i / 2) - 1;
8083     while (parent_index <= max_parent_index) {
8084       int child_index = parent_index * 2 + 1;
8085       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8086       if (child_index + 1 < i) {
8087         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8088         if (right_child_hash > child_hash) {
8089           child_index++;
8090           child_hash = right_child_hash;
8091         }
8092       }
8093       if (child_hash <= parent_hash) break;
8094       SwapSortedKeys(parent_index, child_index);
8095       parent_index = child_index;
8096     }
8097   }
8098   DCHECK(IsSortedNoDuplicates());
8099 }
8100
8101
8102 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8103   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8104   copy->set_getter(pair->getter());
8105   copy->set_setter(pair->setter());
8106   return copy;
8107 }
8108
8109
8110 Object* AccessorPair::GetComponent(AccessorComponent component) {
8111   Object* accessor = get(component);
8112   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8113 }
8114
8115
8116 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8117     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
8118   return Handle<DeoptimizationInputData>::cast(
8119       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
8120                                         pretenure));
8121 }
8122
8123
8124 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8125     Isolate* isolate,
8126     int number_of_deopt_points,
8127     PretenureFlag pretenure) {
8128   Handle<FixedArray> result;
8129   if (number_of_deopt_points == 0) {
8130     result = isolate->factory()->empty_fixed_array();
8131   } else {
8132     result = isolate->factory()->NewFixedArray(
8133         LengthOfFixedArray(number_of_deopt_points), pretenure);
8134   }
8135   return Handle<DeoptimizationOutputData>::cast(result);
8136 }
8137
8138
8139 int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out,
8140                               CatchPrediction* prediction_out) {
8141   int innermost_handler = -1, innermost_start = -1;
8142   for (int i = 0; i < length(); i += kRangeEntrySize) {
8143     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
8144     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
8145     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
8146     int handler_offset = HandlerOffsetField::decode(handler_field);
8147     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
8148     int stack_depth = Smi::cast(get(i + kRangeDepthIndex))->value();
8149     if (pc_offset > start_offset && pc_offset <= end_offset) {
8150       DCHECK_NE(start_offset, innermost_start);
8151       if (start_offset < innermost_start) continue;
8152       innermost_handler = handler_offset;
8153       innermost_start = start_offset;
8154       *stack_depth_out = stack_depth;
8155       if (prediction_out) *prediction_out = prediction;
8156     }
8157   }
8158   return innermost_handler;
8159 }
8160
8161
8162 // TODO(turbofan): Make sure table is sorted and use binary search.
8163 int HandlerTable::LookupReturn(int pc_offset, CatchPrediction* prediction_out) {
8164   for (int i = 0; i < length(); i += kReturnEntrySize) {
8165     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
8166     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
8167     if (pc_offset == return_offset) {
8168       if (prediction_out) {
8169         *prediction_out = HandlerPredictionField::decode(handler_field);
8170       }
8171       return HandlerOffsetField::decode(handler_field);
8172     }
8173   }
8174   return -1;
8175 }
8176
8177
8178 #ifdef DEBUG
8179 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8180   if (IsEmpty()) return other->IsEmpty();
8181   if (other->IsEmpty()) return false;
8182   if (length() != other->length()) return false;
8183   for (int i = 0; i < length(); ++i) {
8184     if (get(i) != other->get(i)) return false;
8185   }
8186   return true;
8187 }
8188 #endif
8189
8190
8191 bool String::LooksValid() {
8192   if (!GetIsolate()->heap()->Contains(this)) return false;
8193   return true;
8194 }
8195
8196
8197 String::FlatContent String::GetFlatContent() {
8198   DCHECK(!AllowHeapAllocation::IsAllowed());
8199   int length = this->length();
8200   StringShape shape(this);
8201   String* string = this;
8202   int offset = 0;
8203   if (shape.representation_tag() == kConsStringTag) {
8204     ConsString* cons = ConsString::cast(string);
8205     if (cons->second()->length() != 0) {
8206       return FlatContent();
8207     }
8208     string = cons->first();
8209     shape = StringShape(string);
8210   }
8211   if (shape.representation_tag() == kSlicedStringTag) {
8212     SlicedString* slice = SlicedString::cast(string);
8213     offset = slice->offset();
8214     string = slice->parent();
8215     shape = StringShape(string);
8216     DCHECK(shape.representation_tag() != kConsStringTag &&
8217            shape.representation_tag() != kSlicedStringTag);
8218   }
8219   if (shape.encoding_tag() == kOneByteStringTag) {
8220     const uint8_t* start;
8221     if (shape.representation_tag() == kSeqStringTag) {
8222       start = SeqOneByteString::cast(string)->GetChars();
8223     } else {
8224       start = ExternalOneByteString::cast(string)->GetChars();
8225     }
8226     return FlatContent(start + offset, length);
8227   } else {
8228     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8229     const uc16* start;
8230     if (shape.representation_tag() == kSeqStringTag) {
8231       start = SeqTwoByteString::cast(string)->GetChars();
8232     } else {
8233       start = ExternalTwoByteString::cast(string)->GetChars();
8234     }
8235     return FlatContent(start + offset, length);
8236   }
8237 }
8238
8239
8240 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8241                                                 RobustnessFlag robust_flag,
8242                                                 int offset, int length,
8243                                                 int* length_return) {
8244   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8245     return base::SmartArrayPointer<char>(NULL);
8246   }
8247   // Negative length means the to the end of the string.
8248   if (length < 0) length = kMaxInt - offset;
8249
8250   // Compute the size of the UTF-8 string. Start at the specified offset.
8251   StringCharacterStream stream(this, offset);
8252   int character_position = offset;
8253   int utf8_bytes = 0;
8254   int last = unibrow::Utf16::kNoPreviousCharacter;
8255   while (stream.HasMore() && character_position++ < offset + length) {
8256     uint16_t character = stream.GetNext();
8257     utf8_bytes += unibrow::Utf8::Length(character, last);
8258     last = character;
8259   }
8260
8261   if (length_return) {
8262     *length_return = utf8_bytes;
8263   }
8264
8265   char* result = NewArray<char>(utf8_bytes + 1);
8266
8267   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8268   stream.Reset(this, offset);
8269   character_position = offset;
8270   int utf8_byte_position = 0;
8271   last = unibrow::Utf16::kNoPreviousCharacter;
8272   while (stream.HasMore() && character_position++ < offset + length) {
8273     uint16_t character = stream.GetNext();
8274     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8275       character = ' ';
8276     }
8277     utf8_byte_position +=
8278         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8279     last = character;
8280   }
8281   result[utf8_byte_position] = 0;
8282   return base::SmartArrayPointer<char>(result);
8283 }
8284
8285
8286 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8287                                                 RobustnessFlag robust_flag,
8288                                                 int* length_return) {
8289   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8290 }
8291
8292
8293 const uc16* String::GetTwoByteData(unsigned start) {
8294   DCHECK(!IsOneByteRepresentationUnderneath());
8295   switch (StringShape(this).representation_tag()) {
8296     case kSeqStringTag:
8297       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8298     case kExternalStringTag:
8299       return ExternalTwoByteString::cast(this)->
8300         ExternalTwoByteStringGetData(start);
8301     case kSlicedStringTag: {
8302       SlicedString* slice = SlicedString::cast(this);
8303       return slice->parent()->GetTwoByteData(start + slice->offset());
8304     }
8305     case kConsStringTag:
8306       UNREACHABLE();
8307       return NULL;
8308   }
8309   UNREACHABLE();
8310   return NULL;
8311 }
8312
8313
8314 base::SmartArrayPointer<uc16> String::ToWideCString(
8315     RobustnessFlag robust_flag) {
8316   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8317     return base::SmartArrayPointer<uc16>();
8318   }
8319   StringCharacterStream stream(this);
8320
8321   uc16* result = NewArray<uc16>(length() + 1);
8322
8323   int i = 0;
8324   while (stream.HasMore()) {
8325     uint16_t character = stream.GetNext();
8326     result[i++] = character;
8327   }
8328   result[i] = 0;
8329   return base::SmartArrayPointer<uc16>(result);
8330 }
8331
8332
8333 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8334   return reinterpret_cast<uc16*>(
8335       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8336 }
8337
8338
8339 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8340   Relocatable* current = isolate->relocatable_top();
8341   while (current != NULL) {
8342     current->PostGarbageCollection();
8343     current = current->prev_;
8344   }
8345 }
8346
8347
8348 // Reserve space for statics needing saving and restoring.
8349 int Relocatable::ArchiveSpacePerThread() {
8350   return sizeof(Relocatable*);  // NOLINT
8351 }
8352
8353
8354 // Archive statics that are thread-local.
8355 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8356   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8357   isolate->set_relocatable_top(NULL);
8358   return to + ArchiveSpacePerThread();
8359 }
8360
8361
8362 // Restore statics that are thread-local.
8363 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8364   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8365   return from + ArchiveSpacePerThread();
8366 }
8367
8368
8369 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8370   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8371   Iterate(v, top);
8372   return thread_storage + ArchiveSpacePerThread();
8373 }
8374
8375
8376 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8377   Iterate(v, isolate->relocatable_top());
8378 }
8379
8380
8381 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8382   Relocatable* current = top;
8383   while (current != NULL) {
8384     current->IterateInstance(v);
8385     current = current->prev_;
8386   }
8387 }
8388
8389
8390 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8391     : Relocatable(isolate),
8392       str_(str.location()),
8393       length_(str->length()) {
8394   PostGarbageCollection();
8395 }
8396
8397
8398 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8399     : Relocatable(isolate),
8400       str_(0),
8401       is_one_byte_(true),
8402       length_(input.length()),
8403       start_(input.start()) {}
8404
8405
8406 void FlatStringReader::PostGarbageCollection() {
8407   if (str_ == NULL) return;
8408   Handle<String> str(str_);
8409   DCHECK(str->IsFlat());
8410   DisallowHeapAllocation no_gc;
8411   // This does not actually prevent the vector from being relocated later.
8412   String::FlatContent content = str->GetFlatContent();
8413   DCHECK(content.IsFlat());
8414   is_one_byte_ = content.IsOneByte();
8415   if (is_one_byte_) {
8416     start_ = content.ToOneByteVector().start();
8417   } else {
8418     start_ = content.ToUC16Vector().start();
8419   }
8420 }
8421
8422
8423 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
8424   DCHECK(cons_string != NULL);
8425   root_ = cons_string;
8426   consumed_ = offset;
8427   // Force stack blown condition to trigger restart.
8428   depth_ = 1;
8429   maximum_depth_ = kStackSize + depth_;
8430   DCHECK(StackBlown());
8431 }
8432
8433
8434 String* ConsStringIterator::Continue(int* offset_out) {
8435   DCHECK(depth_ != 0);
8436   DCHECK_EQ(0, *offset_out);
8437   bool blew_stack = StackBlown();
8438   String* string = NULL;
8439   // Get the next leaf if there is one.
8440   if (!blew_stack) string = NextLeaf(&blew_stack);
8441   // Restart search from root.
8442   if (blew_stack) {
8443     DCHECK(string == NULL);
8444     string = Search(offset_out);
8445   }
8446   // Ensure future calls return null immediately.
8447   if (string == NULL) Reset(NULL);
8448   return string;
8449 }
8450
8451
8452 String* ConsStringIterator::Search(int* offset_out) {
8453   ConsString* cons_string = root_;
8454   // Reset the stack, pushing the root string.
8455   depth_ = 1;
8456   maximum_depth_ = 1;
8457   frames_[0] = cons_string;
8458   const int consumed = consumed_;
8459   int offset = 0;
8460   while (true) {
8461     // Loop until the string is found which contains the target offset.
8462     String* string = cons_string->first();
8463     int length = string->length();
8464     int32_t type;
8465     if (consumed < offset + length) {
8466       // Target offset is in the left branch.
8467       // Keep going if we're still in a ConString.
8468       type = string->map()->instance_type();
8469       if ((type & kStringRepresentationMask) == kConsStringTag) {
8470         cons_string = ConsString::cast(string);
8471         PushLeft(cons_string);
8472         continue;
8473       }
8474       // Tell the stack we're done descending.
8475       AdjustMaximumDepth();
8476     } else {
8477       // Descend right.
8478       // Update progress through the string.
8479       offset += length;
8480       // Keep going if we're still in a ConString.
8481       string = cons_string->second();
8482       type = string->map()->instance_type();
8483       if ((type & kStringRepresentationMask) == kConsStringTag) {
8484         cons_string = ConsString::cast(string);
8485         PushRight(cons_string);
8486         continue;
8487       }
8488       // Need this to be updated for the current string.
8489       length = string->length();
8490       // Account for the possibility of an empty right leaf.
8491       // This happens only if we have asked for an offset outside the string.
8492       if (length == 0) {
8493         // Reset so future operations will return null immediately.
8494         Reset(NULL);
8495         return NULL;
8496       }
8497       // Tell the stack we're done descending.
8498       AdjustMaximumDepth();
8499       // Pop stack so next iteration is in correct place.
8500       Pop();
8501     }
8502     DCHECK(length != 0);
8503     // Adjust return values and exit.
8504     consumed_ = offset + length;
8505     *offset_out = consumed - offset;
8506     return string;
8507   }
8508   UNREACHABLE();
8509   return NULL;
8510 }
8511
8512
8513 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
8514   while (true) {
8515     // Tree traversal complete.
8516     if (depth_ == 0) {
8517       *blew_stack = false;
8518       return NULL;
8519     }
8520     // We've lost track of higher nodes.
8521     if (StackBlown()) {
8522       *blew_stack = true;
8523       return NULL;
8524     }
8525     // Go right.
8526     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8527     String* string = cons_string->second();
8528     int32_t type = string->map()->instance_type();
8529     if ((type & kStringRepresentationMask) != kConsStringTag) {
8530       // Pop stack so next iteration is in correct place.
8531       Pop();
8532       int length = string->length();
8533       // Could be a flattened ConsString.
8534       if (length == 0) continue;
8535       consumed_ += length;
8536       return string;
8537     }
8538     cons_string = ConsString::cast(string);
8539     PushRight(cons_string);
8540     // Need to traverse all the way left.
8541     while (true) {
8542       // Continue left.
8543       string = cons_string->first();
8544       type = string->map()->instance_type();
8545       if ((type & kStringRepresentationMask) != kConsStringTag) {
8546         AdjustMaximumDepth();
8547         int length = string->length();
8548         DCHECK(length != 0);
8549         consumed_ += length;
8550         return string;
8551       }
8552       cons_string = ConsString::cast(string);
8553       PushLeft(cons_string);
8554     }
8555   }
8556   UNREACHABLE();
8557   return NULL;
8558 }
8559
8560
8561 uint16_t ConsString::ConsStringGet(int index) {
8562   DCHECK(index >= 0 && index < this->length());
8563
8564   // Check for a flattened cons string
8565   if (second()->length() == 0) {
8566     String* left = first();
8567     return left->Get(index);
8568   }
8569
8570   String* string = String::cast(this);
8571
8572   while (true) {
8573     if (StringShape(string).IsCons()) {
8574       ConsString* cons_string = ConsString::cast(string);
8575       String* left = cons_string->first();
8576       if (left->length() > index) {
8577         string = left;
8578       } else {
8579         index -= left->length();
8580         string = cons_string->second();
8581       }
8582     } else {
8583       return string->Get(index);
8584     }
8585   }
8586
8587   UNREACHABLE();
8588   return 0;
8589 }
8590
8591
8592 uint16_t SlicedString::SlicedStringGet(int index) {
8593   return parent()->Get(offset() + index);
8594 }
8595
8596
8597 template <typename sinkchar>
8598 void String::WriteToFlat(String* src,
8599                          sinkchar* sink,
8600                          int f,
8601                          int t) {
8602   String* source = src;
8603   int from = f;
8604   int to = t;
8605   while (true) {
8606     DCHECK(0 <= from && from <= to && to <= source->length());
8607     switch (StringShape(source).full_representation_tag()) {
8608       case kOneByteStringTag | kExternalStringTag: {
8609         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8610                   to - from);
8611         return;
8612       }
8613       case kTwoByteStringTag | kExternalStringTag: {
8614         const uc16* data =
8615             ExternalTwoByteString::cast(source)->GetChars();
8616         CopyChars(sink,
8617                   data + from,
8618                   to - from);
8619         return;
8620       }
8621       case kOneByteStringTag | kSeqStringTag: {
8622         CopyChars(sink,
8623                   SeqOneByteString::cast(source)->GetChars() + from,
8624                   to - from);
8625         return;
8626       }
8627       case kTwoByteStringTag | kSeqStringTag: {
8628         CopyChars(sink,
8629                   SeqTwoByteString::cast(source)->GetChars() + from,
8630                   to - from);
8631         return;
8632       }
8633       case kOneByteStringTag | kConsStringTag:
8634       case kTwoByteStringTag | kConsStringTag: {
8635         ConsString* cons_string = ConsString::cast(source);
8636         String* first = cons_string->first();
8637         int boundary = first->length();
8638         if (to - boundary >= boundary - from) {
8639           // Right hand side is longer.  Recurse over left.
8640           if (from < boundary) {
8641             WriteToFlat(first, sink, from, boundary);
8642             sink += boundary - from;
8643             from = 0;
8644           } else {
8645             from -= boundary;
8646           }
8647           to -= boundary;
8648           source = cons_string->second();
8649         } else {
8650           // Left hand side is longer.  Recurse over right.
8651           if (to > boundary) {
8652             String* second = cons_string->second();
8653             // When repeatedly appending to a string, we get a cons string that
8654             // is unbalanced to the left, a list, essentially.  We inline the
8655             // common case of sequential one-byte right child.
8656             if (to - boundary == 1) {
8657               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8658             } else if (second->IsSeqOneByteString()) {
8659               CopyChars(sink + boundary - from,
8660                         SeqOneByteString::cast(second)->GetChars(),
8661                         to - boundary);
8662             } else {
8663               WriteToFlat(second,
8664                           sink + boundary - from,
8665                           0,
8666                           to - boundary);
8667             }
8668             to = boundary;
8669           }
8670           source = first;
8671         }
8672         break;
8673       }
8674       case kOneByteStringTag | kSlicedStringTag:
8675       case kTwoByteStringTag | kSlicedStringTag: {
8676         SlicedString* slice = SlicedString::cast(source);
8677         unsigned offset = slice->offset();
8678         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8679         return;
8680       }
8681     }
8682   }
8683 }
8684
8685
8686
8687 template <typename SourceChar>
8688 static void CalculateLineEndsImpl(Isolate* isolate,
8689                                   List<int>* line_ends,
8690                                   Vector<const SourceChar> src,
8691                                   bool include_ending_line) {
8692   const int src_len = src.length();
8693   UnicodeCache* cache = isolate->unicode_cache();
8694   for (int i = 0; i < src_len - 1; i++) {
8695     SourceChar current = src[i];
8696     SourceChar next = src[i + 1];
8697     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
8698   }
8699
8700   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
8701     line_ends->Add(src_len - 1);
8702   } else if (include_ending_line) {
8703     // Even if the last line misses a line end, it is counted.
8704     line_ends->Add(src_len);
8705   }
8706 }
8707
8708
8709 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
8710                                              bool include_ending_line) {
8711   src = Flatten(src);
8712   // Rough estimate of line count based on a roughly estimated average
8713   // length of (unpacked) code.
8714   int line_count_estimate = src->length() >> 4;
8715   List<int> line_ends(line_count_estimate);
8716   Isolate* isolate = src->GetIsolate();
8717   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
8718     // Dispatch on type of strings.
8719     String::FlatContent content = src->GetFlatContent();
8720     DCHECK(content.IsFlat());
8721     if (content.IsOneByte()) {
8722       CalculateLineEndsImpl(isolate,
8723                             &line_ends,
8724                             content.ToOneByteVector(),
8725                             include_ending_line);
8726     } else {
8727       CalculateLineEndsImpl(isolate,
8728                             &line_ends,
8729                             content.ToUC16Vector(),
8730                             include_ending_line);
8731     }
8732   }
8733   int line_count = line_ends.length();
8734   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
8735   for (int i = 0; i < line_count; i++) {
8736     array->set(i, Smi::FromInt(line_ends[i]));
8737   }
8738   return array;
8739 }
8740
8741
8742 // Compares the contents of two strings by reading and comparing
8743 // int-sized blocks of characters.
8744 template <typename Char>
8745 static inline bool CompareRawStringContents(const Char* const a,
8746                                             const Char* const b,
8747                                             int length) {
8748   return CompareChars(a, b, length) == 0;
8749 }
8750
8751
8752 template<typename Chars1, typename Chars2>
8753 class RawStringComparator : public AllStatic {
8754  public:
8755   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8756     DCHECK(sizeof(Chars1) != sizeof(Chars2));
8757     for (int i = 0; i < len; i++) {
8758       if (a[i] != b[i]) {
8759         return false;
8760       }
8761     }
8762     return true;
8763   }
8764 };
8765
8766
8767 template<>
8768 class RawStringComparator<uint16_t, uint16_t> {
8769  public:
8770   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8771     return CompareRawStringContents(a, b, len);
8772   }
8773 };
8774
8775
8776 template<>
8777 class RawStringComparator<uint8_t, uint8_t> {
8778  public:
8779   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8780     return CompareRawStringContents(a, b, len);
8781   }
8782 };
8783
8784
8785 class StringComparator {
8786   class State {
8787    public:
8788     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
8789
8790     void Init(String* string) {
8791       ConsString* cons_string = String::VisitFlat(this, string);
8792       iter_.Reset(cons_string);
8793       if (cons_string != NULL) {
8794         int offset;
8795         string = iter_.Next(&offset);
8796         String::VisitFlat(this, string, offset);
8797       }
8798     }
8799
8800     inline void VisitOneByteString(const uint8_t* chars, int length) {
8801       is_one_byte_ = true;
8802       buffer8_ = chars;
8803       length_ = length;
8804     }
8805
8806     inline void VisitTwoByteString(const uint16_t* chars, int length) {
8807       is_one_byte_ = false;
8808       buffer16_ = chars;
8809       length_ = length;
8810     }
8811
8812     void Advance(int consumed) {
8813       DCHECK(consumed <= length_);
8814       // Still in buffer.
8815       if (length_ != consumed) {
8816         if (is_one_byte_) {
8817           buffer8_ += consumed;
8818         } else {
8819           buffer16_ += consumed;
8820         }
8821         length_ -= consumed;
8822         return;
8823       }
8824       // Advance state.
8825       int offset;
8826       String* next = iter_.Next(&offset);
8827       DCHECK_EQ(0, offset);
8828       DCHECK(next != NULL);
8829       String::VisitFlat(this, next);
8830     }
8831
8832     ConsStringIterator iter_;
8833     bool is_one_byte_;
8834     int length_;
8835     union {
8836       const uint8_t* buffer8_;
8837       const uint16_t* buffer16_;
8838     };
8839
8840    private:
8841     DISALLOW_COPY_AND_ASSIGN(State);
8842   };
8843
8844  public:
8845   inline StringComparator() {}
8846
8847   template<typename Chars1, typename Chars2>
8848   static inline bool Equals(State* state_1, State* state_2, int to_check) {
8849     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8850     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8851     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8852   }
8853
8854   bool Equals(String* string_1, String* string_2) {
8855     int length = string_1->length();
8856     state_1_.Init(string_1);
8857     state_2_.Init(string_2);
8858     while (true) {
8859       int to_check = Min(state_1_.length_, state_2_.length_);
8860       DCHECK(to_check > 0 && to_check <= length);
8861       bool is_equal;
8862       if (state_1_.is_one_byte_) {
8863         if (state_2_.is_one_byte_) {
8864           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8865         } else {
8866           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8867         }
8868       } else {
8869         if (state_2_.is_one_byte_) {
8870           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8871         } else {
8872           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8873         }
8874       }
8875       // Looping done.
8876       if (!is_equal) return false;
8877       length -= to_check;
8878       // Exit condition. Strings are equal.
8879       if (length == 0) return true;
8880       state_1_.Advance(to_check);
8881       state_2_.Advance(to_check);
8882     }
8883   }
8884
8885  private:
8886   State state_1_;
8887   State state_2_;
8888
8889   DISALLOW_COPY_AND_ASSIGN(StringComparator);
8890 };
8891
8892
8893 bool String::SlowEquals(String* other) {
8894   DisallowHeapAllocation no_gc;
8895   // Fast check: negative check with lengths.
8896   int len = length();
8897   if (len != other->length()) return false;
8898   if (len == 0) return true;
8899
8900   // Fast check: if hash code is computed for both strings
8901   // a fast negative check can be performed.
8902   if (HasHashCode() && other->HasHashCode()) {
8903 #ifdef ENABLE_SLOW_DCHECKS
8904     if (FLAG_enable_slow_asserts) {
8905       if (Hash() != other->Hash()) {
8906         bool found_difference = false;
8907         for (int i = 0; i < len; i++) {
8908           if (Get(i) != other->Get(i)) {
8909             found_difference = true;
8910             break;
8911           }
8912         }
8913         DCHECK(found_difference);
8914       }
8915     }
8916 #endif
8917     if (Hash() != other->Hash()) return false;
8918   }
8919
8920   // We know the strings are both non-empty. Compare the first chars
8921   // before we try to flatten the strings.
8922   if (this->Get(0) != other->Get(0)) return false;
8923
8924   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
8925     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
8926     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
8927     return CompareRawStringContents(str1, str2, len);
8928   }
8929
8930   StringComparator comparator;
8931   return comparator.Equals(this, other);
8932 }
8933
8934
8935 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
8936   // Fast check: negative check with lengths.
8937   int one_length = one->length();
8938   if (one_length != two->length()) return false;
8939   if (one_length == 0) return true;
8940
8941   // Fast check: if hash code is computed for both strings
8942   // a fast negative check can be performed.
8943   if (one->HasHashCode() && two->HasHashCode()) {
8944 #ifdef ENABLE_SLOW_DCHECKS
8945     if (FLAG_enable_slow_asserts) {
8946       if (one->Hash() != two->Hash()) {
8947         bool found_difference = false;
8948         for (int i = 0; i < one_length; i++) {
8949           if (one->Get(i) != two->Get(i)) {
8950             found_difference = true;
8951             break;
8952           }
8953         }
8954         DCHECK(found_difference);
8955       }
8956     }
8957 #endif
8958     if (one->Hash() != two->Hash()) return false;
8959   }
8960
8961   // We know the strings are both non-empty. Compare the first chars
8962   // before we try to flatten the strings.
8963   if (one->Get(0) != two->Get(0)) return false;
8964
8965   one = String::Flatten(one);
8966   two = String::Flatten(two);
8967
8968   DisallowHeapAllocation no_gc;
8969   String::FlatContent flat1 = one->GetFlatContent();
8970   String::FlatContent flat2 = two->GetFlatContent();
8971
8972   if (flat1.IsOneByte() && flat2.IsOneByte()) {
8973       return CompareRawStringContents(flat1.ToOneByteVector().start(),
8974                                       flat2.ToOneByteVector().start(),
8975                                       one_length);
8976   } else {
8977     for (int i = 0; i < one_length; i++) {
8978       if (flat1.Get(i) != flat2.Get(i)) return false;
8979     }
8980     return true;
8981   }
8982 }
8983
8984
8985 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
8986   int slen = length();
8987   // Can't check exact length equality, but we can check bounds.
8988   int str_len = str.length();
8989   if (!allow_prefix_match &&
8990       (str_len < slen ||
8991           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
8992     return false;
8993   }
8994   int i;
8995   size_t remaining_in_str = static_cast<size_t>(str_len);
8996   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
8997   for (i = 0; i < slen && remaining_in_str > 0; i++) {
8998     size_t cursor = 0;
8999     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9000     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9001     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9002       if (i > slen - 1) return false;
9003       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9004       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9005     } else {
9006       if (Get(i) != r) return false;
9007     }
9008     utf8_data += cursor;
9009     remaining_in_str -= cursor;
9010   }
9011   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9012 }
9013
9014
9015 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9016   int slen = length();
9017   if (str.length() != slen) return false;
9018   DisallowHeapAllocation no_gc;
9019   FlatContent content = GetFlatContent();
9020   if (content.IsOneByte()) {
9021     return CompareChars(content.ToOneByteVector().start(),
9022                         str.start(), slen) == 0;
9023   }
9024   for (int i = 0; i < slen; i++) {
9025     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9026   }
9027   return true;
9028 }
9029
9030
9031 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9032   int slen = length();
9033   if (str.length() != slen) return false;
9034   DisallowHeapAllocation no_gc;
9035   FlatContent content = GetFlatContent();
9036   if (content.IsTwoByte()) {
9037     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9038   }
9039   for (int i = 0; i < slen; i++) {
9040     if (Get(i) != str[i]) return false;
9041   }
9042   return true;
9043 }
9044
9045
9046 uint32_t String::ComputeAndSetHash() {
9047   // Should only be called if hash code has not yet been computed.
9048   DCHECK(!HasHashCode());
9049
9050   // Store the hash code in the object.
9051   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9052   set_hash_field(field);
9053
9054   // Check the hash code is there.
9055   DCHECK(HasHashCode());
9056   uint32_t result = field >> kHashShift;
9057   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9058   return result;
9059 }
9060
9061
9062 bool String::ComputeArrayIndex(uint32_t* index) {
9063   int length = this->length();
9064   if (length == 0 || length > kMaxArrayIndexSize) return false;
9065   StringCharacterStream stream(this);
9066   return StringToArrayIndex(&stream, index);
9067 }
9068
9069
9070 bool String::SlowAsArrayIndex(uint32_t* index) {
9071   if (length() <= kMaxCachedArrayIndexLength) {
9072     Hash();  // force computation of hash code
9073     uint32_t field = hash_field();
9074     if ((field & kIsNotArrayIndexMask) != 0) return false;
9075     // Isolate the array index form the full hash field.
9076     *index = ArrayIndexValueBits::decode(field);
9077     return true;
9078   } else {
9079     return ComputeArrayIndex(index);
9080   }
9081 }
9082
9083
9084 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9085   int new_size, old_size;
9086   int old_length = string->length();
9087   if (old_length <= new_length) return string;
9088
9089   if (string->IsSeqOneByteString()) {
9090     old_size = SeqOneByteString::SizeFor(old_length);
9091     new_size = SeqOneByteString::SizeFor(new_length);
9092   } else {
9093     DCHECK(string->IsSeqTwoByteString());
9094     old_size = SeqTwoByteString::SizeFor(old_length);
9095     new_size = SeqTwoByteString::SizeFor(new_length);
9096   }
9097
9098   int delta = old_size - new_size;
9099
9100   Address start_of_string = string->address();
9101   DCHECK_OBJECT_ALIGNED(start_of_string);
9102   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9103
9104   Heap* heap = string->GetHeap();
9105   NewSpace* newspace = heap->new_space();
9106   if (newspace->Contains(start_of_string) &&
9107       newspace->top() == start_of_string + old_size) {
9108     // Last allocated object in new space.  Simply lower allocation top.
9109     newspace->set_top(start_of_string + new_size);
9110   } else {
9111     // Sizes are pointer size aligned, so that we can use filler objects
9112     // that are a multiple of pointer size.
9113     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9114   }
9115   heap->AdjustLiveBytes(start_of_string, -delta, Heap::CONCURRENT_TO_SWEEPER);
9116
9117   // We are storing the new length using release store after creating a filler
9118   // for the left-over space to avoid races with the sweeper thread.
9119   string->synchronized_set_length(new_length);
9120
9121   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9122   return string;
9123 }
9124
9125
9126 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9127   // For array indexes mix the length into the hash as an array index could
9128   // be zero.
9129   DCHECK(length > 0);
9130   DCHECK(length <= String::kMaxArrayIndexSize);
9131   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9132          (1 << String::kArrayIndexValueBits));
9133
9134   value <<= String::ArrayIndexValueBits::kShift;
9135   value |= length << String::ArrayIndexLengthBits::kShift;
9136
9137   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9138   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9139          (value & String::kContainsCachedArrayIndexMask) == 0);
9140   return value;
9141 }
9142
9143
9144 uint32_t StringHasher::GetHashField() {
9145   if (length_ <= String::kMaxHashCalcLength) {
9146     if (is_array_index_) {
9147       return MakeArrayIndexHash(array_index_, length_);
9148     }
9149     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9150            String::kIsNotArrayIndexMask;
9151   } else {
9152     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9153   }
9154 }
9155
9156
9157 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9158                                        uint32_t seed,
9159                                        int* utf16_length_out) {
9160   int vector_length = chars.length();
9161   // Handle some edge cases
9162   if (vector_length <= 1) {
9163     DCHECK(vector_length == 0 ||
9164            static_cast<uint8_t>(chars.start()[0]) <=
9165                unibrow::Utf8::kMaxOneByteChar);
9166     *utf16_length_out = vector_length;
9167     return HashSequentialString(chars.start(), vector_length, seed);
9168   }
9169   // Start with a fake length which won't affect computation.
9170   // It will be updated later.
9171   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9172   size_t remaining = static_cast<size_t>(vector_length);
9173   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9174   int utf16_length = 0;
9175   bool is_index = true;
9176   DCHECK(hasher.is_array_index_);
9177   while (remaining > 0) {
9178     size_t consumed = 0;
9179     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9180     DCHECK(consumed > 0 && consumed <= remaining);
9181     stream += consumed;
9182     remaining -= consumed;
9183     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9184     utf16_length += is_two_characters ? 2 : 1;
9185     // No need to keep hashing. But we do need to calculate utf16_length.
9186     if (utf16_length > String::kMaxHashCalcLength) continue;
9187     if (is_two_characters) {
9188       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9189       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9190       hasher.AddCharacter(c1);
9191       hasher.AddCharacter(c2);
9192       if (is_index) is_index = hasher.UpdateIndex(c1);
9193       if (is_index) is_index = hasher.UpdateIndex(c2);
9194     } else {
9195       hasher.AddCharacter(c);
9196       if (is_index) is_index = hasher.UpdateIndex(c);
9197     }
9198   }
9199   *utf16_length_out = static_cast<int>(utf16_length);
9200   // Must set length here so that hash computation is correct.
9201   hasher.length_ = utf16_length;
9202   return hasher.GetHashField();
9203 }
9204
9205
9206 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
9207   // Run small ConsStrings through ConsStringIterator.
9208   if (cons_string->length() < 64) {
9209     ConsStringIterator iter(cons_string);
9210     int offset;
9211     String* string;
9212     while (nullptr != (string = iter.Next(&offset))) {
9213       DCHECK_EQ(0, offset);
9214       String::VisitFlat(this, string, 0);
9215     }
9216     return;
9217   }
9218   // Slow case.
9219   const int max_length = String::kMaxHashCalcLength;
9220   int length = std::min(cons_string->length(), max_length);
9221   if (cons_string->HasOnlyOneByteChars()) {
9222     uint8_t* buffer = new uint8_t[length];
9223     String::WriteToFlat(cons_string, buffer, 0, length);
9224     AddCharacters(buffer, length);
9225     delete[] buffer;
9226   } else {
9227     uint16_t* buffer = new uint16_t[length];
9228     String::WriteToFlat(cons_string, buffer, 0, length);
9229     AddCharacters(buffer, length);
9230     delete[] buffer;
9231   }
9232 }
9233
9234
9235 void String::PrintOn(FILE* file) {
9236   int length = this->length();
9237   for (int i = 0; i < length; i++) {
9238     PrintF(file, "%c", Get(i));
9239   }
9240 }
9241
9242
9243 inline static uint32_t ObjectAddressForHashing(Object* object) {
9244   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9245   return value & MemoryChunk::kAlignmentMask;
9246 }
9247
9248
9249 int Map::Hash() {
9250   // For performance reasons we only hash the 3 most variable fields of a map:
9251   // constructor, prototype and bit_field2. For predictability reasons we
9252   // use objects' offsets in respective pages for hashing instead of raw
9253   // addresses.
9254
9255   // Shift away the tag.
9256   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
9257
9258   // XOR-ing the prototype and constructor directly yields too many zero bits
9259   // when the two pointers are close (which is fairly common).
9260   // To avoid this we shift the prototype bits relatively to the constructor.
9261   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9262
9263   return hash ^ (hash >> 16) ^ bit_field2();
9264 }
9265
9266
9267 static bool CheckEquivalent(Map* first, Map* second) {
9268   return first->GetConstructor() == second->GetConstructor() &&
9269          first->prototype() == second->prototype() &&
9270          first->instance_type() == second->instance_type() &&
9271          first->bit_field() == second->bit_field() &&
9272          first->is_extensible() == second->is_extensible() &&
9273          first->is_strong() == second->is_strong() &&
9274          first->has_instance_call_handler() ==
9275              second->has_instance_call_handler();
9276 }
9277
9278
9279 bool Map::EquivalentToForTransition(Map* other) {
9280   return CheckEquivalent(this, other);
9281 }
9282
9283
9284 bool Map::EquivalentToForNormalization(Map* other,
9285                                        PropertyNormalizationMode mode) {
9286   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9287       ? 0 : other->inobject_properties();
9288   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
9289          inobject_properties() == properties;
9290 }
9291
9292
9293 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9294   // Iterate over all fields in the body but take care in dealing with
9295   // the code entry.
9296   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9297   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9298   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9299 }
9300
9301
9302 bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
9303   DisallowHeapAllocation no_gc;
9304   if (shared() == candidate) return true;
9305   if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
9306   DeoptimizationInputData* const data =
9307       DeoptimizationInputData::cast(code()->deoptimization_data());
9308   if (data->length() == 0) return false;
9309   FixedArray* const literals = data->LiteralArray();
9310   int const inlined_count = data->InlinedFunctionCount()->value();
9311   for (int i = 0; i < inlined_count; ++i) {
9312     if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
9313       return true;
9314     }
9315   }
9316   return false;
9317 }
9318
9319
9320 void JSFunction::MarkForOptimization() {
9321   Isolate* isolate = GetIsolate();
9322   // Do not optimize if function contains break points.
9323   if (shared()->HasDebugInfo()) return;
9324   DCHECK(!IsOptimized());
9325   DCHECK(shared()->allows_lazy_compilation() ||
9326          !shared()->optimization_disabled());
9327   DCHECK(!shared()->HasDebugInfo());
9328   set_code_no_write_barrier(
9329       isolate->builtins()->builtin(Builtins::kCompileOptimized));
9330   // No write barrier required, since the builtin is part of the root set.
9331 }
9332
9333
9334 void JSFunction::AttemptConcurrentOptimization() {
9335   Isolate* isolate = GetIsolate();
9336   if (!isolate->concurrent_recompilation_enabled() ||
9337       isolate->bootstrapper()->IsActive()) {
9338     MarkForOptimization();
9339     return;
9340   }
9341   if (isolate->concurrent_osr_enabled() &&
9342       isolate->optimizing_compile_dispatcher()->IsQueuedForOSR(this)) {
9343     // Do not attempt regular recompilation if we already queued this for OSR.
9344     // TODO(yangguo): This is necessary so that we don't install optimized
9345     // code on a function that is already optimized, since OSR and regular
9346     // recompilation race.  This goes away as soon as OSR becomes one-shot.
9347     return;
9348   }
9349   DCHECK(!IsInOptimizationQueue());
9350   DCHECK(!IsOptimized());
9351   DCHECK(shared()->allows_lazy_compilation() ||
9352          !shared()->optimization_disabled());
9353   DCHECK(isolate->concurrent_recompilation_enabled());
9354   if (FLAG_trace_concurrent_recompilation) {
9355     PrintF("  ** Marking ");
9356     ShortPrint();
9357     PrintF(" for concurrent recompilation.\n");
9358   }
9359   set_code_no_write_barrier(
9360       isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9361   // No write barrier required, since the builtin is part of the root set.
9362 }
9363
9364
9365 Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9366   Isolate* isolate = function->GetIsolate();
9367   Handle<Map> map(function->map());
9368   Handle<SharedFunctionInfo> shared(function->shared());
9369   Handle<Context> context(function->context());
9370   Handle<JSFunction> clone =
9371       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9372
9373   if (shared->bound()) {
9374     clone->set_function_bindings(function->function_bindings());
9375   }
9376
9377   // In typical case, __proto__ of ``function`` is the default Function
9378   // prototype, which means that SetPrototype below is a no-op.
9379   // In rare cases when that is not true, we mutate the clone's __proto__.
9380   Handle<Object> original_prototype(map->prototype(), isolate);
9381   if (*original_prototype != clone->map()->prototype()) {
9382     JSObject::SetPrototype(clone, original_prototype, false).Assert();
9383   }
9384
9385   return clone;
9386 }
9387
9388
9389 void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
9390     Handle<SharedFunctionInfo> shared, Handle<Code> code) {
9391   Isolate* isolate = shared->GetIsolate();
9392   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9393   Handle<Object> value(shared->optimized_code_map(), isolate);
9394   if (value->IsSmi()) return;  // Empty code maps are unsupported.
9395   Handle<FixedArray> code_map = Handle<FixedArray>::cast(value);
9396   code_map->set(kSharedCodeIndex, *code);
9397 }
9398
9399
9400 void SharedFunctionInfo::AddToOptimizedCodeMap(
9401     Handle<SharedFunctionInfo> shared,
9402     Handle<Context> native_context,
9403     Handle<Code> code,
9404     Handle<FixedArray> literals,
9405     BailoutId osr_ast_id) {
9406   Isolate* isolate = shared->GetIsolate();
9407   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9408   DCHECK(native_context->IsNativeContext());
9409   STATIC_ASSERT(kEntryLength == 4);
9410   Handle<FixedArray> new_code_map;
9411   Handle<Object> value(shared->optimized_code_map(), isolate);
9412   int old_length;
9413   if (value->IsSmi()) {
9414     // No optimized code map.
9415     DCHECK_EQ(0, Smi::cast(*value)->value());
9416     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9417     old_length = kEntriesStart;
9418   } else {
9419     // Copy old map and append one new entry.
9420     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9421     DCHECK(!shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code);
9422     old_length = old_code_map->length();
9423     new_code_map = FixedArray::CopySize(
9424         old_code_map, old_length + kEntryLength);
9425     // Zap the old map for the sake of the heap verifier.
9426     if (Heap::ShouldZapGarbage()) {
9427       Object** data = old_code_map->data_start();
9428       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9429     }
9430   }
9431   new_code_map->set(old_length + kContextOffset, *native_context);
9432   new_code_map->set(old_length + kCachedCodeOffset, *code);
9433   new_code_map->set(old_length + kLiteralsOffset, *literals);
9434   new_code_map->set(old_length + kOsrAstIdOffset,
9435                     Smi::FromInt(osr_ast_id.ToInt()));
9436
9437 #ifdef DEBUG
9438   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9439     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9440     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9441     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9442            Code::OPTIMIZED_FUNCTION);
9443     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9444     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9445   }
9446 #endif
9447   shared->set_optimized_code_map(*new_code_map);
9448 }
9449
9450
9451 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9452   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9453
9454   // If the next map link slot is already used then the function was
9455   // enqueued with code flushing and we remove it now.
9456   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9457     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9458     flusher->EvictOptimizedCodeMap(this);
9459   }
9460
9461   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9462   set_optimized_code_map(Smi::FromInt(0));
9463 }
9464
9465
9466 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9467                                                    const char* reason) {
9468   DisallowHeapAllocation no_gc;
9469   if (optimized_code_map()->IsSmi()) return;
9470
9471   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9472   int dst = kEntriesStart;
9473   int length = code_map->length();
9474   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9475     DCHECK(code_map->get(src)->IsNativeContext());
9476     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9477       // Evict the src entry by not copying it to the dst entry.
9478       if (FLAG_trace_opt) {
9479         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9480         ShortPrint();
9481         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9482         if (osr.IsNone()) {
9483           PrintF("]\n");
9484         } else {
9485           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9486         }
9487       }
9488     } else {
9489       // Keep the src entry by copying it to the dst entry.
9490       if (dst != src) {
9491         code_map->set(dst + kContextOffset,
9492                       code_map->get(src + kContextOffset));
9493         code_map->set(dst + kCachedCodeOffset,
9494                       code_map->get(src + kCachedCodeOffset));
9495         code_map->set(dst + kLiteralsOffset,
9496                       code_map->get(src + kLiteralsOffset));
9497         code_map->set(dst + kOsrAstIdOffset,
9498                       code_map->get(src + kOsrAstIdOffset));
9499       }
9500       dst += kEntryLength;
9501     }
9502   }
9503   if (code_map->get(kSharedCodeIndex) == optimized_code) {
9504     // Evict context-independent code as well.
9505     code_map->set_undefined(kSharedCodeIndex);
9506     if (FLAG_trace_opt) {
9507       PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9508       ShortPrint();
9509       PrintF(" (context-independent code)]\n");
9510     }
9511   }
9512   if (dst != length) {
9513     // Always trim even when array is cleared because of heap verifier.
9514     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
9515                                                                 length - dst);
9516     if (code_map->length() == kEntriesStart &&
9517         code_map->get(kSharedCodeIndex)->IsUndefined()) {
9518       ClearOptimizedCodeMap();
9519     }
9520   }
9521 }
9522
9523
9524 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9525   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9526   DCHECK(shrink_by % kEntryLength == 0);
9527   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9528   // Always trim even when array is cleared because of heap verifier.
9529   GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
9530                                                               shrink_by);
9531   if (code_map->length() == kEntriesStart &&
9532       code_map->get(kSharedCodeIndex)->IsUndefined()) {
9533     ClearOptimizedCodeMap();
9534   }
9535 }
9536
9537
9538 static void GetMinInobjectSlack(Map* map, void* data) {
9539   int slack = map->unused_property_fields();
9540   if (*reinterpret_cast<int*>(data) > slack) {
9541     *reinterpret_cast<int*>(data) = slack;
9542   }
9543 }
9544
9545
9546 static void ShrinkInstanceSize(Map* map, void* data) {
9547   int slack = *reinterpret_cast<int*>(data);
9548   map->set_inobject_properties(map->inobject_properties() - slack);
9549   map->set_unused_property_fields(map->unused_property_fields() - slack);
9550   map->set_instance_size(map->instance_size() - slack * kPointerSize);
9551
9552   // Visitor id might depend on the instance size, recalculate it.
9553   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9554 }
9555
9556
9557 void JSFunction::CompleteInobjectSlackTracking() {
9558   DCHECK(has_initial_map());
9559   Map* map = initial_map();
9560
9561   DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
9562   map->set_counter(Map::kRetainingCounterStart);
9563
9564   int slack = map->unused_property_fields();
9565   TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack);
9566   if (slack != 0) {
9567     // Resize the initial map and all maps in its transition tree.
9568     TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack);
9569   }
9570 }
9571
9572
9573 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
9574   DisallowHeapAllocation no_gc;
9575   if (!object->HasFastProperties()) return false;
9576   Map* map = object->map();
9577   if (map->is_prototype_map()) return false;
9578   DescriptorArray* descriptors = map->instance_descriptors();
9579   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
9580     PropertyDetails details = descriptors->GetDetails(i);
9581     if (details.location() == kDescriptor) continue;
9582     if (details.representation().IsHeapObject() ||
9583         details.representation().IsTagged()) {
9584       FieldIndex index = FieldIndex::ForDescriptor(map, i);
9585       if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9586     }
9587   }
9588   return false;
9589 }
9590
9591
9592 // static
9593 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9594                                    PrototypeOptimizationMode mode) {
9595   if (object->IsGlobalObject()) return;
9596   if (object->IsJSGlobalProxy()) return;
9597   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9598     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9599     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9600                                   "NormalizeAsPrototype");
9601   }
9602   Handle<Map> previous_map(object->map());
9603   if (!object->HasFastProperties()) {
9604     JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9605   }
9606   if (!object->map()->is_prototype_map()) {
9607     if (object->map() == *previous_map) {
9608       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9609       JSObject::MigrateToMap(object, new_map);
9610     }
9611     object->map()->set_is_prototype_map(true);
9612
9613     // Replace the pointer to the exact constructor with the Object function
9614     // from the same context if undetectable from JS. This is to avoid keeping
9615     // memory alive unnecessarily.
9616     Object* maybe_constructor = object->map()->GetConstructor();
9617     if (maybe_constructor->IsJSFunction()) {
9618       JSFunction* constructor = JSFunction::cast(maybe_constructor);
9619       Isolate* isolate = object->GetIsolate();
9620       if (!constructor->shared()->IsApiFunction() &&
9621           object->class_name() == isolate->heap()->Object_string()) {
9622         Handle<String> constructor_name(object->constructor_name(), isolate);
9623         Context* context = constructor->context()->native_context();
9624         JSFunction* object_function = context->object_function();
9625         object->map()->SetConstructor(object_function);
9626         Handle<PrototypeInfo> proto_info =
9627             Map::GetOrCreatePrototypeInfo(object, isolate);
9628         proto_info->set_constructor_name(*constructor_name);
9629       }
9630     }
9631   }
9632 }
9633
9634
9635 // static
9636 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9637   if (!object->map()->is_prototype_map()) return;
9638   OptimizeAsPrototype(object, FAST_PROTOTYPE);
9639 }
9640
9641
9642 // static
9643 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
9644   DCHECK(FLAG_track_prototype_users);
9645   // Contract: In line with InvalidatePrototypeChains()'s requirements,
9646   // leaf maps don't need to register as users, only prototypes do.
9647   DCHECK(user->is_prototype_map());
9648
9649   Handle<Map> current_user = user;
9650   for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
9651     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
9652     if (maybe_proto->IsJSGlobalProxy()) continue;
9653     // Proxies on the prototype chain are not supported.
9654     if (maybe_proto->IsJSProxy()) return;
9655     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
9656     bool just_registered =
9657         RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate);
9658     // Walk up the prototype chain as far as links haven't been registered yet.
9659     if (!just_registered) break;
9660     current_user = handle(proto->map(), isolate);
9661   }
9662 }
9663
9664
9665 // Returns true if the user was not yet registered.
9666 // static
9667 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype,
9668                                                     Handle<HeapObject> user,
9669                                                     Isolate* isolate) {
9670   Handle<PrototypeInfo> proto_info =
9671       Map::GetOrCreatePrototypeInfo(prototype, isolate);
9672   Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
9673   bool was_present = false;
9674   Handle<WeakFixedArray> new_array = WeakFixedArray::Add(
9675       maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present);
9676   if (!maybe_registry.is_identical_to(new_array)) {
9677     proto_info->set_prototype_users(*new_array);
9678   }
9679   if (FLAG_trace_prototype_users && !was_present) {
9680     PrintF("Registering %p as a user of prototype %p (map=%p).\n",
9681            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype),
9682            reinterpret_cast<void*>(prototype->map()));
9683   }
9684   return !was_present;
9685 }
9686
9687
9688 // Can be called regardless of whether |user| was actually registered with
9689 // |prototype|. Returns true when there was a registration.
9690 // static
9691 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9692                                        Handle<HeapObject> user) {
9693   Isolate* isolate = prototype->GetIsolate();
9694   if (prototype->IsJSGlobalProxy()) {
9695     PrototypeIterator iter(isolate, prototype);
9696     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9697   }
9698   DCHECK(prototype->map()->is_prototype_map());
9699   Object* maybe_proto_info = prototype->map()->prototype_info();
9700   if (!maybe_proto_info->IsPrototypeInfo()) return false;
9701   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
9702                                    isolate);
9703   Object* maybe_registry = proto_info->prototype_users();
9704   if (!maybe_registry->IsWeakFixedArray()) return false;
9705   bool result = WeakFixedArray::cast(maybe_registry)->Remove(user);
9706   if (FLAG_trace_prototype_users && result) {
9707     PrintF("Unregistering %p as a user of prototype %p.\n",
9708            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
9709   }
9710   return result;
9711 }
9712
9713
9714 static void InvalidatePrototypeChainsInternal(Map* map) {
9715   if (!map->is_prototype_map()) return;
9716   if (FLAG_trace_prototype_users) {
9717     PrintF("Invalidating prototype map %p 's cell\n",
9718            reinterpret_cast<void*>(map));
9719   }
9720   Object* maybe_proto_info = map->prototype_info();
9721   if (!maybe_proto_info->IsPrototypeInfo()) return;
9722   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
9723   Object* maybe_cell = proto_info->validity_cell();
9724   if (maybe_cell->IsCell()) {
9725     // Just set the value; the cell will be replaced lazily.
9726     Cell* cell = Cell::cast(maybe_cell);
9727     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
9728   }
9729
9730   Object* maybe_array = proto_info->prototype_users();
9731   if (!maybe_array->IsWeakFixedArray()) return;
9732
9733   WeakFixedArray* users = WeakFixedArray::cast(maybe_array);
9734   for (int i = 0; i < users->Length(); ++i) {
9735     Object* maybe_user = users->Get(i);
9736     if (maybe_user->IsSmi()) continue;
9737
9738     // For now, only maps register themselves as users.
9739     Map* user = Map::cast(maybe_user);
9740     // Walk the prototype chain (backwards, towards leaf objects) if necessary.
9741     InvalidatePrototypeChainsInternal(user);
9742   }
9743 }
9744
9745
9746 // static
9747 void JSObject::InvalidatePrototypeChains(Map* map) {
9748   if (!FLAG_eliminate_prototype_chain_checks) return;
9749   DisallowHeapAllocation no_gc;
9750   if (map->IsJSGlobalProxyMap()) {
9751     PrototypeIterator iter(map);
9752     map = JSObject::cast(iter.GetCurrent())->map();
9753   }
9754   InvalidatePrototypeChainsInternal(map);
9755 }
9756
9757
9758 // static
9759 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
9760                                                     Isolate* isolate) {
9761   Object* maybe_proto_info = prototype->map()->prototype_info();
9762   if (maybe_proto_info->IsPrototypeInfo()) {
9763     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
9764   }
9765   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
9766   prototype->map()->set_prototype_info(*proto_info);
9767   return proto_info;
9768 }
9769
9770
9771 // static
9772 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
9773                                                         Isolate* isolate) {
9774   Handle<Object> maybe_prototype(map->prototype(), isolate);
9775   if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
9776   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
9777   if (prototype->IsJSGlobalProxy()) {
9778     PrototypeIterator iter(isolate, prototype);
9779     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9780   }
9781   // Ensure the prototype is registered with its own prototypes so its cell
9782   // will be invalidated when necessary.
9783   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
9784                                       isolate);
9785   Handle<PrototypeInfo> proto_info =
9786       GetOrCreatePrototypeInfo(prototype, isolate);
9787   Object* maybe_cell = proto_info->validity_cell();
9788   // Return existing cell if it's still valid.
9789   if (maybe_cell->IsCell()) {
9790     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
9791     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
9792       return cell;
9793     }
9794   }
9795   // Otherwise create a new cell.
9796   Handle<Cell> cell = isolate->factory()->NewCell(
9797       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
9798   proto_info->set_validity_cell(*cell);
9799   return cell;
9800 }
9801
9802
9803 // static
9804 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
9805                        PrototypeOptimizationMode proto_mode) {
9806   if (prototype->IsJSObject()) {
9807     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9808     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9809   }
9810   WriteBarrierMode wb_mode =
9811       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9812   map->set_prototype(*prototype, wb_mode);
9813 }
9814
9815
9816 Handle<Object> CacheInitialJSArrayMaps(
9817     Handle<Context> native_context, Handle<Map> initial_map) {
9818   // Replace all of the cached initial array maps in the native context with
9819   // the appropriate transitioned elements kind maps.
9820   Factory* factory = native_context->GetIsolate()->factory();
9821   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9822       kElementsKindCount, TENURED);
9823
9824   Handle<Map> current_map = initial_map;
9825   ElementsKind kind = current_map->elements_kind();
9826   DCHECK(kind == GetInitialFastElementsKind());
9827   maps->set(kind, *current_map);
9828   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9829        i < kFastElementsKindCount; ++i) {
9830     Handle<Map> new_map;
9831     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9832     Map* maybe_elements_transition = current_map->ElementsTransitionMap();
9833     if (maybe_elements_transition != NULL) {
9834       new_map = handle(maybe_elements_transition);
9835       DCHECK(new_map->elements_kind() == next_kind);
9836     } else {
9837       new_map = Map::CopyAsElementsKind(
9838           current_map, next_kind, INSERT_TRANSITION);
9839     }
9840     maps->set(next_kind, *new_map);
9841     current_map = new_map;
9842   }
9843   if (initial_map->is_strong())
9844     native_context->set_js_array_strong_maps(*maps);
9845   else
9846     native_context->set_js_array_maps(*maps);
9847   return initial_map;
9848 }
9849
9850
9851 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9852                                       Handle<Object> value) {
9853   Isolate* isolate = function->GetIsolate();
9854
9855   DCHECK(value->IsJSReceiver());
9856
9857   // Now some logic for the maps of the objects that are created by using this
9858   // function as a constructor.
9859   if (function->has_initial_map()) {
9860     // If the function has allocated the initial map replace it with a
9861     // copy containing the new prototype.  Also complete any in-object
9862     // slack tracking that is in progress at this point because it is
9863     // still tracking the old copy.
9864     if (function->IsInobjectSlackTrackingInProgress()) {
9865       function->CompleteInobjectSlackTracking();
9866     }
9867
9868     Handle<Map> initial_map(function->initial_map(), isolate);
9869
9870     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9871         initial_map->instance_type() == JS_OBJECT_TYPE) {
9872       // Put the value in the initial map field until an initial map is needed.
9873       // At that point, a new initial map is created and the prototype is put
9874       // into the initial map where it belongs.
9875       function->set_prototype_or_initial_map(*value);
9876     } else {
9877       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
9878       JSFunction::SetInitialMap(function, new_map, value);
9879
9880       // If the function is used as the global Array function, cache the
9881       // updated initial maps (and transitioned versions) in the native context.
9882       Handle<Context> native_context(function->context()->native_context(),
9883                                      isolate);
9884       Handle<Object> array_function(
9885           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
9886       if (array_function->IsJSFunction() &&
9887           *function == JSFunction::cast(*array_function)) {
9888         CacheInitialJSArrayMaps(native_context, new_map);
9889         Handle<Map> new_strong_map = Map::Copy(new_map, "SetInstancePrototype");
9890         new_strong_map->set_is_strong();
9891         CacheInitialJSArrayMaps(native_context, new_strong_map);
9892       }
9893     }
9894
9895     // Deoptimize all code that embeds the previous initial map.
9896     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9897         isolate, DependentCode::kInitialMapChangedGroup);
9898   } else {
9899     // Put the value in the initial map field until an initial map is
9900     // needed.  At that point, a new initial map is created and the
9901     // prototype is put into the initial map where it belongs.
9902     function->set_prototype_or_initial_map(*value);
9903     if (value->IsJSObject()) {
9904       // Optimize as prototype to detach it from its transition tree.
9905       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
9906                                     FAST_PROTOTYPE);
9907     }
9908   }
9909   isolate->heap()->ClearInstanceofCache();
9910 }
9911
9912
9913 void JSFunction::SetPrototype(Handle<JSFunction> function,
9914                               Handle<Object> value) {
9915   DCHECK(function->should_have_prototype());
9916   Handle<Object> construct_prototype = value;
9917
9918   // If the value is not a JSReceiver, store the value in the map's
9919   // constructor field so it can be accessed.  Also, set the prototype
9920   // used for constructing objects to the original object prototype.
9921   // See ECMA-262 13.2.2.
9922   if (!value->IsJSReceiver()) {
9923     // Copy the map so this does not affect unrelated functions.
9924     // Remove map transitions because they point to maps with a
9925     // different prototype.
9926     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
9927
9928     JSObject::MigrateToMap(function, new_map);
9929     new_map->SetConstructor(*value);
9930     new_map->set_non_instance_prototype(true);
9931     Isolate* isolate = new_map->GetIsolate();
9932     construct_prototype = handle(
9933         isolate->context()->native_context()->initial_object_prototype(),
9934         isolate);
9935   } else {
9936     function->map()->set_non_instance_prototype(false);
9937   }
9938
9939   return SetInstancePrototype(function, construct_prototype);
9940 }
9941
9942
9943 bool JSFunction::RemovePrototype() {
9944   Context* native_context = context()->native_context();
9945   Map* no_prototype_map =
9946       is_strict(shared()->language_mode())
9947           ? native_context->strict_function_without_prototype_map()
9948           : native_context->sloppy_function_without_prototype_map();
9949
9950   if (map() == no_prototype_map) return true;
9951
9952 #ifdef DEBUG
9953   if (map() != (is_strict(shared()->language_mode())
9954                     ? native_context->strict_function_map()
9955                     : native_context->sloppy_function_map())) {
9956     return false;
9957   }
9958 #endif
9959
9960   set_map(no_prototype_map);
9961   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9962   return true;
9963 }
9964
9965
9966 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9967                                Handle<Object> prototype) {
9968   if (map->prototype() != *prototype) {
9969     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
9970   }
9971   function->set_prototype_or_initial_map(*map);
9972   map->SetConstructor(*function);
9973 #if TRACE_MAPS
9974   if (FLAG_trace_maps) {
9975     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
9976            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
9977            function->shared()->DebugName()->ToCString().get());
9978   }
9979 #endif
9980 }
9981
9982
9983 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9984   if (function->has_initial_map()) return;
9985   Isolate* isolate = function->GetIsolate();
9986
9987   // First create a new map with the size and number of in-object properties
9988   // suggested by the function.
9989   InstanceType instance_type;
9990   int instance_size;
9991   int in_object_properties;
9992   if (function->shared()->is_generator()) {
9993     instance_type = JS_GENERATOR_OBJECT_TYPE;
9994     instance_size = JSGeneratorObject::kSize;
9995     in_object_properties = 0;
9996   } else {
9997     instance_type = JS_OBJECT_TYPE;
9998     instance_size = function->shared()->CalculateInstanceSize();
9999     in_object_properties = function->shared()->CalculateInObjectProperties();
10000   }
10001   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10002
10003   // Fetch or allocate prototype.
10004   Handle<Object> prototype;
10005   if (function->has_instance_prototype()) {
10006     prototype = handle(function->instance_prototype(), isolate);
10007   } else {
10008     prototype = isolate->factory()->NewFunctionPrototype(function);
10009   }
10010   map->set_inobject_properties(in_object_properties);
10011   map->set_unused_property_fields(in_object_properties);
10012   DCHECK(map->has_fast_object_elements());
10013
10014   // Finally link initial map and constructor function.
10015   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10016
10017   if (!function->shared()->is_generator()) {
10018     function->StartInobjectSlackTracking();
10019   }
10020 }
10021
10022
10023 void JSFunction::SetInstanceClassName(String* name) {
10024   shared()->set_instance_class_name(name);
10025 }
10026
10027
10028 void JSFunction::PrintName(FILE* out) {
10029   base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10030   PrintF(out, "%s", name.get());
10031 }
10032
10033
10034 // The filter is a pattern that matches function names in this way:
10035 //   "*"      all; the default
10036 //   "-"      all but the top-level function
10037 //   "-name"  all but the function "name"
10038 //   ""       only the top-level function
10039 //   "name"   only the function "name"
10040 //   "name*"  only functions starting with "name"
10041 //   "~"      none; the tilde is not an identifier
10042 bool JSFunction::PassesFilter(const char* raw_filter) {
10043   if (*raw_filter == '*') return true;
10044   String* name = shared()->DebugName();
10045   Vector<const char> filter = CStrVector(raw_filter);
10046   if (filter.length() == 0) return name->length() == 0;
10047   if (filter[0] == '-') {
10048     // Negative filter.
10049     if (filter.length() == 1) {
10050       return (name->length() != 0);
10051     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10052       return false;
10053     }
10054     if (filter[filter.length() - 1] == '*' &&
10055         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10056       return false;
10057     }
10058     return true;
10059
10060   } else if (name->IsUtf8EqualTo(filter)) {
10061     return true;
10062   }
10063   if (filter[filter.length() - 1] == '*' &&
10064       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10065     return true;
10066   }
10067   return false;
10068 }
10069
10070
10071 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
10072   Isolate* isolate = function->GetIsolate();
10073   Handle<Object> name =
10074       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
10075   if (name->IsString()) return Handle<String>::cast(name);
10076   return handle(function->shared()->DebugName(), isolate);
10077 }
10078
10079
10080 void Oddball::Initialize(Isolate* isolate,
10081                          Handle<Oddball> oddball,
10082                          const char* to_string,
10083                          Handle<Object> to_number,
10084                          byte kind) {
10085   Handle<String> internalized_to_string =
10086       isolate->factory()->InternalizeUtf8String(to_string);
10087   oddball->set_to_string(*internalized_to_string);
10088   oddball->set_to_number(*to_number);
10089   oddball->set_kind(kind);
10090 }
10091
10092
10093 void Script::InitLineEnds(Handle<Script> script) {
10094   if (!script->line_ends()->IsUndefined()) return;
10095
10096   Isolate* isolate = script->GetIsolate();
10097
10098   if (!script->source()->IsString()) {
10099     DCHECK(script->source()->IsUndefined());
10100     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10101     script->set_line_ends(*empty);
10102     DCHECK(script->line_ends()->IsFixedArray());
10103     return;
10104   }
10105
10106   Handle<String> src(String::cast(script->source()), isolate);
10107
10108   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10109
10110   if (*array != isolate->heap()->empty_fixed_array()) {
10111     array->set_map(isolate->heap()->fixed_cow_array_map());
10112   }
10113
10114   script->set_line_ends(*array);
10115   DCHECK(script->line_ends()->IsFixedArray());
10116 }
10117
10118
10119 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10120   int line_number = GetLineNumber(script, code_pos);
10121   if (line_number == -1) return -1;
10122
10123   DisallowHeapAllocation no_allocation;
10124   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10125   line_number = line_number - script->line_offset()->value();
10126   if (line_number == 0) return code_pos + script->column_offset()->value();
10127   int prev_line_end_pos =
10128       Smi::cast(line_ends_array->get(line_number - 1))->value();
10129   return code_pos - (prev_line_end_pos + 1);
10130 }
10131
10132
10133 int Script::GetLineNumberWithArray(int code_pos) {
10134   DisallowHeapAllocation no_allocation;
10135   DCHECK(line_ends()->IsFixedArray());
10136   FixedArray* line_ends_array = FixedArray::cast(line_ends());
10137   int line_ends_len = line_ends_array->length();
10138   if (line_ends_len == 0) return -1;
10139
10140   if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
10141     return line_offset()->value();
10142   }
10143
10144   int left = 0;
10145   int right = line_ends_len;
10146   while (int half = (right - left) / 2) {
10147     if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
10148       right -= half;
10149     } else {
10150       left += half;
10151     }
10152   }
10153   return right + line_offset()->value();
10154 }
10155
10156
10157 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10158   InitLineEnds(script);
10159   return script->GetLineNumberWithArray(code_pos);
10160 }
10161
10162
10163 int Script::GetLineNumber(int code_pos) {
10164   DisallowHeapAllocation no_allocation;
10165   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10166
10167   // Slow mode: we do not have line_ends. We have to iterate through source.
10168   if (!source()->IsString()) return -1;
10169
10170   String* source_string = String::cast(source());
10171   int line = 0;
10172   int len = source_string->length();
10173   for (int pos = 0; pos < len; pos++) {
10174     if (pos == code_pos) break;
10175     if (source_string->Get(pos) == '\n') line++;
10176   }
10177   return line;
10178 }
10179
10180
10181 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10182   Isolate* isolate = script->GetIsolate();
10183   Handle<String> name_or_source_url_key =
10184       isolate->factory()->InternalizeOneByteString(
10185           STATIC_CHAR_VECTOR("nameOrSourceURL"));
10186   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10187   Handle<Object> property = Object::GetProperty(
10188       script_wrapper, name_or_source_url_key).ToHandleChecked();
10189   DCHECK(property->IsJSFunction());
10190   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10191   Handle<Object> result;
10192   // Do not check against pending exception, since this function may be called
10193   // when an exception has already been pending.
10194   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10195     return isolate->factory()->undefined_value();
10196   }
10197   return result;
10198 }
10199
10200
10201 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10202   Isolate* isolate = script->GetIsolate();
10203   if (!script->wrapper()->IsUndefined()) {
10204     DCHECK(script->wrapper()->IsWeakCell());
10205     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
10206     if (!cell->cleared()) {
10207       // Return a handle for the existing script wrapper from the cache.
10208       return handle(JSObject::cast(cell->value()));
10209     }
10210     // If we found an empty WeakCell, that means the script wrapper was
10211     // GCed.  We are not notified directly of that, so we decrement here
10212     // so that we at least don't count double for any given script.
10213     isolate->counters()->script_wrappers()->Decrement();
10214   }
10215   // Construct a new script wrapper.
10216   isolate->counters()->script_wrappers()->Increment();
10217   Handle<JSFunction> constructor = isolate->script_function();
10218   Handle<JSValue> result =
10219       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10220   result->set_value(*script);
10221   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
10222   script->set_wrapper(*cell);
10223   return result;
10224 }
10225
10226
10227 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
10228     FunctionLiteral* fun) {
10229   if (shared_function_infos()->IsWeakFixedArray()) {
10230     WeakFixedArray* array = WeakFixedArray::cast(shared_function_infos());
10231     for (int i = 0; i < array->Length(); i++) {
10232       Object* obj = array->Get(i);
10233       if (!obj->IsSharedFunctionInfo()) continue;
10234       SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
10235       if (fun->function_token_position() == shared->function_token_position() &&
10236           fun->start_position() == shared->start_position()) {
10237         return Handle<SharedFunctionInfo>(shared);
10238       }
10239     }
10240   }
10241   return MaybeHandle<SharedFunctionInfo>();
10242 }
10243
10244
10245 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
10246                                    Handle<Object> script_object) {
10247   if (shared->script() == *script_object) return;
10248   // Remove shared function info from old script's list.
10249   if (shared->script()->IsScript()) {
10250     Script* old_script = Script::cast(shared->script());
10251     if (old_script->shared_function_infos()->IsWeakFixedArray()) {
10252       WeakFixedArray* list =
10253           WeakFixedArray::cast(old_script->shared_function_infos());
10254       list->Remove(shared);
10255     }
10256   }
10257   // Add shared function info to new script's list.
10258   if (script_object->IsScript()) {
10259     Handle<Script> script = Handle<Script>::cast(script_object);
10260     Handle<Object> list(script->shared_function_infos(), shared->GetIsolate());
10261 #ifdef DEBUG
10262     bool found = false;
10263     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAddIfNotFound,
10264                                &found);
10265     CHECK(!found);
10266 #else
10267     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAlwaysAdd);
10268 #endif  // DEBUG
10269     script->set_shared_function_infos(*list);
10270   }
10271   // Finally set new script.
10272   shared->set_script(*script_object);
10273 }
10274
10275
10276 String* SharedFunctionInfo::DebugName() {
10277   Object* n = name();
10278   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10279   return String::cast(n);
10280 }
10281
10282
10283 bool SharedFunctionInfo::HasSourceCode() const {
10284   return !script()->IsUndefined() &&
10285          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10286 }
10287
10288
10289 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10290   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10291   Handle<String> source(String::cast(Script::cast(script())->source()));
10292   return GetIsolate()->factory()->NewSubString(
10293       source, start_position(), end_position());
10294 }
10295
10296
10297 bool SharedFunctionInfo::IsInlineable() {
10298   // Check that the function has a script associated with it.
10299   if (!script()->IsScript()) return false;
10300   return !optimization_disabled();
10301 }
10302
10303
10304 int SharedFunctionInfo::SourceSize() {
10305   return end_position() - start_position();
10306 }
10307
10308
10309 int SharedFunctionInfo::CalculateInstanceSize() {
10310   int instance_size =
10311       JSObject::kHeaderSize +
10312       expected_nof_properties() * kPointerSize;
10313   if (instance_size > JSObject::kMaxInstanceSize) {
10314     instance_size = JSObject::kMaxInstanceSize;
10315   }
10316   return instance_size;
10317 }
10318
10319
10320 int SharedFunctionInfo::CalculateInObjectProperties() {
10321   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10322 }
10323
10324
10325 // Output the source code without any allocation in the heap.
10326 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
10327   const SharedFunctionInfo* s = v.value;
10328   // For some native functions there is no source.
10329   if (!s->HasSourceCode()) return os << "<No Source>";
10330
10331   // Get the source for the script which this function came from.
10332   // Don't use String::cast because we don't want more assertion errors while
10333   // we are already creating a stack dump.
10334   String* script_source =
10335       reinterpret_cast<String*>(Script::cast(s->script())->source());
10336
10337   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10338
10339   if (!s->is_toplevel()) {
10340     os << "function ";
10341     Object* name = s->name();
10342     if (name->IsString() && String::cast(name)->length() > 0) {
10343       String::cast(name)->PrintUC16(os);
10344     }
10345   }
10346
10347   int len = s->end_position() - s->start_position();
10348   if (len <= v.max_length || v.max_length < 0) {
10349     script_source->PrintUC16(os, s->start_position(), s->end_position());
10350     return os;
10351   } else {
10352     script_source->PrintUC16(os, s->start_position(),
10353                              s->start_position() + v.max_length);
10354     return os << "...\n";
10355   }
10356 }
10357
10358
10359 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10360   if (code->instruction_size() != recompiled->instruction_size()) return false;
10361   ByteArray* code_relocation = code->relocation_info();
10362   ByteArray* recompiled_relocation = recompiled->relocation_info();
10363   int length = code_relocation->length();
10364   if (length != recompiled_relocation->length()) return false;
10365   int compare = memcmp(code_relocation->GetDataStartAddress(),
10366                        recompiled_relocation->GetDataStartAddress(),
10367                        length);
10368   return compare == 0;
10369 }
10370
10371
10372 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10373   DCHECK(!has_deoptimization_support());
10374   DisallowHeapAllocation no_allocation;
10375   Code* code = this->code();
10376   if (IsCodeEquivalent(code, recompiled)) {
10377     // Copy the deoptimization data from the recompiled code.
10378     code->set_deoptimization_data(recompiled->deoptimization_data());
10379     code->set_has_deoptimization_support(true);
10380   } else {
10381     // TODO(3025757): In case the recompiled isn't equivalent to the
10382     // old code, we have to replace it. We should try to avoid this
10383     // altogether because it flushes valuable type feedback by
10384     // effectively resetting all IC state.
10385     ReplaceCode(recompiled);
10386   }
10387   DCHECK(has_deoptimization_support());
10388 }
10389
10390
10391 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10392   // Disable optimization for the shared function info and mark the
10393   // code as non-optimizable. The marker on the shared function info
10394   // is there because we flush non-optimized code thereby loosing the
10395   // non-optimizable information for the code. When the code is
10396   // regenerated and set on the shared function info it is marked as
10397   // non-optimizable if optimization is disabled for the shared
10398   // function info.
10399   DCHECK(reason != kNoReason);
10400   set_optimization_disabled(true);
10401   set_disable_optimization_reason(reason);
10402   // Code should be the lazy compilation stub or else unoptimized.
10403   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10404   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10405   if (FLAG_trace_opt) {
10406     PrintF("[disabled optimization for ");
10407     ShortPrint();
10408     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10409   }
10410 }
10411
10412
10413 void SharedFunctionInfo::InitFromFunctionLiteral(
10414     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
10415   shared_info->set_length(lit->scope()->default_function_length());
10416   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
10417   shared_info->set_function_token_position(lit->function_token_position());
10418   shared_info->set_start_position(lit->start_position());
10419   shared_info->set_end_position(lit->end_position());
10420   shared_info->set_is_expression(lit->is_expression());
10421   shared_info->set_is_anonymous(lit->is_anonymous());
10422   shared_info->set_inferred_name(*lit->inferred_name());
10423   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
10424   shared_info->set_allows_lazy_compilation_without_context(
10425       lit->AllowsLazyCompilationWithoutContext());
10426   shared_info->set_language_mode(lit->language_mode());
10427   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
10428   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
10429   shared_info->set_ast_node_count(lit->ast_node_count());
10430   shared_info->set_is_function(lit->is_function());
10431   if (lit->dont_optimize_reason() != kNoReason) {
10432     shared_info->DisableOptimization(lit->dont_optimize_reason());
10433   }
10434   shared_info->set_dont_crankshaft(lit->flags() &
10435                                    AstProperties::kDontCrankshaft);
10436   shared_info->set_kind(lit->kind());
10437   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
10438   shared_info->set_asm_function(lit->scope()->asm_function());
10439 }
10440
10441
10442 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10443   DCHECK(!id.IsNone());
10444   Code* unoptimized = code();
10445   DeoptimizationOutputData* data =
10446       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10447   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10448   USE(ignore);
10449   return true;  // Return true if there was no DCHECK.
10450 }
10451
10452
10453 void JSFunction::StartInobjectSlackTracking() {
10454   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10455
10456   Map* map = initial_map();
10457
10458   // No tracking during the snapshot construction phase.
10459   Isolate* isolate = GetIsolate();
10460   if (isolate->serializer_enabled()) return;
10461
10462   if (map->unused_property_fields() == 0) return;
10463
10464   map->set_counter(Map::kSlackTrackingCounterStart);
10465 }
10466
10467
10468 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10469   code()->ClearInlineCaches();
10470   // If we clear ICs, we need to clear the type feedback vector too, since
10471   // CallICs are synced with a feedback vector slot.
10472   ClearTypeFeedbackInfo();
10473   set_ic_age(new_ic_age);
10474   if (code()->kind() == Code::FUNCTION) {
10475     code()->set_profiler_ticks(0);
10476     if (optimization_disabled() &&
10477         opt_count() >= FLAG_max_opt_count) {
10478       // Re-enable optimizations if they were disabled due to opt_count limit.
10479       set_optimization_disabled(false);
10480     }
10481     set_opt_count(0);
10482     set_deopt_count(0);
10483   }
10484 }
10485
10486
10487 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
10488     Context* native_context, BailoutId osr_ast_id) {
10489   DisallowHeapAllocation no_gc;
10490   DCHECK(native_context->IsNativeContext());
10491   Object* value = optimized_code_map();
10492   if (!value->IsSmi()) {
10493     FixedArray* optimized_code_map = FixedArray::cast(value);
10494     int length = optimized_code_map->length();
10495     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10496     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10497       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10498           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10499         return {Code::cast(optimized_code_map->get(i + kCachedCodeOffset)),
10500                 FixedArray::cast(optimized_code_map->get(i + kLiteralsOffset))};
10501       }
10502     }
10503     Object* shared_code = optimized_code_map->get(kSharedCodeIndex);
10504     if (shared_code->IsCode() && osr_ast_id.IsNone()) {
10505       return {Code::cast(shared_code), nullptr};
10506     }
10507     if (FLAG_trace_opt) {
10508       PrintF("[didn't find optimized code in optimized code map for ");
10509       ShortPrint();
10510       PrintF("]\n");
10511     }
10512   }
10513   return {nullptr, nullptr};
10514 }
10515
10516
10517 #define DECLARE_TAG(ignore1, name, ignore2) name,
10518 const char* const VisitorSynchronization::kTags[
10519     VisitorSynchronization::kNumberOfSyncTags] = {
10520   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10521 };
10522 #undef DECLARE_TAG
10523
10524
10525 #define DECLARE_TAG(ignore1, ignore2, name) name,
10526 const char* const VisitorSynchronization::kTagNames[
10527     VisitorSynchronization::kNumberOfSyncTags] = {
10528   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10529 };
10530 #undef DECLARE_TAG
10531
10532
10533 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10534   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10535   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10536   Object* old_target = target;
10537   VisitPointer(&target);
10538   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10539 }
10540
10541
10542 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10543   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10544   Object* stub = rinfo->code_age_stub();
10545   if (stub) {
10546     VisitPointer(&stub);
10547   }
10548 }
10549
10550
10551 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10552   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10553   Object* old_code = code;
10554   VisitPointer(&code);
10555   if (code != old_code) {
10556     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10557   }
10558 }
10559
10560
10561 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10562   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10563   Object* cell = rinfo->target_cell();
10564   Object* old_cell = cell;
10565   VisitPointer(&cell);
10566   if (cell != old_cell) {
10567     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10568   }
10569 }
10570
10571
10572 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10573   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10574          rinfo->IsPatchedDebugBreakSlotSequence());
10575   Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
10576   Object* old_target = target;
10577   VisitPointer(&target);
10578   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10579 }
10580
10581
10582 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10583   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10584   Object* p = rinfo->target_object();
10585   VisitPointer(&p);
10586 }
10587
10588
10589 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10590   Address p = rinfo->target_external_reference();
10591   VisitExternalReference(&p);
10592 }
10593
10594
10595 void Code::InvalidateRelocation() {
10596   InvalidateEmbeddedObjects();
10597   set_relocation_info(GetHeap()->empty_byte_array());
10598 }
10599
10600
10601 void Code::InvalidateEmbeddedObjects() {
10602   Object* undefined = GetHeap()->undefined_value();
10603   Cell* undefined_cell = GetHeap()->undefined_cell();
10604   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10605                   RelocInfo::ModeMask(RelocInfo::CELL);
10606   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10607     RelocInfo::Mode mode = it.rinfo()->rmode();
10608     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10609       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10610     } else if (mode == RelocInfo::CELL) {
10611       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10612     }
10613   }
10614 }
10615
10616
10617 void Code::Relocate(intptr_t delta) {
10618   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10619     it.rinfo()->apply(delta);
10620   }
10621   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10622 }
10623
10624
10625 void Code::CopyFrom(const CodeDesc& desc) {
10626   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10627
10628   // copy code
10629   CopyBytes(instruction_start(), desc.buffer,
10630             static_cast<size_t>(desc.instr_size));
10631
10632   // copy reloc info
10633   CopyBytes(relocation_start(),
10634             desc.buffer + desc.buffer_size - desc.reloc_size,
10635             static_cast<size_t>(desc.reloc_size));
10636
10637   // unbox handles and relocate
10638   intptr_t delta = instruction_start() - desc.buffer;
10639   int mode_mask = RelocInfo::kCodeTargetMask |
10640                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10641                   RelocInfo::ModeMask(RelocInfo::CELL) |
10642                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10643                   RelocInfo::kApplyMask;
10644   // Needed to find target_object and runtime_entry on X64
10645   Assembler* origin = desc.origin;
10646   AllowDeferredHandleDereference embedding_raw_address;
10647   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10648     RelocInfo::Mode mode = it.rinfo()->rmode();
10649     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10650       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10651       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10652     } else if (mode == RelocInfo::CELL) {
10653       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10654       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10655     } else if (RelocInfo::IsCodeTarget(mode)) {
10656       // rewrite code handles in inline cache targets to direct
10657       // pointers to the first instruction in the code object
10658       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10659       Code* code = Code::cast(*p);
10660       it.rinfo()->set_target_address(code->instruction_start(),
10661                                      SKIP_WRITE_BARRIER,
10662                                      SKIP_ICACHE_FLUSH);
10663     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10664       Address p = it.rinfo()->target_runtime_entry(origin);
10665       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10666                                            SKIP_ICACHE_FLUSH);
10667     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10668       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10669       Code* code = Code::cast(*p);
10670       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10671     } else {
10672       it.rinfo()->apply(delta);
10673     }
10674   }
10675   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10676 }
10677
10678
10679 // Locate the source position which is closest to the address in the code. This
10680 // is using the source position information embedded in the relocation info.
10681 // The position returned is relative to the beginning of the script where the
10682 // source for this function is found.
10683 int Code::SourcePosition(Address pc) {
10684   int distance = kMaxInt;
10685   int position = RelocInfo::kNoPosition;  // Initially no position found.
10686   // Run through all the relocation info to find the best matching source
10687   // position. All the code needs to be considered as the sequence of the
10688   // instructions in the code does not necessarily follow the same order as the
10689   // source.
10690   RelocIterator it(this, RelocInfo::kPositionMask);
10691   while (!it.done()) {
10692     // Only look at positions after the current pc.
10693     if (it.rinfo()->pc() < pc) {
10694       // Get position and distance.
10695
10696       int dist = static_cast<int>(pc - it.rinfo()->pc());
10697       int pos = static_cast<int>(it.rinfo()->data());
10698       // If this position is closer than the current candidate or if it has the
10699       // same distance as the current candidate and the position is higher then
10700       // this position is the new candidate.
10701       if ((dist < distance) ||
10702           (dist == distance && pos > position)) {
10703         position = pos;
10704         distance = dist;
10705       }
10706     }
10707     it.next();
10708   }
10709   return position;
10710 }
10711
10712
10713 // Same as Code::SourcePosition above except it only looks for statement
10714 // positions.
10715 int Code::SourceStatementPosition(Address pc) {
10716   // First find the position as close as possible using all position
10717   // information.
10718   int position = SourcePosition(pc);
10719   // Now find the closest statement position before the position.
10720   int statement_position = 0;
10721   RelocIterator it(this, RelocInfo::kPositionMask);
10722   while (!it.done()) {
10723     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10724       int p = static_cast<int>(it.rinfo()->data());
10725       if (statement_position < p && p <= position) {
10726         statement_position = p;
10727       }
10728     }
10729     it.next();
10730   }
10731   return statement_position;
10732 }
10733
10734
10735 SafepointEntry Code::GetSafepointEntry(Address pc) {
10736   SafepointTable table(this);
10737   return table.FindEntry(pc);
10738 }
10739
10740
10741 Object* Code::FindNthObject(int n, Map* match_map) {
10742   DCHECK(is_inline_cache_stub());
10743   DisallowHeapAllocation no_allocation;
10744   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10745   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10746     RelocInfo* info = it.rinfo();
10747     Object* object = info->target_object();
10748     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10749     if (object->IsHeapObject()) {
10750       if (HeapObject::cast(object)->map() == match_map) {
10751         if (--n == 0) return object;
10752       }
10753     }
10754   }
10755   return NULL;
10756 }
10757
10758
10759 AllocationSite* Code::FindFirstAllocationSite() {
10760   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10761   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10762 }
10763
10764
10765 Map* Code::FindFirstMap() {
10766   Object* result = FindNthObject(1, GetHeap()->meta_map());
10767   return (result != NULL) ? Map::cast(result) : NULL;
10768 }
10769
10770
10771 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10772   DCHECK(is_inline_cache_stub() || is_handler());
10773   DisallowHeapAllocation no_allocation;
10774   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10775   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10776   int current_pattern = 0;
10777   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10778     RelocInfo* info = it.rinfo();
10779     Object* object = info->target_object();
10780     if (object->IsHeapObject()) {
10781       if (object->IsWeakCell()) {
10782         object = HeapObject::cast(WeakCell::cast(object)->value());
10783       }
10784       Map* map = HeapObject::cast(object)->map();
10785       if (map == *pattern.find_[current_pattern]) {
10786         info->set_target_object(*pattern.replace_[current_pattern]);
10787         if (++current_pattern == pattern.count_) return;
10788       }
10789     }
10790   }
10791   UNREACHABLE();
10792 }
10793
10794
10795 void Code::FindAllMaps(MapHandleList* maps) {
10796   DCHECK(is_inline_cache_stub());
10797   DisallowHeapAllocation no_allocation;
10798   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10799   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10800     RelocInfo* info = it.rinfo();
10801     Object* object = info->target_object();
10802     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10803     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10804   }
10805 }
10806
10807
10808 Code* Code::FindFirstHandler() {
10809   DCHECK(is_inline_cache_stub());
10810   DisallowHeapAllocation no_allocation;
10811   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10812              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10813   bool skip_next_handler = false;
10814   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10815     RelocInfo* info = it.rinfo();
10816     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10817       Object* obj = info->target_object();
10818       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10819     } else {
10820       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10821       if (code->kind() == Code::HANDLER) {
10822         if (!skip_next_handler) return code;
10823         skip_next_handler = false;
10824       }
10825     }
10826   }
10827   return NULL;
10828 }
10829
10830
10831 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10832   DCHECK(is_inline_cache_stub());
10833   DisallowHeapAllocation no_allocation;
10834   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10835              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10836   bool skip_next_handler = false;
10837   int i = 0;
10838   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10839     if (i == length) return true;
10840     RelocInfo* info = it.rinfo();
10841     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10842       Object* obj = info->target_object();
10843       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10844     } else {
10845       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10846       // IC stubs with handlers never contain non-handler code objects before
10847       // handler targets.
10848       if (code->kind() != Code::HANDLER) break;
10849       if (!skip_next_handler) {
10850         code_list->Add(Handle<Code>(code));
10851         i++;
10852       }
10853       skip_next_handler = false;
10854     }
10855   }
10856   return i == length;
10857 }
10858
10859
10860 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
10861   DCHECK(is_inline_cache_stub());
10862   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10863              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10864   bool return_next = false;
10865   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10866     RelocInfo* info = it.rinfo();
10867     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10868       Object* object = info->target_object();
10869       if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10870       if (object == map) return_next = true;
10871     } else if (return_next) {
10872       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10873       DCHECK(code->kind() == Code::HANDLER);
10874       return handle(code);
10875     }
10876   }
10877   return MaybeHandle<Code>();
10878 }
10879
10880
10881 Name* Code::FindFirstName() {
10882   DCHECK(is_inline_cache_stub());
10883   DisallowHeapAllocation no_allocation;
10884   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10885   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10886     RelocInfo* info = it.rinfo();
10887     Object* object = info->target_object();
10888     if (object->IsName()) return Name::cast(object);
10889   }
10890   return NULL;
10891 }
10892
10893
10894 void Code::ClearInlineCaches() {
10895   ClearInlineCaches(NULL);
10896 }
10897
10898
10899 void Code::ClearInlineCaches(Code::Kind kind) {
10900   ClearInlineCaches(&kind);
10901 }
10902
10903
10904 void Code::ClearInlineCaches(Code::Kind* kind) {
10905   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10906              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10907              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10908   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10909     RelocInfo* info = it.rinfo();
10910     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10911     if (target->is_inline_cache_stub()) {
10912       if (kind == NULL || *kind == target->kind()) {
10913         IC::Clear(this->GetIsolate(), info->pc(),
10914                   info->host()->constant_pool());
10915       }
10916     }
10917   }
10918 }
10919
10920
10921 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
10922   feedback_vector()->ClearSlots(this);
10923   feedback_vector()->ClearICSlots(this);
10924 }
10925
10926
10927 void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
10928   feedback_vector()->ClearSlotsAtGCTime(this);
10929   feedback_vector()->ClearICSlotsAtGCTime(this);
10930 }
10931
10932
10933 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
10934   DisallowHeapAllocation no_gc;
10935   DCHECK(kind() == FUNCTION);
10936   BackEdgeTable back_edges(this, &no_gc);
10937   for (uint32_t i = 0; i < back_edges.length(); i++) {
10938     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10939   }
10940   return BailoutId::None();
10941 }
10942
10943
10944 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
10945   DisallowHeapAllocation no_gc;
10946   DCHECK(kind() == FUNCTION);
10947   BackEdgeTable back_edges(this, &no_gc);
10948   for (uint32_t i = 0; i < back_edges.length(); i++) {
10949     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10950   }
10951   UNREACHABLE();  // We expect to find the back edge.
10952   return 0;
10953 }
10954
10955
10956 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10957   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10958 }
10959
10960
10961 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10962   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10963       NO_MARKING_PARITY);
10964 }
10965
10966
10967 // NextAge defines the Code::Age state transitions during a GC cycle.
10968 static Code::Age NextAge(Code::Age age) {
10969   switch (age) {
10970     case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
10971     case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
10972     case Code::kLastCodeAge:  // Clamp at last Code::Age value.
10973       return age;
10974     case Code::kExecutedOnceCodeAge:
10975       // Pre-age code that has only been executed once.
10976       return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
10977     default:
10978       return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
10979   }
10980 }
10981
10982
10983 // IsOldAge defines the collection criteria for a Code object.
10984 static bool IsOldAge(Code::Age age) {
10985   return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
10986 }
10987
10988
10989 void Code::MakeYoung(Isolate* isolate) {
10990   byte* sequence = FindCodeAgeSequence();
10991   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
10992 }
10993
10994
10995 void Code::MarkToBeExecutedOnce(Isolate* isolate) {
10996   byte* sequence = FindCodeAgeSequence();
10997   if (sequence != NULL) {
10998     PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
10999                          NO_MARKING_PARITY);
11000   }
11001 }
11002
11003
11004 void Code::MakeOlder(MarkingParity current_parity) {
11005   byte* sequence = FindCodeAgeSequence();
11006   if (sequence != NULL) {
11007     Age age;
11008     MarkingParity code_parity;
11009     Isolate* isolate = GetIsolate();
11010     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11011     Age next_age = NextAge(age);
11012     if (age != next_age && code_parity != current_parity) {
11013       PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
11014     }
11015   }
11016 }
11017
11018
11019 bool Code::IsOld() {
11020   return IsOldAge(GetAge());
11021 }
11022
11023
11024 byte* Code::FindCodeAgeSequence() {
11025   return FLAG_age_code &&
11026       prologue_offset() != Code::kPrologueOffsetNotSet &&
11027       (kind() == OPTIMIZED_FUNCTION ||
11028        (kind() == FUNCTION && !has_debug_break_slots()))
11029       ? instruction_start() + prologue_offset()
11030       : NULL;
11031 }
11032
11033
11034 Code::Age Code::GetAge() {
11035   byte* sequence = FindCodeAgeSequence();
11036   if (sequence == NULL) {
11037     return kNoAgeCodeAge;
11038   }
11039   Age age;
11040   MarkingParity parity;
11041   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11042   return age;
11043 }
11044
11045
11046 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11047                                MarkingParity* parity) {
11048   Isolate* isolate = code->GetIsolate();
11049   Builtins* builtins = isolate->builtins();
11050   Code* stub = NULL;
11051 #define HANDLE_CODE_AGE(AGE)                                            \
11052   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11053   if (code == stub) {                                                   \
11054     *age = k##AGE##CodeAge;                                             \
11055     *parity = EVEN_MARKING_PARITY;                                      \
11056     return;                                                             \
11057   }                                                                     \
11058   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11059   if (code == stub) {                                                   \
11060     *age = k##AGE##CodeAge;                                             \
11061     *parity = ODD_MARKING_PARITY;                                       \
11062     return;                                                             \
11063   }
11064   CODE_AGE_LIST(HANDLE_CODE_AGE)
11065 #undef HANDLE_CODE_AGE
11066   stub = *builtins->MarkCodeAsExecutedOnce();
11067   if (code == stub) {
11068     *age = kNotExecutedCodeAge;
11069     *parity = NO_MARKING_PARITY;
11070     return;
11071   }
11072   stub = *builtins->MarkCodeAsExecutedTwice();
11073   if (code == stub) {
11074     *age = kExecutedOnceCodeAge;
11075     *parity = NO_MARKING_PARITY;
11076     return;
11077   }
11078   stub = *builtins->MarkCodeAsToBeExecutedOnce();
11079   if (code == stub) {
11080     *age = kToBeExecutedOnceCodeAge;
11081     *parity = NO_MARKING_PARITY;
11082     return;
11083   }
11084   UNREACHABLE();
11085 }
11086
11087
11088 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11089   Builtins* builtins = isolate->builtins();
11090   switch (age) {
11091 #define HANDLE_CODE_AGE(AGE)                                            \
11092     case k##AGE##CodeAge: {                                             \
11093       Code* stub = parity == EVEN_MARKING_PARITY                        \
11094           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11095           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11096       return stub;                                                      \
11097     }
11098     CODE_AGE_LIST(HANDLE_CODE_AGE)
11099 #undef HANDLE_CODE_AGE
11100     case kNotExecutedCodeAge: {
11101       DCHECK(parity == NO_MARKING_PARITY);
11102       return *builtins->MarkCodeAsExecutedOnce();
11103     }
11104     case kExecutedOnceCodeAge: {
11105       DCHECK(parity == NO_MARKING_PARITY);
11106       return *builtins->MarkCodeAsExecutedTwice();
11107     }
11108     case kToBeExecutedOnceCodeAge: {
11109       DCHECK(parity == NO_MARKING_PARITY);
11110       return *builtins->MarkCodeAsToBeExecutedOnce();
11111     }
11112     default:
11113       UNREACHABLE();
11114       break;
11115   }
11116   return NULL;
11117 }
11118
11119
11120 void Code::PrintDeoptLocation(FILE* out, Address pc) {
11121   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
11122   class SourcePosition pos = info.position;
11123   if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
11124     if (FLAG_hydrogen_track_positions) {
11125       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
11126              pos.inlining_id(), pos.position(),
11127              Deoptimizer::GetDeoptReason(info.deopt_reason));
11128     } else {
11129       PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
11130              Deoptimizer::GetDeoptReason(info.deopt_reason));
11131     }
11132   }
11133 }
11134
11135
11136 bool Code::CanDeoptAt(Address pc) {
11137   DeoptimizationInputData* deopt_data =
11138       DeoptimizationInputData::cast(deoptimization_data());
11139   Address code_start_address = instruction_start();
11140   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11141     if (deopt_data->Pc(i)->value() == -1) continue;
11142     Address address = code_start_address + deopt_data->Pc(i)->value();
11143     if (address == pc) return true;
11144   }
11145   return false;
11146 }
11147
11148
11149 // Identify kind of code.
11150 const char* Code::Kind2String(Kind kind) {
11151   switch (kind) {
11152 #define CASE(name) case name: return #name;
11153     CODE_KIND_LIST(CASE)
11154 #undef CASE
11155     case NUMBER_OF_KINDS: break;
11156   }
11157   UNREACHABLE();
11158   return NULL;
11159 }
11160
11161
11162 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
11163   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
11164   WeakCell* raw_cell = code->CachedWeakCell();
11165   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
11166   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
11167   DeoptimizationInputData::cast(code->deoptimization_data())
11168       ->SetWeakCellCache(*cell);
11169   return cell;
11170 }
11171
11172
11173 WeakCell* Code::CachedWeakCell() {
11174   DCHECK(kind() == OPTIMIZED_FUNCTION);
11175   Object* weak_cell_cache =
11176       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
11177   if (weak_cell_cache->IsWeakCell()) {
11178     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
11179     return WeakCell::cast(weak_cell_cache);
11180   }
11181   return NULL;
11182 }
11183
11184
11185 #ifdef ENABLE_DISASSEMBLER
11186
11187 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11188     std::ostream& os) {  // NOLINT
11189   disasm::NameConverter converter;
11190   int const inlined_function_count = InlinedFunctionCount()->value();
11191   os << "Inlined functions (count = " << inlined_function_count << ")\n";
11192   for (int id = 0; id < inlined_function_count; ++id) {
11193     Object* info = LiteralArray()->get(id);
11194     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
11195   }
11196   os << "\n";
11197   int deopt_count = DeoptCount();
11198   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11199   if (0 != deopt_count) {
11200     os << " index  ast id    argc     pc";
11201     if (FLAG_print_code_verbose) os << "  commands";
11202     os << "\n";
11203   }
11204   for (int i = 0; i < deopt_count; i++) {
11205     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
11206        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
11207        << std::setw(6) << Pc(i)->value();
11208
11209     if (!FLAG_print_code_verbose) {
11210       os << "\n";
11211       continue;
11212     }
11213     // Print details of the frame translation.
11214     int translation_index = TranslationIndex(i)->value();
11215     TranslationIterator iterator(TranslationByteArray(), translation_index);
11216     Translation::Opcode opcode =
11217         static_cast<Translation::Opcode>(iterator.Next());
11218     DCHECK(Translation::BEGIN == opcode);
11219     int frame_count = iterator.Next();
11220     int jsframe_count = iterator.Next();
11221     os << "  " << Translation::StringFor(opcode)
11222        << " {frame count=" << frame_count
11223        << ", js frame count=" << jsframe_count << "}\n";
11224
11225     while (iterator.HasNext() &&
11226            Translation::BEGIN !=
11227            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11228       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
11229
11230       switch (opcode) {
11231         case Translation::BEGIN:
11232           UNREACHABLE();
11233           break;
11234
11235         case Translation::JS_FRAME: {
11236           int ast_id = iterator.Next();
11237           int shared_info_id = iterator.Next();
11238           unsigned height = iterator.Next();
11239           Object* shared_info = LiteralArray()->get(shared_info_id);
11240           os << "{ast_id=" << ast_id << ", function="
11241              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11242              << ", height=" << height << "}";
11243           break;
11244         }
11245
11246         case Translation::JS_FRAME_FUNCTION: {
11247           os << "{function}";
11248           break;
11249         }
11250
11251         case Translation::COMPILED_STUB_FRAME: {
11252           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11253           os << "{kind=" << stub_kind << "}";
11254           break;
11255         }
11256
11257         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11258         case Translation::CONSTRUCT_STUB_FRAME: {
11259           int shared_info_id = iterator.Next();
11260           Object* shared_info = LiteralArray()->get(shared_info_id);
11261           unsigned height = iterator.Next();
11262           os << "{function="
11263              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11264              << ", height=" << height << "}";
11265           break;
11266         }
11267
11268         case Translation::GETTER_STUB_FRAME:
11269         case Translation::SETTER_STUB_FRAME: {
11270           int shared_info_id = iterator.Next();
11271           Object* shared_info = LiteralArray()->get(shared_info_id);
11272           os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
11273                                           ->DebugName()) << "}";
11274           break;
11275         }
11276
11277         case Translation::REGISTER: {
11278           int reg_code = iterator.Next();
11279           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11280           break;
11281         }
11282
11283         case Translation::INT32_REGISTER: {
11284           int reg_code = iterator.Next();
11285           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11286           break;
11287         }
11288
11289         case Translation::UINT32_REGISTER: {
11290           int reg_code = iterator.Next();
11291           os << "{input=" << converter.NameOfCPURegister(reg_code)
11292              << " (unsigned)}";
11293           break;
11294         }
11295
11296         case Translation::BOOL_REGISTER: {
11297           int reg_code = iterator.Next();
11298           os << "{input=" << converter.NameOfCPURegister(reg_code)
11299              << " (bool)}";
11300           break;
11301         }
11302
11303         case Translation::DOUBLE_REGISTER: {
11304           int reg_code = iterator.Next();
11305           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11306              << "}";
11307           break;
11308         }
11309
11310         case Translation::STACK_SLOT: {
11311           int input_slot_index = iterator.Next();
11312           os << "{input=" << input_slot_index << "}";
11313           break;
11314         }
11315
11316         case Translation::INT32_STACK_SLOT: {
11317           int input_slot_index = iterator.Next();
11318           os << "{input=" << input_slot_index << "}";
11319           break;
11320         }
11321
11322         case Translation::UINT32_STACK_SLOT: {
11323           int input_slot_index = iterator.Next();
11324           os << "{input=" << input_slot_index << " (unsigned)}";
11325           break;
11326         }
11327
11328         case Translation::BOOL_STACK_SLOT: {
11329           int input_slot_index = iterator.Next();
11330           os << "{input=" << input_slot_index << " (bool)}";
11331           break;
11332         }
11333
11334         case Translation::DOUBLE_STACK_SLOT: {
11335           int input_slot_index = iterator.Next();
11336           os << "{input=" << input_slot_index << "}";
11337           break;
11338         }
11339
11340         case Translation::LITERAL: {
11341           unsigned literal_index = iterator.Next();
11342           os << "{literal_id=" << literal_index << "}";
11343           break;
11344         }
11345
11346         case Translation::DUPLICATED_OBJECT: {
11347           int object_index = iterator.Next();
11348           os << "{object_index=" << object_index << "}";
11349           break;
11350         }
11351
11352         case Translation::ARGUMENTS_OBJECT:
11353         case Translation::CAPTURED_OBJECT: {
11354           int args_length = iterator.Next();
11355           os << "{length=" << args_length << "}";
11356           break;
11357         }
11358       }
11359       os << "\n";
11360     }
11361   }
11362 }
11363
11364
11365 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11366     std::ostream& os) {  // NOLINT
11367   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11368      << ")\n";
11369   if (this->DeoptPoints() == 0) return;
11370
11371   os << "ast id        pc  state\n";
11372   for (int i = 0; i < this->DeoptPoints(); i++) {
11373     int pc_and_state = this->PcAndState(i)->value();
11374     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
11375        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
11376        << FullCodeGenerator::State2String(
11377               FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
11378   }
11379 }
11380
11381
11382 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
11383   os << "   from   to       hdlr\n";
11384   for (int i = 0; i < length(); i += kRangeEntrySize) {
11385     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
11386     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
11387     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
11388     int handler_offset = HandlerOffsetField::decode(handler_field);
11389     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11390     int depth = Smi::cast(get(i + kRangeDepthIndex))->value();
11391     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
11392        << ")  ->  " << std::setw(4) << handler_offset
11393        << " (prediction=" << prediction << ", depth=" << depth << ")\n";
11394   }
11395 }
11396
11397
11398 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
11399   os << "   off      hdlr (c)\n";
11400   for (int i = 0; i < length(); i += kReturnEntrySize) {
11401     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
11402     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
11403     int handler_offset = HandlerOffsetField::decode(handler_field);
11404     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11405     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
11406        << handler_offset << " (prediction=" << prediction << ")\n";
11407   }
11408 }
11409
11410
11411 const char* Code::ICState2String(InlineCacheState state) {
11412   switch (state) {
11413     case UNINITIALIZED: return "UNINITIALIZED";
11414     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11415     case MONOMORPHIC: return "MONOMORPHIC";
11416     case PROTOTYPE_FAILURE:
11417       return "PROTOTYPE_FAILURE";
11418     case POLYMORPHIC: return "POLYMORPHIC";
11419     case MEGAMORPHIC: return "MEGAMORPHIC";
11420     case GENERIC: return "GENERIC";
11421     case DEBUG_STUB: return "DEBUG_STUB";
11422     case DEFAULT:
11423       return "DEFAULT";
11424   }
11425   UNREACHABLE();
11426   return NULL;
11427 }
11428
11429
11430 const char* Code::StubType2String(StubType type) {
11431   switch (type) {
11432     case NORMAL: return "NORMAL";
11433     case FAST: return "FAST";
11434   }
11435   UNREACHABLE();  // keep the compiler happy
11436   return NULL;
11437 }
11438
11439
11440 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
11441                              Kind kind, ExtraICState extra) {
11442   os << "extra_ic_state = ";
11443   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
11444       is_strict(static_cast<LanguageMode>(extra))) {
11445     os << "STRICT\n";
11446   } else {
11447     os << extra << "\n";
11448   }
11449 }
11450
11451
11452 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
11453   os << "kind = " << Kind2String(kind()) << "\n";
11454   if (IsCodeStubOrIC()) {
11455     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11456     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11457   }
11458   if (is_inline_cache_stub()) {
11459     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11460     PrintExtraICState(os, kind(), extra_ic_state());
11461     if (ic_state() == MONOMORPHIC) {
11462       os << "type = " << StubType2String(type()) << "\n";
11463     }
11464     if (is_compare_ic_stub()) {
11465       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11466       CompareICStub stub(stub_key(), GetIsolate());
11467       os << "compare_state = " << CompareICState::GetStateName(stub.left())
11468          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
11469          << CompareICState::GetStateName(stub.state()) << "\n";
11470       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
11471     }
11472   }
11473   if ((name != NULL) && (name[0] != '\0')) {
11474     os << "name = " << name << "\n";
11475   }
11476   if (kind() == OPTIMIZED_FUNCTION) {
11477     os << "stack_slots = " << stack_slots() << "\n";
11478   }
11479   os << "compiler = " << (is_turbofanned()
11480                               ? "turbofan"
11481                               : is_crankshafted() ? "crankshaft"
11482                                                   : kind() == Code::FUNCTION
11483                                                         ? "full-codegen"
11484                                                         : "unknown") << "\n";
11485
11486   os << "Instructions (size = " << instruction_size() << ")\n";
11487   {
11488     Isolate* isolate = GetIsolate();
11489     int size = instruction_size();
11490     int safepoint_offset =
11491         is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
11492     int back_edge_offset = (kind() == Code::FUNCTION)
11493                                ? static_cast<int>(back_edge_table_offset())
11494                                : size;
11495     int constant_pool_offset = FLAG_enable_embedded_constant_pool
11496                                    ? this->constant_pool_offset()
11497                                    : size;
11498
11499     // Stop before reaching any embedded tables
11500     int code_size = Min(safepoint_offset, back_edge_offset);
11501     code_size = Min(code_size, constant_pool_offset);
11502     byte* begin = instruction_start();
11503     byte* end = begin + code_size;
11504     Disassembler::Decode(isolate, &os, begin, end, this);
11505
11506     if (constant_pool_offset < size) {
11507       int constant_pool_size = size - constant_pool_offset;
11508       DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
11509       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
11510       Vector<char> buf = Vector<char>::New(50);
11511       intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
11512       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
11513         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
11514         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
11515       }
11516     }
11517   }
11518   os << "\n";
11519
11520   if (kind() == FUNCTION) {
11521     DeoptimizationOutputData* data =
11522         DeoptimizationOutputData::cast(this->deoptimization_data());
11523     data->DeoptimizationOutputDataPrint(os);
11524   } else if (kind() == OPTIMIZED_FUNCTION) {
11525     DeoptimizationInputData* data =
11526         DeoptimizationInputData::cast(this->deoptimization_data());
11527     data->DeoptimizationInputDataPrint(os);
11528   }
11529   os << "\n";
11530
11531   if (is_crankshafted()) {
11532     SafepointTable table(this);
11533     os << "Safepoints (size = " << table.size() << ")\n";
11534     for (unsigned i = 0; i < table.length(); i++) {
11535       unsigned pc_offset = table.GetPcOffset(i);
11536       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
11537       os << std::setw(4) << pc_offset << "  ";
11538       table.PrintEntry(i, os);
11539       os << " (sp -> fp)  ";
11540       SafepointEntry entry = table.GetEntry(i);
11541       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11542         os << std::setw(6) << entry.deoptimization_index();
11543       } else {
11544         os << "<none>";
11545       }
11546       if (entry.argument_count() > 0) {
11547         os << " argc: " << entry.argument_count();
11548       }
11549       os << "\n";
11550     }
11551     os << "\n";
11552   } else if (kind() == FUNCTION) {
11553     unsigned offset = back_edge_table_offset();
11554     // If there is no back edge table, the "table start" will be at or after
11555     // (due to alignment) the end of the instruction stream.
11556     if (static_cast<int>(offset) < instruction_size()) {
11557       DisallowHeapAllocation no_gc;
11558       BackEdgeTable back_edges(this, &no_gc);
11559
11560       os << "Back edges (size = " << back_edges.length() << ")\n";
11561       os << "ast_id  pc_offset  loop_depth\n";
11562
11563       for (uint32_t i = 0; i < back_edges.length(); i++) {
11564         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
11565            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
11566            << back_edges.loop_depth(i) << "\n";
11567       }
11568
11569       os << "\n";
11570     }
11571 #ifdef OBJECT_PRINT
11572     if (!type_feedback_info()->IsUndefined()) {
11573       OFStream os(stdout);
11574       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11575       os << "\n";
11576     }
11577 #endif
11578   }
11579
11580   if (handler_table()->length() > 0) {
11581     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
11582     if (kind() == FUNCTION) {
11583       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
11584     } else if (kind() == OPTIMIZED_FUNCTION) {
11585       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
11586     }
11587     os << "\n";
11588   }
11589
11590   os << "RelocInfo (size = " << relocation_size() << ")\n";
11591   for (RelocIterator it(this); !it.done(); it.next()) {
11592     it.rinfo()->Print(GetIsolate(), os);
11593   }
11594   os << "\n";
11595 }
11596 #endif  // ENABLE_DISASSEMBLER
11597
11598
11599 void BytecodeArray::Disassemble(std::ostream& os) {
11600   os << "Frame size " << frame_size() << "\n";
11601   Vector<char> buf = Vector<char>::New(50);
11602   int bytecode_size = 0;
11603   for (int i = 0; i < this->length(); i += bytecode_size) {
11604     interpreter::Bytecode bytecode = static_cast<interpreter::Bytecode>(get(i));
11605     bytecode_size = interpreter::Bytecodes::Size(bytecode);
11606
11607     SNPrintF(buf, "%p : ", GetFirstBytecodeAddress() + i);
11608     os << buf.start();
11609     for (int j = 0; j < bytecode_size; j++) {
11610       SNPrintF(buf, "%02x ", get(i + j));
11611       os << buf.start();
11612     }
11613     for (int j = bytecode_size; j < interpreter::Bytecodes::kMaximumSize; j++) {
11614       os << "   ";
11615     }
11616     os << bytecode << "\n";
11617   }
11618 }
11619
11620
11621 // static
11622 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11623   DCHECK(capacity >= 0);
11624   array->GetIsolate()->factory()->NewJSArrayStorage(
11625       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11626 }
11627
11628
11629 // Returns false if the passed-in index is marked non-configurable, which will
11630 // cause the truncation operation to halt, and thus no further old values need
11631 // be collected.
11632 static bool GetOldValue(Isolate* isolate,
11633                         Handle<JSObject> object,
11634                         uint32_t index,
11635                         List<Handle<Object> >* old_values,
11636                         List<uint32_t>* indices) {
11637   LookupIterator it(isolate, object, index, LookupIterator::HIDDEN);
11638   CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
11639   DCHECK(it.IsFound());
11640   if (!it.IsConfigurable()) return false;
11641   Handle<Object> value =
11642       it.state() == LookupIterator::ACCESSOR
11643           ? Handle<Object>::cast(isolate->factory()->the_hole_value())
11644           : JSReceiver::GetDataProperty(&it);
11645   old_values->Add(value);
11646   indices->Add(index);
11647   return true;
11648 }
11649
11650
11651 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
11652   // We should never end in here with a pixel or external array.
11653   DCHECK(array->AllowsSetLength());
11654   if (array->SetLengthWouldNormalize(new_length)) {
11655     JSObject::NormalizeElements(array);
11656   }
11657   array->GetElementsAccessor()->SetLength(array, new_length);
11658 }
11659
11660
11661 MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
11662                                                  uint32_t new_length) {
11663   if (!array->map()->is_observed()) {
11664     SetLength(array, new_length);
11665     return array;
11666   }
11667
11668   Isolate* isolate = array->GetIsolate();
11669   List<uint32_t> indices;
11670   List<Handle<Object> > old_values;
11671   Handle<Object> old_length_handle(array->length(), isolate);
11672   uint32_t old_length = 0;
11673   CHECK(old_length_handle->ToArrayLength(&old_length));
11674
11675   static const PropertyAttributes kNoAttrFilter = NONE;
11676   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11677   if (num_elements > 0) {
11678     if (old_length == static_cast<uint32_t>(num_elements)) {
11679       // Simple case for arrays without holes.
11680       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11681         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11682       }
11683     } else {
11684       // For sparse arrays, only iterate over existing elements.
11685       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11686       // the to-be-removed indices twice.
11687       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11688       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11689       while (num_elements-- > 0) {
11690         uint32_t index = NumberToUint32(keys->get(num_elements));
11691         if (index < new_length) break;
11692         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11693       }
11694     }
11695   }
11696
11697   SetLength(array, new_length);
11698
11699   CHECK(array->length()->ToArrayLength(&new_length));
11700   if (old_length == new_length) return array;
11701
11702   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
11703
11704   for (int i = 0; i < indices.length(); ++i) {
11705     // For deletions where the property was an accessor, old_values[i]
11706     // will be the hole, which instructs EnqueueChangeRecord to elide
11707     // the "oldValue" property.
11708     RETURN_ON_EXCEPTION(
11709         isolate,
11710         JSObject::EnqueueChangeRecord(
11711             array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11712             old_values[i]),
11713         Object);
11714   }
11715
11716   RETURN_ON_EXCEPTION(isolate,
11717                       JSObject::EnqueueChangeRecord(
11718                           array, "update", isolate->factory()->length_string(),
11719                           old_length_handle),
11720                       Object);
11721
11722   RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
11723
11724   uint32_t index = Min(old_length, new_length);
11725   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11726   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11727   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11728   if (delete_count > 0) {
11729     for (int i = indices.length() - 1; i >= 0; i--) {
11730       // Skip deletions where the property was an accessor, leaving holes
11731       // in the array of old values.
11732       if (old_values[i]->IsTheHole()) continue;
11733       JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
11734           .Assert();
11735     }
11736
11737     JSArray::SetLength(deleted, delete_count);
11738   }
11739
11740   RETURN_ON_EXCEPTION(
11741       isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
11742
11743   return array;
11744 }
11745
11746
11747 // static
11748 void Map::AddDependentCode(Handle<Map> map,
11749                            DependentCode::DependencyGroup group,
11750                            Handle<Code> code) {
11751   Handle<WeakCell> cell = Code::WeakCellFor(code);
11752   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
11753       Handle<DependentCode>(map->dependent_code()), group, cell);
11754   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11755 }
11756
11757
11758 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
11759   Recompute(entries);
11760 }
11761
11762
11763 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
11764   start_indexes_[0] = 0;
11765   for (int g = 1; g <= kGroupCount; g++) {
11766     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11767     start_indexes_[g] = start_indexes_[g - 1] + count;
11768   }
11769 }
11770
11771
11772 Handle<DependentCode> DependentCode::InsertCompilationDependencies(
11773     Handle<DependentCode> entries, DependencyGroup group,
11774     Handle<Foreign> info) {
11775   return Insert(entries, group, info);
11776 }
11777
11778
11779 Handle<DependentCode> DependentCode::InsertWeakCode(
11780     Handle<DependentCode> entries, DependencyGroup group,
11781     Handle<WeakCell> code_cell) {
11782   return Insert(entries, group, code_cell);
11783 }
11784
11785
11786 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
11787                                             DependencyGroup group,
11788                                             Handle<Object> object) {
11789   GroupStartIndexes starts(*entries);
11790   int start = starts.at(group);
11791   int end = starts.at(group + 1);
11792   int number_of_entries = starts.number_of_entries();
11793   // Check for existing entry to avoid duplicates.
11794   for (int i = start; i < end; i++) {
11795     if (entries->object_at(i) == *object) return entries;
11796   }
11797   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11798     entries = EnsureSpace(entries);
11799     // The number of codes can change after Compact and GC.
11800     starts.Recompute(*entries);
11801     start = starts.at(group);
11802     end = starts.at(group + 1);
11803   }
11804
11805   entries->ExtendGroup(group);
11806   entries->set_object_at(end, *object);
11807   entries->set_number_of_entries(group, end + 1 - start);
11808   return entries;
11809 }
11810
11811
11812 Handle<DependentCode> DependentCode::EnsureSpace(
11813     Handle<DependentCode> entries) {
11814   if (entries->length() == 0) {
11815     entries = Handle<DependentCode>::cast(
11816         FixedArray::CopySize(entries, kCodesStartIndex + 1, TENURED));
11817     for (int g = 0; g < kGroupCount; g++) {
11818       entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11819     }
11820     return entries;
11821   }
11822   if (entries->Compact()) return entries;
11823   GroupStartIndexes starts(*entries);
11824   int capacity =
11825       kCodesStartIndex + DependentCode::Grow(starts.number_of_entries());
11826   return Handle<DependentCode>::cast(
11827       FixedArray::CopySize(entries, capacity, TENURED));
11828 }
11829
11830
11831 bool DependentCode::Compact() {
11832   GroupStartIndexes starts(this);
11833   int n = 0;
11834   for (int g = 0; g < kGroupCount; g++) {
11835     int start = starts.at(g);
11836     int end = starts.at(g + 1);
11837     int count = 0;
11838     DCHECK(start >= n);
11839     for (int i = start; i < end; i++) {
11840       Object* obj = object_at(i);
11841       if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
11842         if (i != n + count) {
11843           copy(i, n + count);
11844         }
11845         count++;
11846       }
11847     }
11848     if (count != end - start) {
11849       set_number_of_entries(static_cast<DependencyGroup>(g), count);
11850     }
11851     n += count;
11852   }
11853   return n < starts.number_of_entries();
11854 }
11855
11856
11857 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
11858                                          WeakCell* code_cell) {
11859   DisallowHeapAllocation no_gc;
11860   GroupStartIndexes starts(this);
11861   int start = starts.at(group);
11862   int end = starts.at(group + 1);
11863   for (int i = start; i < end; i++) {
11864     if (object_at(i) == info) {
11865       set_object_at(i, code_cell);
11866       break;
11867     }
11868   }
11869
11870 #ifdef DEBUG
11871   for (int i = start; i < end; i++) {
11872     DCHECK(object_at(i) != info);
11873   }
11874 #endif
11875 }
11876
11877
11878 void DependentCode::RemoveCompilationDependencies(
11879     DependentCode::DependencyGroup group, Foreign* info) {
11880   DisallowHeapAllocation no_allocation;
11881   GroupStartIndexes starts(this);
11882   int start = starts.at(group);
11883   int end = starts.at(group + 1);
11884   // Find compilation info wrapper.
11885   int info_pos = -1;
11886   for (int i = start; i < end; i++) {
11887     if (object_at(i) == info) {
11888       info_pos = i;
11889       break;
11890     }
11891   }
11892   if (info_pos == -1) return;  // Not found.
11893   int gap = info_pos;
11894   // Use the last of each group to fill the gap in the previous group.
11895   for (int i = group; i < kGroupCount; i++) {
11896     int last_of_group = starts.at(i + 1) - 1;
11897     DCHECK(last_of_group >= gap);
11898     if (last_of_group == gap) continue;
11899     copy(last_of_group, gap);
11900     gap = last_of_group;
11901   }
11902   DCHECK(gap == starts.number_of_entries() - 1);
11903   clear_at(gap);  // Clear last gap.
11904   set_number_of_entries(group, end - start - 1);
11905
11906 #ifdef DEBUG
11907   for (int i = start; i < end - 1; i++) {
11908     DCHECK(object_at(i) != info);
11909   }
11910 #endif
11911 }
11912
11913
11914 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
11915   GroupStartIndexes starts(this);
11916   int start = starts.at(group);
11917   int end = starts.at(group + 1);
11918   for (int i = start; i < end; i++) {
11919     if (object_at(i) == code_cell) return true;
11920   }
11921   return false;
11922 }
11923
11924
11925 bool DependentCode::MarkCodeForDeoptimization(
11926     Isolate* isolate,
11927     DependentCode::DependencyGroup group) {
11928   DisallowHeapAllocation no_allocation_scope;
11929   DependentCode::GroupStartIndexes starts(this);
11930   int start = starts.at(group);
11931   int end = starts.at(group + 1);
11932   int code_entries = starts.number_of_entries();
11933   if (start == end) return false;
11934
11935   // Mark all the code that needs to be deoptimized.
11936   bool marked = false;
11937   bool invalidate_embedded_objects = group == kWeakCodeGroup;
11938   for (int i = start; i < end; i++) {
11939     Object* obj = object_at(i);
11940     if (obj->IsWeakCell()) {
11941       WeakCell* cell = WeakCell::cast(obj);
11942       if (cell->cleared()) continue;
11943       Code* code = Code::cast(cell->value());
11944       if (!code->marked_for_deoptimization()) {
11945         SetMarkedForDeoptimization(code, group);
11946         if (invalidate_embedded_objects) {
11947           code->InvalidateEmbeddedObjects();
11948         }
11949         marked = true;
11950       }
11951     } else {
11952       DCHECK(obj->IsForeign());
11953       CompilationDependencies* info =
11954           reinterpret_cast<CompilationDependencies*>(
11955               Foreign::cast(obj)->foreign_address());
11956       info->Abort();
11957     }
11958   }
11959   // Compact the array by moving all subsequent groups to fill in the new holes.
11960   for (int src = end, dst = start; src < code_entries; src++, dst++) {
11961     copy(src, dst);
11962   }
11963   // Now the holes are at the end of the array, zap them for heap-verifier.
11964   int removed = end - start;
11965   for (int i = code_entries - removed; i < code_entries; i++) {
11966     clear_at(i);
11967   }
11968   set_number_of_entries(group, 0);
11969   return marked;
11970 }
11971
11972
11973 void DependentCode::DeoptimizeDependentCodeGroup(
11974     Isolate* isolate,
11975     DependentCode::DependencyGroup group) {
11976   DCHECK(AllowCodeDependencyChange::IsAllowed());
11977   DisallowHeapAllocation no_allocation_scope;
11978   bool marked = MarkCodeForDeoptimization(isolate, group);
11979   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
11980 }
11981
11982
11983 void DependentCode::SetMarkedForDeoptimization(Code* code,
11984                                                DependencyGroup group) {
11985   code->set_marked_for_deoptimization(true);
11986   if (FLAG_trace_deopt &&
11987       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
11988     DeoptimizationInputData* deopt_data =
11989         DeoptimizationInputData::cast(code->deoptimization_data());
11990     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
11991     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
11992                          " (opt #%d) for deoptimization, reason: %s]\n",
11993            reinterpret_cast<intptr_t>(code),
11994            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
11995   }
11996 }
11997
11998
11999 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
12000   switch (group) {
12001     case kWeakCodeGroup:
12002       return "weak-code";
12003     case kTransitionGroup:
12004       return "transition";
12005     case kPrototypeCheckGroup:
12006       return "prototype-check";
12007     case kPropertyCellChangedGroup:
12008       return "property-cell-changed";
12009     case kFieldTypeGroup:
12010       return "field-type";
12011     case kInitialMapChangedGroup:
12012       return "initial-map-changed";
12013     case kAllocationSiteTenuringChangedGroup:
12014       return "allocation-site-tenuring-changed";
12015     case kAllocationSiteTransitionChangedGroup:
12016       return "allocation-site-transition-changed";
12017   }
12018   UNREACHABLE();
12019   return "?";
12020 }
12021
12022
12023 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12024                                        Handle<Object> prototype,
12025                                        PrototypeOptimizationMode mode) {
12026   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
12027   if (new_map.is_null()) {
12028     new_map = Copy(map, "TransitionToPrototype");
12029     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
12030     Map::SetPrototype(new_map, prototype, mode);
12031   }
12032   return new_map;
12033 }
12034
12035
12036 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12037                                            Handle<Object> value,
12038                                            bool from_javascript) {
12039 #ifdef DEBUG
12040   int size = object->Size();
12041 #endif
12042
12043   Isolate* isolate = object->GetIsolate();
12044   // Strong objects may not have their prototype set via __proto__ or
12045   // setPrototypeOf.
12046   if (from_javascript && object->map()->is_strong()) {
12047     THROW_NEW_ERROR(isolate,
12048                     NewTypeError(MessageTemplate::kStrongSetProto, object),
12049                     Object);
12050   }
12051   Heap* heap = isolate->heap();
12052   // Silently ignore the change if value is not a JSObject or null.
12053   // SpiderMonkey behaves this way.
12054   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12055
12056   // From 8.6.2 Object Internal Methods
12057   // ...
12058   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12059   // [[Prototype]] internal properties of the object may not be modified.
12060   // ...
12061   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12062   // or [[Extensible]] must not violate the invariants defined in the preceding
12063   // paragraph.
12064   if (!object->map()->is_extensible()) {
12065     THROW_NEW_ERROR(isolate,
12066                     NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12067                     Object);
12068   }
12069
12070   // Before we can set the prototype we need to be sure
12071   // prototype cycles are prevented.
12072   // It is sufficient to validate that the receiver is not in the new prototype
12073   // chain.
12074   for (PrototypeIterator iter(isolate, *value,
12075                               PrototypeIterator::START_AT_RECEIVER);
12076        !iter.IsAtEnd(); iter.Advance()) {
12077     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12078       // Cycle detected.
12079       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto),
12080                       Object);
12081     }
12082   }
12083
12084   bool dictionary_elements_in_chain =
12085       object->map()->DictionaryElementsInPrototypeChainOnly();
12086   Handle<JSObject> real_receiver = object;
12087
12088   if (from_javascript) {
12089     // Find the first object in the chain whose prototype object is not
12090     // hidden and set the new prototype on that object.
12091     PrototypeIterator iter(isolate, real_receiver);
12092     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12093       real_receiver =
12094           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12095       iter.Advance();
12096       if (!real_receiver->map()->is_extensible()) {
12097         THROW_NEW_ERROR(
12098             isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12099             Object);
12100       }
12101     }
12102   }
12103
12104   // Set the new prototype of the object.
12105   Handle<Map> map(real_receiver->map());
12106
12107   // Nothing to do if prototype is already set.
12108   if (map->prototype() == *value) return value;
12109
12110   isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
12111
12112   PrototypeOptimizationMode mode =
12113       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12114   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12115   DCHECK(new_map->prototype() == *value);
12116   JSObject::MigrateToMap(real_receiver, new_map);
12117
12118   if (from_javascript && !dictionary_elements_in_chain &&
12119       new_map->DictionaryElementsInPrototypeChainOnly()) {
12120     // If the prototype chain didn't previously have element callbacks, then
12121     // KeyedStoreICs need to be cleared to ensure any that involve this
12122     // map go generic.
12123     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12124   }
12125
12126   heap->ClearInstanceofCache();
12127   DCHECK(size == object->Size());
12128   return value;
12129 }
12130
12131
12132 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12133                                         Arguments* args,
12134                                         uint32_t first_arg,
12135                                         uint32_t arg_count,
12136                                         EnsureElementsMode mode) {
12137   // Elements in |Arguments| are ordered backwards (because they're on the
12138   // stack), but the method that's called here iterates over them in forward
12139   // direction.
12140   return EnsureCanContainElements(
12141       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12142 }
12143
12144
12145 ElementsAccessor* JSObject::GetElementsAccessor() {
12146   return ElementsAccessor::ForKind(GetElementsKind());
12147 }
12148
12149
12150 void JSObject::ValidateElements(Handle<JSObject> object) {
12151 #ifdef ENABLE_SLOW_DCHECKS
12152   if (FLAG_enable_slow_asserts) {
12153     ElementsAccessor* accessor = object->GetElementsAccessor();
12154     accessor->Validate(object);
12155   }
12156 #endif
12157 }
12158
12159
12160 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
12161                                         uint32_t index,
12162                                         uint32_t* new_capacity) {
12163   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
12164                 JSObject::kMaxUncheckedFastElementsLength);
12165   if (index < capacity) {
12166     *new_capacity = capacity;
12167     return false;
12168   }
12169   if (index - capacity >= JSObject::kMaxGap) return true;
12170   *new_capacity = JSObject::NewElementsCapacity(index + 1);
12171   DCHECK_LT(index, *new_capacity);
12172   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
12173       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
12174        object->GetHeap()->InNewSpace(object))) {
12175     return false;
12176   }
12177   // If the fast-case backing storage takes up roughly three times as
12178   // much space (in machine words) as a dictionary backing storage
12179   // would, the object should have slow elements.
12180   int used_elements = object->GetFastElementsUsage();
12181   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12182                         SeededNumberDictionary::kEntrySize;
12183   return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
12184 }
12185
12186
12187 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
12188   if (HasFastElements()) {
12189     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12190     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12191     uint32_t new_capacity;
12192     return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
12193   }
12194   return false;
12195 }
12196
12197
12198 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
12199   if (object->HasSloppyArgumentsElements()) {
12200     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
12201   }
12202   DCHECK(object->HasDictionaryElements());
12203   SeededNumberDictionary* dictionary = object->element_dictionary();
12204   ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
12205   for (int i = 0; i < dictionary->Capacity(); i++) {
12206     Object* key = dictionary->KeyAt(i);
12207     if (key->IsNumber()) {
12208       Object* value = dictionary->ValueAt(i);
12209       if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
12210       if (!value->IsSmi()) {
12211         if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
12212         kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12213       }
12214     }
12215   }
12216   return kind;
12217 }
12218
12219
12220 static bool ShouldConvertToFastElements(JSObject* object,
12221                                         SeededNumberDictionary* dictionary,
12222                                         uint32_t index,
12223                                         uint32_t* new_capacity) {
12224   // If properties with non-standard attributes or accessors were added, we
12225   // cannot go back to fast elements.
12226   if (dictionary->requires_slow_elements()) return false;
12227
12228   // Adding a property with this index will require slow elements.
12229   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
12230
12231   if (object->IsJSArray()) {
12232     Object* length = JSArray::cast(object)->length();
12233     if (!length->IsSmi()) return false;
12234     *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
12235   } else {
12236     *new_capacity = dictionary->max_number_key() + 1;
12237   }
12238   *new_capacity = Max(index + 1, *new_capacity);
12239
12240   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
12241                              SeededNumberDictionary::kEntrySize;
12242   return 2 * dictionary_size >= *new_capacity;
12243 }
12244
12245
12246 // static
12247 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
12248                                              uint32_t index,
12249                                              Handle<Object> value,
12250                                              PropertyAttributes attributes) {
12251   DCHECK(object->map()->is_extensible());
12252
12253   Isolate* isolate = object->GetIsolate();
12254
12255   uint32_t old_length = 0;
12256   uint32_t new_capacity = 0;
12257
12258   Handle<Object> old_length_handle;
12259   if (object->IsJSArray()) {
12260     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
12261     if (object->map()->is_observed()) {
12262       old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
12263     }
12264   }
12265
12266   ElementsKind kind = object->GetElementsKind();
12267   FixedArrayBase* elements = object->elements();
12268   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
12269   if (IsSloppyArgumentsElements(kind)) {
12270     elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
12271     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
12272   }
12273
12274   if (attributes != NONE) {
12275     kind = dictionary_kind;
12276   } else if (elements->IsSeededNumberDictionary()) {
12277     kind = ShouldConvertToFastElements(*object,
12278                                        SeededNumberDictionary::cast(elements),
12279                                        index, &new_capacity)
12280                ? BestFittingFastElementsKind(*object)
12281                : dictionary_kind;  // Overwrite in case of arguments.
12282   } else if (ShouldConvertToSlowElements(
12283                  *object, static_cast<uint32_t>(elements->length()), index,
12284                  &new_capacity)) {
12285     kind = dictionary_kind;
12286   }
12287
12288   ElementsKind to = value->OptimalElementsKind();
12289   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
12290     to = GetHoleyElementsKind(to);
12291     kind = GetHoleyElementsKind(kind);
12292   }
12293   to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
12294   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
12295   accessor->Add(object, index, value, attributes, new_capacity);
12296
12297   uint32_t new_length = old_length;
12298   Handle<Object> new_length_handle;
12299   if (object->IsJSArray() && index >= old_length) {
12300     new_length = index + 1;
12301     new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
12302     JSArray::cast(*object)->set_length(*new_length_handle);
12303   }
12304
12305   if (!old_length_handle.is_null() && new_length != old_length) {
12306     // |old_length_handle| is kept null above unless the object is observed.
12307     DCHECK(object->map()->is_observed());
12308     Handle<JSArray> array = Handle<JSArray>::cast(object);
12309     Handle<String> name = isolate->factory()->Uint32ToString(index);
12310
12311     RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12312     RETURN_ON_EXCEPTION(
12313         isolate, EnqueueChangeRecord(array, "add", name,
12314                                      isolate->factory()->the_hole_value()),
12315         Object);
12316     RETURN_ON_EXCEPTION(isolate,
12317                         EnqueueChangeRecord(array, "update",
12318                                             isolate->factory()->length_string(),
12319                                             old_length_handle),
12320                         Object);
12321     RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
12322     Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12323     RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
12324                                                      new_length - old_length),
12325                         Object);
12326   } else if (object->map()->is_observed()) {
12327     Handle<String> name = isolate->factory()->Uint32ToString(index);
12328     RETURN_ON_EXCEPTION(
12329         isolate, EnqueueChangeRecord(object, "add", name,
12330                                      isolate->factory()->the_hole_value()),
12331         Object);
12332   }
12333
12334   return value;
12335 }
12336
12337
12338 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
12339   if (!HasFastElements()) return false;
12340   uint32_t capacity = static_cast<uint32_t>(elements()->length());
12341   uint32_t new_capacity;
12342   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
12343          ShouldConvertToSlowElements(this, capacity, new_length - 1,
12344                                      &new_capacity);
12345 }
12346
12347
12348 const double AllocationSite::kPretenureRatio = 0.85;
12349
12350
12351 void AllocationSite::ResetPretenureDecision() {
12352   set_pretenure_decision(kUndecided);
12353   set_memento_found_count(0);
12354   set_memento_create_count(0);
12355 }
12356
12357
12358 PretenureFlag AllocationSite::GetPretenureMode() {
12359   PretenureDecision mode = pretenure_decision();
12360   // Zombie objects "decide" to be untenured.
12361   return mode == kTenure ? TENURED : NOT_TENURED;
12362 }
12363
12364
12365 bool AllocationSite::IsNestedSite() {
12366   DCHECK(FLAG_trace_track_allocation_sites);
12367   Object* current = GetHeap()->allocation_sites_list();
12368   while (current->IsAllocationSite()) {
12369     AllocationSite* current_site = AllocationSite::cast(current);
12370     if (current_site->nested_site() == this) {
12371       return true;
12372     }
12373     current = current_site->weak_next();
12374   }
12375   return false;
12376 }
12377
12378
12379 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
12380                                               ElementsKind to_kind) {
12381   Isolate* isolate = site->GetIsolate();
12382
12383   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12384     Handle<JSArray> transition_info =
12385         handle(JSArray::cast(site->transition_info()));
12386     ElementsKind kind = transition_info->GetElementsKind();
12387     // if kind is holey ensure that to_kind is as well.
12388     if (IsHoleyElementsKind(kind)) {
12389       to_kind = GetHoleyElementsKind(to_kind);
12390     }
12391     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12392       // If the array is huge, it's not likely to be defined in a local
12393       // function, so we shouldn't make new instances of it very often.
12394       uint32_t length = 0;
12395       CHECK(transition_info->length()->ToArrayLength(&length));
12396       if (length <= kMaximumArrayBytesToPretransition) {
12397         if (FLAG_trace_track_allocation_sites) {
12398           bool is_nested = site->IsNestedSite();
12399           PrintF(
12400               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12401               reinterpret_cast<void*>(*site),
12402               is_nested ? "(nested)" : "",
12403               ElementsKindToString(kind),
12404               ElementsKindToString(to_kind));
12405         }
12406         JSObject::TransitionElementsKind(transition_info, to_kind);
12407         site->dependent_code()->DeoptimizeDependentCodeGroup(
12408             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12409       }
12410     }
12411   } else {
12412     ElementsKind kind = site->GetElementsKind();
12413     // if kind is holey ensure that to_kind is as well.
12414     if (IsHoleyElementsKind(kind)) {
12415       to_kind = GetHoleyElementsKind(to_kind);
12416     }
12417     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12418       if (FLAG_trace_track_allocation_sites) {
12419         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12420                reinterpret_cast<void*>(*site),
12421                ElementsKindToString(kind),
12422                ElementsKindToString(to_kind));
12423       }
12424       site->SetElementsKind(to_kind);
12425       site->dependent_code()->DeoptimizeDependentCodeGroup(
12426           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12427     }
12428   }
12429 }
12430
12431
12432 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
12433   switch (decision) {
12434     case kUndecided: return "undecided";
12435     case kDontTenure: return "don't tenure";
12436     case kMaybeTenure: return "maybe tenure";
12437     case kTenure: return "tenure";
12438     case kZombie: return "zombie";
12439     default: UNREACHABLE();
12440   }
12441   return NULL;
12442 }
12443
12444
12445 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
12446                                     ElementsKind to_kind) {
12447   if (!object->IsJSArray()) return;
12448
12449   Heap* heap = object->GetHeap();
12450   if (!heap->InNewSpace(*object)) return;
12451
12452   Handle<AllocationSite> site;
12453   {
12454     DisallowHeapAllocation no_allocation;
12455
12456     AllocationMemento* memento = heap->FindAllocationMemento(*object);
12457     if (memento == NULL) return;
12458
12459     // Walk through to the Allocation Site
12460     site = handle(memento->GetAllocationSite());
12461   }
12462   AllocationSite::DigestTransitionFeedback(site, to_kind);
12463 }
12464
12465
12466 void JSObject::TransitionElementsKind(Handle<JSObject> object,
12467                                       ElementsKind to_kind) {
12468   ElementsKind from_kind = object->GetElementsKind();
12469
12470   if (IsFastHoleyElementsKind(from_kind)) {
12471     to_kind = GetHoleyElementsKind(to_kind);
12472   }
12473
12474   if (from_kind == to_kind) return;
12475
12476   // This method should never be called for any other case.
12477   DCHECK(IsFastElementsKind(from_kind));
12478   DCHECK(IsFastElementsKind(to_kind));
12479   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
12480
12481   UpdateAllocationSite(object, to_kind);
12482   if (object->elements() == object->GetHeap()->empty_fixed_array() ||
12483       IsFastDoubleElementsKind(from_kind) ==
12484           IsFastDoubleElementsKind(to_kind)) {
12485     // No change is needed to the elements() buffer, the transition
12486     // only requires a map change.
12487     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12488     MigrateToMap(object, new_map);
12489     if (FLAG_trace_elements_transitions) {
12490       Handle<FixedArrayBase> elms(object->elements());
12491       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12492     }
12493   } else {
12494     DCHECK((IsFastSmiElementsKind(from_kind) &&
12495             IsFastDoubleElementsKind(to_kind)) ||
12496            (IsFastDoubleElementsKind(from_kind) &&
12497             IsFastObjectElementsKind(to_kind)));
12498     uint32_t c = static_cast<uint32_t>(object->elements()->length());
12499     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
12500   }
12501 }
12502
12503
12504 // static
12505 bool Map::IsValidElementsTransition(ElementsKind from_kind,
12506                                     ElementsKind to_kind) {
12507   // Transitions can't go backwards.
12508   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12509     return false;
12510   }
12511
12512   // Transitions from HOLEY -> PACKED are not allowed.
12513   return !IsFastHoleyElementsKind(from_kind) ||
12514       IsFastHoleyElementsKind(to_kind);
12515 }
12516
12517
12518 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
12519   LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
12520                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12521   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
12522   CHECK(it.IsFound());
12523   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
12524   return it.IsReadOnly();
12525 }
12526
12527
12528 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
12529                                         uint32_t index) {
12530   uint32_t length = 0;
12531   CHECK(array->length()->ToArrayLength(&length));
12532   if (length <= index) return HasReadOnlyLength(array);
12533   return false;
12534 }
12535
12536
12537 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
12538   Isolate* isolate = array->GetIsolate();
12539   Handle<Name> length = isolate->factory()->length_string();
12540   THROW_NEW_ERROR(
12541       isolate,
12542       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array),
12543       Object);
12544 }
12545
12546
12547 template <typename BackingStore>
12548 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
12549   int limit = object->IsJSArray()
12550                   ? Smi::cast(JSArray::cast(object)->length())->value()
12551                   : store->length();
12552   int used = 0;
12553   for (int i = 0; i < limit; ++i) {
12554     if (!store->is_the_hole(i)) ++used;
12555   }
12556   return used;
12557 }
12558
12559
12560 int JSObject::GetFastElementsUsage() {
12561   FixedArrayBase* store = elements();
12562   switch (GetElementsKind()) {
12563     case FAST_SMI_ELEMENTS:
12564     case FAST_DOUBLE_ELEMENTS:
12565     case FAST_ELEMENTS:
12566       // Only JSArray have packed elements.
12567       return Smi::cast(JSArray::cast(this)->length())->value();
12568     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
12569       store = FixedArray::cast(FixedArray::cast(store)->get(1));
12570     // Fall through.
12571     case FAST_HOLEY_SMI_ELEMENTS:
12572     case FAST_HOLEY_ELEMENTS:
12573       return FastHoleyElementsUsage(this, FixedArray::cast(store));
12574     case FAST_HOLEY_DOUBLE_ELEMENTS:
12575       if (elements()->length() == 0) return 0;
12576       return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
12577
12578     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
12579     case DICTIONARY_ELEMENTS:
12580 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
12581     case TYPE##_ELEMENTS:                                                    \
12582
12583     TYPED_ARRAYS(TYPED_ARRAY_CASE)
12584 #undef TYPED_ARRAY_CASE
12585     UNREACHABLE();
12586   }
12587   return 0;
12588 }
12589
12590
12591 // Certain compilers request function template instantiation when they
12592 // see the definition of the other template functions in the
12593 // class. This requires us to have the template functions put
12594 // together, so even though this function belongs in objects-debug.cc,
12595 // we keep it here instead to satisfy certain compilers.
12596 #ifdef OBJECT_PRINT
12597 template <typename Derived, typename Shape, typename Key>
12598 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
12599   int capacity = this->Capacity();
12600   for (int i = 0; i < capacity; i++) {
12601     Object* k = this->KeyAt(i);
12602     if (this->IsKey(k)) {
12603       os << " ";
12604       if (k->IsString()) {
12605         String::cast(k)->StringPrint(os);
12606       } else {
12607         os << Brief(k);
12608       }
12609       os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i)
12610          << "\n";
12611     }
12612   }
12613 }
12614 #endif
12615
12616
12617 template<typename Derived, typename Shape, typename Key>
12618 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
12619   int pos = 0;
12620   int capacity = this->Capacity();
12621   DisallowHeapAllocation no_gc;
12622   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
12623   for (int i = 0; i < capacity; i++) {
12624     Object* k = this->KeyAt(i);
12625     if (this->IsKey(k)) {
12626       elements->set(pos++, this->ValueAt(i), mode);
12627     }
12628   }
12629   DCHECK(pos == elements->length());
12630 }
12631
12632
12633 InterceptorInfo* JSObject::GetNamedInterceptor() {
12634   DCHECK(map()->has_named_interceptor());
12635   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12636   DCHECK(constructor->shared()->IsApiFunction());
12637   Object* result =
12638       constructor->shared()->get_api_func_data()->named_property_handler();
12639   return InterceptorInfo::cast(result);
12640 }
12641
12642
12643 InterceptorInfo* JSObject::GetIndexedInterceptor() {
12644   DCHECK(map()->has_indexed_interceptor());
12645   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12646   DCHECK(constructor->shared()->IsApiFunction());
12647   Object* result =
12648       constructor->shared()->get_api_func_data()->indexed_property_handler();
12649   return InterceptorInfo::cast(result);
12650 }
12651
12652
12653 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
12654                                                          bool* done) {
12655   *done = false;
12656   Isolate* isolate = it->isolate();
12657   // Make sure that the top context does not change when doing callbacks or
12658   // interceptor calls.
12659   AssertNoContextChange ncc(isolate);
12660
12661   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
12662   Handle<InterceptorInfo> interceptor = it->GetInterceptor();
12663   if (interceptor->getter()->IsUndefined()) {
12664     return isolate->factory()->undefined_value();
12665   }
12666
12667   Handle<JSObject> holder = it->GetHolder<JSObject>();
12668   v8::Local<v8::Value> result;
12669   PropertyCallbackArguments args(isolate, interceptor->data(),
12670                                  *it->GetReceiver(), *holder);
12671
12672   if (it->IsElement()) {
12673     uint32_t index = it->index();
12674     v8::IndexedPropertyGetterCallback getter =
12675         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
12676     LOG(isolate,
12677         ApiIndexedPropertyAccess("interceptor-indexed-get", *holder, index));
12678     result = args.Call(getter, index);
12679   } else {
12680     Handle<Name> name = it->name();
12681
12682     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
12683       return isolate->factory()->undefined_value();
12684     }
12685
12686     v8::GenericNamedPropertyGetterCallback getter =
12687         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
12688             interceptor->getter());
12689     LOG(isolate,
12690         ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
12691     result = args.Call(getter, v8::Utils::ToLocal(name));
12692   }
12693
12694   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12695   if (result.IsEmpty()) return isolate->factory()->undefined_value();
12696   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12697   result_internal->VerifyApiCallResultType();
12698   *done = true;
12699   // Rebox handle before return
12700   return handle(*result_internal, isolate);
12701 }
12702
12703
12704 // Compute the property keys from the interceptor.
12705 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
12706     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12707   Isolate* isolate = receiver->GetIsolate();
12708   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
12709   PropertyCallbackArguments
12710       args(isolate, interceptor->data(), *receiver, *object);
12711   v8::Local<v8::Object> result;
12712   if (!interceptor->enumerator()->IsUndefined()) {
12713     v8::GenericNamedPropertyEnumeratorCallback enum_fun =
12714         v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>(
12715             interceptor->enumerator());
12716     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
12717     result = args.Call(enum_fun);
12718   }
12719   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12720   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12721          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12722   // Rebox before returning.
12723   return handle(*v8::Utils::OpenHandle(*result), isolate);
12724 }
12725
12726
12727 // Compute the element keys from the interceptor.
12728 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
12729     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12730   Isolate* isolate = receiver->GetIsolate();
12731   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12732   PropertyCallbackArguments
12733       args(isolate, interceptor->data(), *receiver, *object);
12734   v8::Local<v8::Object> result;
12735   if (!interceptor->enumerator()->IsUndefined()) {
12736     v8::IndexedPropertyEnumeratorCallback enum_fun =
12737         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
12738             interceptor->enumerator());
12739     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
12740     result = args.Call(enum_fun);
12741   }
12742   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12743   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12744          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12745   // Rebox before returning.
12746   return handle(*v8::Utils::OpenHandle(*result), isolate);
12747 }
12748
12749
12750 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
12751                                            Handle<Name> name) {
12752   LookupIterator it = LookupIterator::PropertyOrElement(
12753       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12754   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12755   if (!maybe_result.IsJust()) return Nothing<bool>();
12756   return Just(it.IsFound());
12757 }
12758
12759
12760 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
12761                                              uint32_t index) {
12762   Isolate* isolate = object->GetIsolate();
12763   LookupIterator it(isolate, object, index,
12764                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12765   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12766   if (!maybe_result.IsJust()) return Nothing<bool>();
12767   return Just(it.IsFound());
12768 }
12769
12770
12771 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
12772                                                    Handle<Name> name) {
12773   LookupIterator it = LookupIterator::PropertyOrElement(
12774       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12775   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12776   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
12777                                : Nothing<bool>();
12778 }
12779
12780
12781 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
12782   if (HasFastProperties()) {
12783     Map* map = this->map();
12784     if (filter == NONE) return map->NumberOfOwnDescriptors();
12785     if (filter & DONT_ENUM) {
12786       int result = map->EnumLength();
12787       if (result != kInvalidEnumCacheSentinel) return result;
12788     }
12789     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
12790   } else if (IsGlobalObject()) {
12791     return global_dictionary()->NumberOfElementsFilterAttributes(filter);
12792   } else {
12793     return property_dictionary()->NumberOfElementsFilterAttributes(filter);
12794   }
12795 }
12796
12797
12798 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
12799   Object* temp = get(i);
12800   set(i, get(j));
12801   set(j, temp);
12802   if (this != numbers) {
12803     temp = numbers->get(i);
12804     numbers->set(i, Smi::cast(numbers->get(j)));
12805     numbers->set(j, Smi::cast(temp));
12806   }
12807 }
12808
12809
12810 static void InsertionSortPairs(FixedArray* content,
12811                                FixedArray* numbers,
12812                                int len) {
12813   for (int i = 1; i < len; i++) {
12814     int j = i;
12815     while (j > 0 &&
12816            (NumberToUint32(numbers->get(j - 1)) >
12817             NumberToUint32(numbers->get(j)))) {
12818       content->SwapPairs(numbers, j - 1, j);
12819       j--;
12820     }
12821   }
12822 }
12823
12824
12825 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
12826   // In-place heap sort.
12827   DCHECK(content->length() == numbers->length());
12828
12829   // Bottom-up max-heap construction.
12830   for (int i = 1; i < len; ++i) {
12831     int child_index = i;
12832     while (child_index > 0) {
12833       int parent_index = ((child_index + 1) >> 1) - 1;
12834       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12835       uint32_t child_value = NumberToUint32(numbers->get(child_index));
12836       if (parent_value < child_value) {
12837         content->SwapPairs(numbers, parent_index, child_index);
12838       } else {
12839         break;
12840       }
12841       child_index = parent_index;
12842     }
12843   }
12844
12845   // Extract elements and create sorted array.
12846   for (int i = len - 1; i > 0; --i) {
12847     // Put max element at the back of the array.
12848     content->SwapPairs(numbers, 0, i);
12849     // Sift down the new top element.
12850     int parent_index = 0;
12851     while (true) {
12852       int child_index = ((parent_index + 1) << 1) - 1;
12853       if (child_index >= i) break;
12854       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
12855       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
12856       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12857       if (child_index + 1 >= i || child1_value > child2_value) {
12858         if (parent_value > child1_value) break;
12859         content->SwapPairs(numbers, parent_index, child_index);
12860         parent_index = child_index;
12861       } else {
12862         if (parent_value > child2_value) break;
12863         content->SwapPairs(numbers, parent_index, child_index + 1);
12864         parent_index = child_index + 1;
12865       }
12866     }
12867   }
12868 }
12869
12870
12871 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
12872 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
12873   DCHECK(this->length() == numbers->length());
12874   // For small arrays, simply use insertion sort.
12875   if (len <= 10) {
12876     InsertionSortPairs(this, numbers, len);
12877     return;
12878   }
12879   // Check the range of indices.
12880   uint32_t min_index = NumberToUint32(numbers->get(0));
12881   uint32_t max_index = min_index;
12882   uint32_t i;
12883   for (i = 1; i < len; i++) {
12884     if (NumberToUint32(numbers->get(i)) < min_index) {
12885       min_index = NumberToUint32(numbers->get(i));
12886     } else if (NumberToUint32(numbers->get(i)) > max_index) {
12887       max_index = NumberToUint32(numbers->get(i));
12888     }
12889   }
12890   if (max_index - min_index + 1 == len) {
12891     // Indices form a contiguous range, unless there are duplicates.
12892     // Do an in-place linear time sort assuming distinct numbers, but
12893     // avoid hanging in case they are not.
12894     for (i = 0; i < len; i++) {
12895       uint32_t p;
12896       uint32_t j = 0;
12897       // While the current element at i is not at its correct position p,
12898       // swap the elements at these two positions.
12899       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
12900              j++ < len) {
12901         SwapPairs(numbers, i, p);
12902       }
12903     }
12904   } else {
12905     HeapSortPairs(this, numbers, len);
12906     return;
12907   }
12908 }
12909
12910
12911 // Fill in the names of own properties into the supplied storage. The main
12912 // purpose of this function is to provide reflection information for the object
12913 // mirrors.
12914 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index,
12915                                   PropertyAttributes filter) {
12916   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
12917   if (HasFastProperties()) {
12918     int start_index = index;
12919     int real_size = map()->NumberOfOwnDescriptors();
12920     DescriptorArray* descs = map()->instance_descriptors();
12921     for (int i = 0; i < real_size; i++) {
12922       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
12923           !FilterKey(descs->GetKey(i), filter)) {
12924         storage->set(index++, descs->GetKey(i));
12925       }
12926     }
12927     return index - start_index;
12928   } else if (IsGlobalObject()) {
12929     return global_dictionary()->CopyKeysTo(storage, index, filter,
12930                                            GlobalDictionary::UNSORTED);
12931   } else {
12932     return property_dictionary()->CopyKeysTo(storage, index, filter,
12933                                              NameDictionary::UNSORTED);
12934   }
12935 }
12936
12937
12938 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
12939   return GetOwnElementKeys(NULL, filter);
12940 }
12941
12942
12943 int JSObject::NumberOfEnumElements() {
12944   // Fast case for objects with no elements.
12945   if (!IsJSValue() && HasFastObjectElements()) {
12946     uint32_t length = IsJSArray() ?
12947         static_cast<uint32_t>(
12948             Smi::cast(JSArray::cast(this)->length())->value()) :
12949         static_cast<uint32_t>(FixedArray::cast(elements())->length());
12950     if (length == 0) return 0;
12951   }
12952   // Compute the number of enumerable elements.
12953   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
12954 }
12955
12956
12957 int JSObject::GetOwnElementKeys(FixedArray* storage,
12958                                 PropertyAttributes filter) {
12959   int counter = 0;
12960
12961   // If this is a String wrapper, add the string indices first,
12962   // as they're guaranteed to preced the elements in numerical order
12963   // and ascending order is required by ECMA-262, 6th, 9.1.12.
12964   if (IsJSValue()) {
12965     Object* val = JSValue::cast(this)->value();
12966     if (val->IsString()) {
12967       String* str = String::cast(val);
12968       if (storage) {
12969         for (int i = 0; i < str->length(); i++) {
12970           storage->set(counter + i, Smi::FromInt(i));
12971         }
12972       }
12973       counter += str->length();
12974     }
12975   }
12976
12977   switch (GetElementsKind()) {
12978     case FAST_SMI_ELEMENTS:
12979     case FAST_ELEMENTS:
12980     case FAST_HOLEY_SMI_ELEMENTS:
12981     case FAST_HOLEY_ELEMENTS: {
12982       int length = IsJSArray() ?
12983           Smi::cast(JSArray::cast(this)->length())->value() :
12984           FixedArray::cast(elements())->length();
12985       for (int i = 0; i < length; i++) {
12986         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
12987           if (storage != NULL) {
12988             storage->set(counter, Smi::FromInt(i));
12989           }
12990           counter++;
12991         }
12992       }
12993       DCHECK(!storage || storage->length() >= counter);
12994       break;
12995     }
12996     case FAST_DOUBLE_ELEMENTS:
12997     case FAST_HOLEY_DOUBLE_ELEMENTS: {
12998       int length = IsJSArray() ?
12999           Smi::cast(JSArray::cast(this)->length())->value() :
13000           FixedArrayBase::cast(elements())->length();
13001       for (int i = 0; i < length; i++) {
13002         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
13003           if (storage != NULL) {
13004             storage->set(counter, Smi::FromInt(i));
13005           }
13006           counter++;
13007         }
13008       }
13009       DCHECK(!storage || storage->length() >= counter);
13010       break;
13011     }
13012
13013 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13014     case TYPE##_ELEMENTS:                                                    \
13015
13016     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13017 #undef TYPED_ARRAY_CASE
13018     {
13019       int length = FixedArrayBase::cast(elements())->length();
13020       while (counter < length) {
13021         if (storage != NULL) {
13022           storage->set(counter, Smi::FromInt(counter));
13023         }
13024         counter++;
13025       }
13026       DCHECK(!storage || storage->length() >= counter);
13027       break;
13028     }
13029
13030     case DICTIONARY_ELEMENTS: {
13031       if (storage != NULL) {
13032         element_dictionary()->CopyKeysTo(storage, counter, filter,
13033                                          SeededNumberDictionary::SORTED);
13034       }
13035       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13036       break;
13037     }
13038     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
13039     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
13040       FixedArray* parameter_map = FixedArray::cast(elements());
13041       int mapped_length = parameter_map->length() - 2;
13042       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13043       if (arguments->IsDictionary()) {
13044         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13045         // will insert in storage starting at index 0.
13046         SeededNumberDictionary* dictionary =
13047             SeededNumberDictionary::cast(arguments);
13048         if (storage != NULL) {
13049           dictionary->CopyKeysTo(storage, counter, filter,
13050                                  SeededNumberDictionary::UNSORTED);
13051         }
13052         counter += dictionary->NumberOfElementsFilterAttributes(filter);
13053         for (int i = 0; i < mapped_length; ++i) {
13054           if (!parameter_map->get(i + 2)->IsTheHole()) {
13055             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13056             ++counter;
13057           }
13058         }
13059         if (storage != NULL) storage->SortPairs(storage, counter);
13060
13061       } else {
13062         int backing_length = arguments->length();
13063         int i = 0;
13064         for (; i < mapped_length; ++i) {
13065           if (!parameter_map->get(i + 2)->IsTheHole()) {
13066             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13067             ++counter;
13068           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13069             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13070             ++counter;
13071           }
13072         }
13073         for (; i < backing_length; ++i) {
13074           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13075           ++counter;
13076         }
13077       }
13078       break;
13079     }
13080   }
13081
13082   DCHECK(!storage || storage->length() == counter);
13083   return counter;
13084 }
13085
13086
13087 int JSObject::GetEnumElementKeys(FixedArray* storage) {
13088   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
13089 }
13090
13091
13092 const char* Symbol::PrivateSymbolToName() const {
13093   Heap* heap = GetIsolate()->heap();
13094 #define SYMBOL_CHECK_AND_PRINT(name) \
13095   if (this == heap->name()) return #name;
13096   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
13097 #undef SYMBOL_CHECK_AND_PRINT
13098   return "UNKNOWN";
13099 }
13100
13101
13102 void Symbol::SymbolShortPrint(std::ostream& os) {
13103   os << "<Symbol: " << Hash();
13104   if (!name()->IsUndefined()) {
13105     os << " ";
13106     HeapStringAllocator allocator;
13107     StringStream accumulator(&allocator);
13108     String::cast(name())->StringShortPrint(&accumulator);
13109     os << accumulator.ToCString().get();
13110   } else {
13111     os << " (" << PrivateSymbolToName() << ")";
13112   }
13113   os << ">";
13114 }
13115
13116
13117 // StringSharedKeys are used as keys in the eval cache.
13118 class StringSharedKey : public HashTableKey {
13119  public:
13120   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
13121                   LanguageMode language_mode, int scope_position)
13122       : source_(source),
13123         shared_(shared),
13124         language_mode_(language_mode),
13125         scope_position_(scope_position) {}
13126
13127   bool IsMatch(Object* other) override {
13128     DisallowHeapAllocation no_allocation;
13129     if (!other->IsFixedArray()) {
13130       if (!other->IsNumber()) return false;
13131       uint32_t other_hash = static_cast<uint32_t>(other->Number());
13132       return Hash() == other_hash;
13133     }
13134     FixedArray* other_array = FixedArray::cast(other);
13135     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13136     if (shared != *shared_) return false;
13137     int language_unchecked = Smi::cast(other_array->get(2))->value();
13138     DCHECK(is_valid_language_mode(language_unchecked));
13139     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13140     if (language_mode != language_mode_) return false;
13141     int scope_position = Smi::cast(other_array->get(3))->value();
13142     if (scope_position != scope_position_) return false;
13143     String* source = String::cast(other_array->get(1));
13144     return source->Equals(*source_);
13145   }
13146
13147   static uint32_t StringSharedHashHelper(String* source,
13148                                          SharedFunctionInfo* shared,
13149                                          LanguageMode language_mode,
13150                                          int scope_position) {
13151     uint32_t hash = source->Hash();
13152     if (shared->HasSourceCode()) {
13153       // Instead of using the SharedFunctionInfo pointer in the hash
13154       // code computation, we use a combination of the hash of the
13155       // script source code and the start position of the calling scope.
13156       // We do this to ensure that the cache entries can survive garbage
13157       // collection.
13158       Script* script(Script::cast(shared->script()));
13159       hash ^= String::cast(script->source())->Hash();
13160       STATIC_ASSERT(LANGUAGE_END == 3);
13161       if (is_strict(language_mode)) hash ^= 0x8000;
13162       if (is_strong(language_mode)) hash ^= 0x10000;
13163       hash += scope_position;
13164     }
13165     return hash;
13166   }
13167
13168   uint32_t Hash() override {
13169     return StringSharedHashHelper(*source_, *shared_, language_mode_,
13170                                   scope_position_);
13171   }
13172
13173   uint32_t HashForObject(Object* obj) override {
13174     DisallowHeapAllocation no_allocation;
13175     if (obj->IsNumber()) {
13176       return static_cast<uint32_t>(obj->Number());
13177     }
13178     FixedArray* other_array = FixedArray::cast(obj);
13179     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13180     String* source = String::cast(other_array->get(1));
13181     int language_unchecked = Smi::cast(other_array->get(2))->value();
13182     DCHECK(is_valid_language_mode(language_unchecked));
13183     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13184     int scope_position = Smi::cast(other_array->get(3))->value();
13185     return StringSharedHashHelper(source, shared, language_mode,
13186                                   scope_position);
13187   }
13188
13189
13190   Handle<Object> AsHandle(Isolate* isolate) override {
13191     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
13192     array->set(0, *shared_);
13193     array->set(1, *source_);
13194     array->set(2, Smi::FromInt(language_mode_));
13195     array->set(3, Smi::FromInt(scope_position_));
13196     return array;
13197   }
13198
13199  private:
13200   Handle<String> source_;
13201   Handle<SharedFunctionInfo> shared_;
13202   LanguageMode language_mode_;
13203   int scope_position_;
13204 };
13205
13206
13207 // RegExpKey carries the source and flags of a regular expression as key.
13208 class RegExpKey : public HashTableKey {
13209  public:
13210   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
13211       : string_(string),
13212         flags_(Smi::FromInt(flags.value())) { }
13213
13214   // Rather than storing the key in the hash table, a pointer to the
13215   // stored value is stored where the key should be.  IsMatch then
13216   // compares the search key to the found object, rather than comparing
13217   // a key to a key.
13218   bool IsMatch(Object* obj) override {
13219     FixedArray* val = FixedArray::cast(obj);
13220     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13221         && (flags_ == val->get(JSRegExp::kFlagsIndex));
13222   }
13223
13224   uint32_t Hash() override { return RegExpHash(*string_, flags_); }
13225
13226   Handle<Object> AsHandle(Isolate* isolate) override {
13227     // Plain hash maps, which is where regexp keys are used, don't
13228     // use this function.
13229     UNREACHABLE();
13230     return MaybeHandle<Object>().ToHandleChecked();
13231   }
13232
13233   uint32_t HashForObject(Object* obj) override {
13234     FixedArray* val = FixedArray::cast(obj);
13235     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13236                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13237   }
13238
13239   static uint32_t RegExpHash(String* string, Smi* flags) {
13240     return string->Hash() + flags->value();
13241   }
13242
13243   Handle<String> string_;
13244   Smi* flags_;
13245 };
13246
13247
13248 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
13249   if (hash_field_ == 0) Hash();
13250   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
13251 }
13252
13253
13254 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
13255   if (hash_field_ == 0) Hash();
13256   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
13257 }
13258
13259
13260 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
13261   if (hash_field_ == 0) Hash();
13262   return isolate->factory()->NewOneByteInternalizedSubString(
13263       string_, from_, length_, hash_field_);
13264 }
13265
13266
13267 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
13268   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
13269   return String::cast(string)->IsOneByteEqualTo(chars);
13270 }
13271
13272
13273 // InternalizedStringKey carries a string/internalized-string object as key.
13274 class InternalizedStringKey : public HashTableKey {
13275  public:
13276   explicit InternalizedStringKey(Handle<String> string)
13277       : string_(string) { }
13278
13279   bool IsMatch(Object* string) override {
13280     return String::cast(string)->Equals(*string_);
13281   }
13282
13283   uint32_t Hash() override { return string_->Hash(); }
13284
13285   uint32_t HashForObject(Object* other) override {
13286     return String::cast(other)->Hash();
13287   }
13288
13289   Handle<Object> AsHandle(Isolate* isolate) override {
13290     // Internalize the string if possible.
13291     MaybeHandle<Map> maybe_map =
13292         isolate->factory()->InternalizedStringMapForString(string_);
13293     Handle<Map> map;
13294     if (maybe_map.ToHandle(&map)) {
13295       string_->set_map_no_write_barrier(*map);
13296       DCHECK(string_->IsInternalizedString());
13297       return string_;
13298     }
13299     // Otherwise allocate a new internalized string.
13300     return isolate->factory()->NewInternalizedStringImpl(
13301         string_, string_->length(), string_->hash_field());
13302   }
13303
13304   static uint32_t StringHash(Object* obj) {
13305     return String::cast(obj)->Hash();
13306   }
13307
13308   Handle<String> string_;
13309 };
13310
13311
13312 template<typename Derived, typename Shape, typename Key>
13313 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
13314   IteratePointers(v, 0, kElementsStartOffset);
13315 }
13316
13317
13318 template<typename Derived, typename Shape, typename Key>
13319 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
13320   IteratePointers(v,
13321                   kElementsStartOffset,
13322                   kHeaderSize + length() * kPointerSize);
13323 }
13324
13325
13326 template<typename Derived, typename Shape, typename Key>
13327 Handle<Derived> HashTable<Derived, Shape, Key>::New(
13328     Isolate* isolate,
13329     int at_least_space_for,
13330     MinimumCapacity capacity_option,
13331     PretenureFlag pretenure) {
13332   DCHECK(0 <= at_least_space_for);
13333   DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
13334
13335   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13336                      ? at_least_space_for
13337                      : isolate->creating_default_snapshot()
13338                            ? ComputeCapacityForSerialization(at_least_space_for)
13339                            : ComputeCapacity(at_least_space_for);
13340   if (capacity > HashTable::kMaxCapacity) {
13341     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13342   }
13343
13344   Factory* factory = isolate->factory();
13345   int length = EntryToIndex(capacity);
13346   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
13347   array->set_map_no_write_barrier(*factory->hash_table_map());
13348   Handle<Derived> table = Handle<Derived>::cast(array);
13349
13350   table->SetNumberOfElements(0);
13351   table->SetNumberOfDeletedElements(0);
13352   table->SetCapacity(capacity);
13353   return table;
13354 }
13355
13356
13357 // Find entry for key otherwise return kNotFound.
13358 template <typename Derived, typename Shape>
13359 int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
13360   if (!key->IsUniqueName()) {
13361     return DerivedDictionary::FindEntry(key);
13362   }
13363
13364   // Optimized for unique names. Knowledge of the key type allows:
13365   // 1. Move the check if the key is unique out of the loop.
13366   // 2. Avoid comparing hash codes in unique-to-unique comparison.
13367   // 3. Detect a case when a dictionary key is not unique but the key is.
13368   //    In case of positive result the dictionary key may be replaced by the
13369   //    internalized string with minimal performance penalty. It gives a chance
13370   //    to perform further lookups in code stubs (and significant performance
13371   //    boost a certain style of code).
13372
13373   // EnsureCapacity will guarantee the hash table is never full.
13374   uint32_t capacity = this->Capacity();
13375   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
13376   uint32_t count = 1;
13377
13378   while (true) {
13379     int index = Derived::EntryToIndex(entry);
13380     Object* element = this->get(index);
13381     if (element->IsUndefined()) break;  // Empty entry.
13382     if (*key == element) return entry;
13383     if (!element->IsUniqueName() &&
13384         !element->IsTheHole() &&
13385         Name::cast(element)->Equals(*key)) {
13386       // Replace a key that is a non-internalized string by the equivalent
13387       // internalized string for faster further lookups.
13388       this->set(index, *key);
13389       return entry;
13390     }
13391     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
13392     entry = Derived::NextProbe(entry, count++, capacity);
13393   }
13394   return Derived::kNotFound;
13395 }
13396
13397
13398 template<typename Derived, typename Shape, typename Key>
13399 void HashTable<Derived, Shape, Key>::Rehash(
13400     Handle<Derived> new_table,
13401     Key key) {
13402   DCHECK(NumberOfElements() < new_table->Capacity());
13403
13404   DisallowHeapAllocation no_gc;
13405   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
13406
13407   // Copy prefix to new array.
13408   for (int i = kPrefixStartIndex;
13409        i < kPrefixStartIndex + Shape::kPrefixSize;
13410        i++) {
13411     new_table->set(i, get(i), mode);
13412   }
13413
13414   // Rehash the elements.
13415   int capacity = this->Capacity();
13416   for (int i = 0; i < capacity; i++) {
13417     uint32_t from_index = EntryToIndex(i);
13418     Object* k = this->get(from_index);
13419     if (IsKey(k)) {
13420       uint32_t hash = this->HashForObject(key, k);
13421       uint32_t insertion_index =
13422           EntryToIndex(new_table->FindInsertionEntry(hash));
13423       for (int j = 0; j < Shape::kEntrySize; j++) {
13424         new_table->set(insertion_index + j, get(from_index + j), mode);
13425       }
13426     }
13427   }
13428   new_table->SetNumberOfElements(NumberOfElements());
13429   new_table->SetNumberOfDeletedElements(0);
13430 }
13431
13432
13433 template<typename Derived, typename Shape, typename Key>
13434 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
13435     Key key,
13436     Object* k,
13437     int probe,
13438     uint32_t expected) {
13439   uint32_t hash = this->HashForObject(key, k);
13440   uint32_t capacity = this->Capacity();
13441   uint32_t entry = FirstProbe(hash, capacity);
13442   for (int i = 1; i < probe; i++) {
13443     if (entry == expected) return expected;
13444     entry = NextProbe(entry, i, capacity);
13445   }
13446   return entry;
13447 }
13448
13449
13450 template<typename Derived, typename Shape, typename Key>
13451 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
13452                                           uint32_t entry2,
13453                                           WriteBarrierMode mode) {
13454   int index1 = EntryToIndex(entry1);
13455   int index2 = EntryToIndex(entry2);
13456   Object* temp[Shape::kEntrySize];
13457   for (int j = 0; j < Shape::kEntrySize; j++) {
13458     temp[j] = get(index1 + j);
13459   }
13460   for (int j = 0; j < Shape::kEntrySize; j++) {
13461     set(index1 + j, get(index2 + j), mode);
13462   }
13463   for (int j = 0; j < Shape::kEntrySize; j++) {
13464     set(index2 + j, temp[j], mode);
13465   }
13466 }
13467
13468
13469 template<typename Derived, typename Shape, typename Key>
13470 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
13471   DisallowHeapAllocation no_gc;
13472   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
13473   uint32_t capacity = Capacity();
13474   bool done = false;
13475   for (int probe = 1; !done; probe++) {
13476     // All elements at entries given by one of the first _probe_ probes
13477     // are placed correctly. Other elements might need to be moved.
13478     done = true;
13479     for (uint32_t current = 0; current < capacity; current++) {
13480       Object* current_key = get(EntryToIndex(current));
13481       if (IsKey(current_key)) {
13482         uint32_t target = EntryForProbe(key, current_key, probe, current);
13483         if (current == target) continue;
13484         Object* target_key = get(EntryToIndex(target));
13485         if (!IsKey(target_key) ||
13486             EntryForProbe(key, target_key, probe, target) != target) {
13487           // Put the current element into the correct position.
13488           Swap(current, target, mode);
13489           // The other element will be processed on the next iteration.
13490           current--;
13491         } else {
13492           // The place for the current element is occupied. Leave the element
13493           // for the next probe.
13494           done = false;
13495         }
13496       }
13497     }
13498   }
13499 }
13500
13501
13502 template<typename Derived, typename Shape, typename Key>
13503 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
13504     Handle<Derived> table,
13505     int n,
13506     Key key,
13507     PretenureFlag pretenure) {
13508   Isolate* isolate = table->GetIsolate();
13509   int capacity = table->Capacity();
13510   int nof = table->NumberOfElements() + n;
13511   int nod = table->NumberOfDeletedElements();
13512   // Return if:
13513   //   50% is still free after adding n elements and
13514   //   at most 50% of the free elements are deleted elements.
13515   if (nod <= (capacity - nof) >> 1) {
13516     int needed_free = nof >> 1;
13517     if (nof + needed_free <= capacity) return table;
13518   }
13519
13520   const int kMinCapacityForPretenure = 256;
13521   bool should_pretenure = pretenure == TENURED ||
13522       ((capacity > kMinCapacityForPretenure) &&
13523           !isolate->heap()->InNewSpace(*table));
13524   Handle<Derived> new_table = HashTable::New(
13525       isolate,
13526       nof * 2,
13527       USE_DEFAULT_MINIMUM_CAPACITY,
13528       should_pretenure ? TENURED : NOT_TENURED);
13529
13530   table->Rehash(new_table, key);
13531   return new_table;
13532 }
13533
13534
13535 template<typename Derived, typename Shape, typename Key>
13536 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
13537                                                        Key key) {
13538   int capacity = table->Capacity();
13539   int nof = table->NumberOfElements();
13540
13541   // Shrink to fit the number of elements if only a quarter of the
13542   // capacity is filled with elements.
13543   if (nof > (capacity >> 2)) return table;
13544   // Allocate a new dictionary with room for at least the current
13545   // number of elements. The allocation method will make sure that
13546   // there is extra room in the dictionary for additions. Don't go
13547   // lower than room for 16 elements.
13548   int at_least_room_for = nof;
13549   if (at_least_room_for < 16) return table;
13550
13551   Isolate* isolate = table->GetIsolate();
13552   const int kMinCapacityForPretenure = 256;
13553   bool pretenure =
13554       (at_least_room_for > kMinCapacityForPretenure) &&
13555       !isolate->heap()->InNewSpace(*table);
13556   Handle<Derived> new_table = HashTable::New(
13557       isolate,
13558       at_least_room_for,
13559       USE_DEFAULT_MINIMUM_CAPACITY,
13560       pretenure ? TENURED : NOT_TENURED);
13561
13562   table->Rehash(new_table, key);
13563   return new_table;
13564 }
13565
13566
13567 template<typename Derived, typename Shape, typename Key>
13568 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
13569   uint32_t capacity = Capacity();
13570   uint32_t entry = FirstProbe(hash, capacity);
13571   uint32_t count = 1;
13572   // EnsureCapacity will guarantee the hash table is never full.
13573   while (true) {
13574     Object* element = KeyAt(entry);
13575     if (element->IsUndefined() || element->IsTheHole()) break;
13576     entry = NextProbe(entry, count++, capacity);
13577   }
13578   return entry;
13579 }
13580
13581
13582 // Force instantiation of template instances class.
13583 // Please note this list is compiler dependent.
13584
13585 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
13586
13587 template class HashTable<CompilationCacheTable,
13588                          CompilationCacheShape,
13589                          HashTableKey*>;
13590
13591 template class HashTable<ObjectHashTable,
13592                          ObjectHashTableShape,
13593                          Handle<Object> >;
13594
13595 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
13596
13597 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
13598
13599 template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
13600                           Handle<Name> >;
13601
13602 template class Dictionary<SeededNumberDictionary,
13603                           SeededNumberDictionaryShape,
13604                           uint32_t>;
13605
13606 template class Dictionary<UnseededNumberDictionary,
13607                           UnseededNumberDictionaryShape,
13608                           uint32_t>;
13609
13610 template Handle<SeededNumberDictionary>
13611 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13612     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13613
13614 template Handle<UnseededNumberDictionary>
13615 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13616     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13617
13618 template Handle<NameDictionary>
13619 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13620     New(Isolate*, int n, PretenureFlag pretenure);
13621
13622 template Handle<GlobalDictionary>
13623 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::New(
13624     Isolate*, int n, PretenureFlag pretenure);
13625
13626 template Handle<SeededNumberDictionary>
13627 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13628     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
13629
13630 template Handle<UnseededNumberDictionary>
13631 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13632     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
13633
13634 template Object*
13635 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13636     SlowReverseLookup(Object* value);
13637
13638 template Object*
13639 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13640     SlowReverseLookup(Object* value);
13641
13642 template Handle<Object>
13643 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
13644     Handle<NameDictionary>, int);
13645
13646 template Handle<Object>
13647 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13648            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
13649
13650 template Handle<NameDictionary>
13651 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13652     New(Isolate*, int, MinimumCapacity, PretenureFlag);
13653
13654 template Handle<NameDictionary>
13655 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13656     Shrink(Handle<NameDictionary>, Handle<Name>);
13657
13658 template Handle<SeededNumberDictionary>
13659 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13660     Shrink(Handle<SeededNumberDictionary>, uint32_t);
13661
13662 template Handle<NameDictionary>
13663 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
13664     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
13665
13666 template Handle<GlobalDictionary>
13667     Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Add(
13668         Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
13669         PropertyDetails);
13670
13671 template Handle<FixedArray> Dictionary<
13672     NameDictionary, NameDictionaryShape,
13673     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
13674
13675 template Handle<FixedArray> Dictionary<
13676     NameDictionary, NameDictionaryShape,
13677     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
13678
13679 template Handle<SeededNumberDictionary>
13680 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13681     Add(Handle<SeededNumberDictionary>,
13682         uint32_t,
13683         Handle<Object>,
13684         PropertyDetails);
13685
13686 template Handle<UnseededNumberDictionary>
13687 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13688     Add(Handle<UnseededNumberDictionary>,
13689         uint32_t,
13690         Handle<Object>,
13691         PropertyDetails);
13692
13693 template Handle<SeededNumberDictionary>
13694 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13695     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
13696
13697 template Handle<UnseededNumberDictionary>
13698 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13699     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
13700
13701 template Handle<NameDictionary>
13702 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13703     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
13704
13705 template bool Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13706                          uint32_t>::HasComplexElements();
13707
13708 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
13709                        uint32_t>::FindEntry(uint32_t);
13710
13711 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
13712     Handle<Name>);
13713
13714
13715 Handle<Object> JSObject::PrepareSlowElementsForSort(
13716     Handle<JSObject> object, uint32_t limit) {
13717   DCHECK(object->HasDictionaryElements());
13718   Isolate* isolate = object->GetIsolate();
13719   // Must stay in dictionary mode, either because of requires_slow_elements,
13720   // or because we are not going to sort (and therefore compact) all of the
13721   // elements.
13722   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
13723   Handle<SeededNumberDictionary> new_dict =
13724       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
13725
13726   uint32_t pos = 0;
13727   uint32_t undefs = 0;
13728   int capacity = dict->Capacity();
13729   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
13730   // Entry to the new dictionary does not cause it to grow, as we have
13731   // allocated one that is large enough for all entries.
13732   DisallowHeapAllocation no_gc;
13733   for (int i = 0; i < capacity; i++) {
13734     Object* k = dict->KeyAt(i);
13735     if (!dict->IsKey(k)) continue;
13736
13737     DCHECK(k->IsNumber());
13738     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
13739     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
13740     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
13741
13742     HandleScope scope(isolate);
13743     Handle<Object> value(dict->ValueAt(i), isolate);
13744     PropertyDetails details = dict->DetailsAt(i);
13745     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
13746       // Bail out and do the sorting of undefineds and array holes in JS.
13747       // Also bail out if the element is not supposed to be moved.
13748       return bailout;
13749     }
13750
13751     uint32_t key = NumberToUint32(k);
13752     if (key < limit) {
13753       if (value->IsUndefined()) {
13754         undefs++;
13755       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13756         // Adding an entry with the key beyond smi-range requires
13757         // allocation. Bailout.
13758         return bailout;
13759       } else {
13760         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13761             new_dict, pos, value, details);
13762         DCHECK(result.is_identical_to(new_dict));
13763         USE(result);
13764         pos++;
13765       }
13766     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
13767       // Adding an entry with the key beyond smi-range requires
13768       // allocation. Bailout.
13769       return bailout;
13770     } else {
13771       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13772           new_dict, key, value, details);
13773       DCHECK(result.is_identical_to(new_dict));
13774       USE(result);
13775     }
13776   }
13777
13778   uint32_t result = pos;
13779   PropertyDetails no_details = PropertyDetails::Empty();
13780   while (undefs > 0) {
13781     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13782       // Adding an entry with the key beyond smi-range requires
13783       // allocation. Bailout.
13784       return bailout;
13785     }
13786     HandleScope scope(isolate);
13787     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13788         new_dict, pos, isolate->factory()->undefined_value(), no_details);
13789     DCHECK(result.is_identical_to(new_dict));
13790     USE(result);
13791     pos++;
13792     undefs--;
13793   }
13794
13795   object->set_elements(*new_dict);
13796
13797   AllowHeapAllocation allocate_return_value;
13798   return isolate->factory()->NewNumberFromUint(result);
13799 }
13800
13801
13802 // Collects all defined (non-hole) and non-undefined (array) elements at
13803 // the start of the elements array.
13804 // If the object is in dictionary mode, it is converted to fast elements
13805 // mode.
13806 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
13807                                                 uint32_t limit) {
13808   Isolate* isolate = object->GetIsolate();
13809   if (object->HasSloppyArgumentsElements() ||
13810       object->map()->is_observed()) {
13811     return handle(Smi::FromInt(-1), isolate);
13812   }
13813
13814   if (object->HasDictionaryElements()) {
13815     // Convert to fast elements containing only the existing properties.
13816     // Ordering is irrelevant, since we are going to sort anyway.
13817     Handle<SeededNumberDictionary> dict(object->element_dictionary());
13818     if (object->IsJSArray() || dict->requires_slow_elements() ||
13819         dict->max_number_key() >= limit) {
13820       return JSObject::PrepareSlowElementsForSort(object, limit);
13821     }
13822     // Convert to fast elements.
13823
13824     Handle<Map> new_map =
13825         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
13826
13827     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
13828         NOT_TENURED: TENURED;
13829     Handle<FixedArray> fast_elements =
13830         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
13831     dict->CopyValuesTo(*fast_elements);
13832     JSObject::ValidateElements(object);
13833
13834     JSObject::SetMapAndElements(object, new_map, fast_elements);
13835   } else if (object->HasFixedTypedArrayElements()) {
13836     // Typed arrays cannot have holes or undefined elements.
13837     return handle(Smi::FromInt(
13838         FixedArrayBase::cast(object->elements())->length()), isolate);
13839   } else if (!object->HasFastDoubleElements()) {
13840     EnsureWritableFastElements(object);
13841   }
13842   DCHECK(object->HasFastSmiOrObjectElements() ||
13843          object->HasFastDoubleElements());
13844
13845   // Collect holes at the end, undefined before that and the rest at the
13846   // start, and return the number of non-hole, non-undefined values.
13847
13848   Handle<FixedArrayBase> elements_base(object->elements());
13849   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
13850   if (limit > elements_length) {
13851     limit = elements_length ;
13852   }
13853   if (limit == 0) {
13854     return handle(Smi::FromInt(0), isolate);
13855   }
13856
13857   uint32_t result = 0;
13858   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
13859     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
13860     // Split elements into defined and the_hole, in that order.
13861     unsigned int holes = limit;
13862     // Assume most arrays contain no holes and undefined values, so minimize the
13863     // number of stores of non-undefined, non-the-hole values.
13864     for (unsigned int i = 0; i < holes; i++) {
13865       if (elements->is_the_hole(i)) {
13866         holes--;
13867       } else {
13868         continue;
13869       }
13870       // Position i needs to be filled.
13871       while (holes > i) {
13872         if (elements->is_the_hole(holes)) {
13873           holes--;
13874         } else {
13875           elements->set(i, elements->get_scalar(holes));
13876           break;
13877         }
13878       }
13879     }
13880     result = holes;
13881     while (holes < limit) {
13882       elements->set_the_hole(holes);
13883       holes++;
13884     }
13885   } else {
13886     FixedArray* elements = FixedArray::cast(*elements_base);
13887     DisallowHeapAllocation no_gc;
13888
13889     // Split elements into defined, undefined and the_hole, in that order.  Only
13890     // count locations for undefined and the hole, and fill them afterwards.
13891     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
13892     unsigned int undefs = limit;
13893     unsigned int holes = limit;
13894     // Assume most arrays contain no holes and undefined values, so minimize the
13895     // number of stores of non-undefined, non-the-hole values.
13896     for (unsigned int i = 0; i < undefs; i++) {
13897       Object* current = elements->get(i);
13898       if (current->IsTheHole()) {
13899         holes--;
13900         undefs--;
13901       } else if (current->IsUndefined()) {
13902         undefs--;
13903       } else {
13904         continue;
13905       }
13906       // Position i needs to be filled.
13907       while (undefs > i) {
13908         current = elements->get(undefs);
13909         if (current->IsTheHole()) {
13910           holes--;
13911           undefs--;
13912         } else if (current->IsUndefined()) {
13913           undefs--;
13914         } else {
13915           elements->set(i, current, write_barrier);
13916           break;
13917         }
13918       }
13919     }
13920     result = undefs;
13921     while (undefs < holes) {
13922       elements->set_undefined(undefs);
13923       undefs++;
13924     }
13925     while (holes < limit) {
13926       elements->set_the_hole(holes);
13927       holes++;
13928     }
13929   }
13930
13931   return isolate->factory()->NewNumberFromUint(result);
13932 }
13933
13934
13935 ExternalArrayType JSTypedArray::type() {
13936   switch (elements()->map()->instance_type()) {
13937 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
13938     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
13939       return kExternal##Type##Array;
13940
13941     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
13942 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
13943
13944     default:
13945       UNREACHABLE();
13946       return static_cast<ExternalArrayType>(-1);
13947   }
13948 }
13949
13950
13951 size_t JSTypedArray::element_size() {
13952   switch (elements()->map()->instance_type()) {
13953 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
13954   case FIXED_##TYPE##_ARRAY_TYPE:                                    \
13955     return size;
13956
13957     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
13958 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
13959
13960     default:
13961       UNREACHABLE();
13962       return 0;
13963   }
13964 }
13965
13966
13967 void FixedArray::SetValue(uint32_t index, Object* value) { set(index, value); }
13968
13969
13970 void FixedDoubleArray::SetValue(uint32_t index, Object* value) {
13971   set(index, value->Number());
13972 }
13973 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
13974                                           Handle<Name> name) {
13975   DCHECK(!global->HasFastProperties());
13976   auto dictionary = handle(global->global_dictionary());
13977   int entry = dictionary->FindEntry(name);
13978   if (entry == GlobalDictionary::kNotFound) return;
13979   PropertyCell::InvalidateEntry(dictionary, entry);
13980 }
13981
13982
13983 // TODO(ishell): rename to EnsureEmptyPropertyCell or something.
13984 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
13985     Handle<GlobalObject> global, Handle<Name> name) {
13986   DCHECK(!global->HasFastProperties());
13987   auto dictionary = handle(global->global_dictionary());
13988   int entry = dictionary->FindEntry(name);
13989   Handle<PropertyCell> cell;
13990   if (entry != GlobalDictionary::kNotFound) {
13991     // This call should be idempotent.
13992     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
13993     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
13994     DCHECK(cell->property_details().cell_type() ==
13995                PropertyCellType::kUninitialized ||
13996            cell->property_details().cell_type() ==
13997                PropertyCellType::kInvalidated);
13998     DCHECK(cell->value()->IsTheHole());
13999     return cell;
14000   }
14001   Isolate* isolate = global->GetIsolate();
14002   cell = isolate->factory()->NewPropertyCell();
14003   PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
14004   dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
14005   global->set_properties(*dictionary);
14006   return cell;
14007 }
14008
14009
14010 // This class is used for looking up two character strings in the string table.
14011 // If we don't have a hit we don't want to waste much time so we unroll the
14012 // string hash calculation loop here for speed.  Doesn't work if the two
14013 // characters form a decimal integer, since such strings have a different hash
14014 // algorithm.
14015 class TwoCharHashTableKey : public HashTableKey {
14016  public:
14017   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
14018     : c1_(c1), c2_(c2) {
14019     // Char 1.
14020     uint32_t hash = seed;
14021     hash += c1;
14022     hash += hash << 10;
14023     hash ^= hash >> 6;
14024     // Char 2.
14025     hash += c2;
14026     hash += hash << 10;
14027     hash ^= hash >> 6;
14028     // GetHash.
14029     hash += hash << 3;
14030     hash ^= hash >> 11;
14031     hash += hash << 15;
14032     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14033     hash_ = hash;
14034 #ifdef DEBUG
14035     // If this assert fails then we failed to reproduce the two-character
14036     // version of the string hashing algorithm above.  One reason could be
14037     // that we were passed two digits as characters, since the hash
14038     // algorithm is different in that case.
14039     uint16_t chars[2] = {c1, c2};
14040     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14041     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
14042     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14043 #endif
14044   }
14045
14046   bool IsMatch(Object* o) override {
14047     if (!o->IsString()) return false;
14048     String* other = String::cast(o);
14049     if (other->length() != 2) return false;
14050     if (other->Get(0) != c1_) return false;
14051     return other->Get(1) == c2_;
14052   }
14053
14054   uint32_t Hash() override { return hash_; }
14055   uint32_t HashForObject(Object* key) override {
14056     if (!key->IsString()) return 0;
14057     return String::cast(key)->Hash();
14058   }
14059
14060   Handle<Object> AsHandle(Isolate* isolate) override {
14061     // The TwoCharHashTableKey is only used for looking in the string
14062     // table, not for adding to it.
14063     UNREACHABLE();
14064     return MaybeHandle<Object>().ToHandleChecked();
14065   }
14066
14067  private:
14068   uint16_t c1_;
14069   uint16_t c2_;
14070   uint32_t hash_;
14071 };
14072
14073
14074 MaybeHandle<String> StringTable::InternalizeStringIfExists(
14075     Isolate* isolate,
14076     Handle<String> string) {
14077   if (string->IsInternalizedString()) {
14078     return string;
14079   }
14080   return LookupStringIfExists(isolate, string);
14081 }
14082
14083
14084 MaybeHandle<String> StringTable::LookupStringIfExists(
14085     Isolate* isolate,
14086     Handle<String> string) {
14087   Handle<StringTable> string_table = isolate->factory()->string_table();
14088   InternalizedStringKey key(string);
14089   int entry = string_table->FindEntry(&key);
14090   if (entry == kNotFound) {
14091     return MaybeHandle<String>();
14092   } else {
14093     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14094     DCHECK(StringShape(*result).IsInternalized());
14095     return result;
14096   }
14097 }
14098
14099
14100 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
14101     Isolate* isolate,
14102     uint16_t c1,
14103     uint16_t c2) {
14104   Handle<StringTable> string_table = isolate->factory()->string_table();
14105   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
14106   int entry = string_table->FindEntry(&key);
14107   if (entry == kNotFound) {
14108     return MaybeHandle<String>();
14109   } else {
14110     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14111     DCHECK(StringShape(*result).IsInternalized());
14112     return result;
14113   }
14114 }
14115
14116
14117 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
14118                                                    int expected) {
14119   Handle<StringTable> table = isolate->factory()->string_table();
14120   // We need a key instance for the virtual hash function.
14121   InternalizedStringKey dummy_key(Handle<String>::null());
14122   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
14123   isolate->factory()->set_string_table(table);
14124 }
14125
14126
14127 Handle<String> StringTable::LookupString(Isolate* isolate,
14128                                          Handle<String> string) {
14129   InternalizedStringKey key(string);
14130   return LookupKey(isolate, &key);
14131 }
14132
14133
14134 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
14135   Handle<StringTable> table = isolate->factory()->string_table();
14136   int entry = table->FindEntry(key);
14137
14138   // String already in table.
14139   if (entry != kNotFound) {
14140     return handle(String::cast(table->KeyAt(entry)), isolate);
14141   }
14142
14143   // Adding new string. Grow table if needed.
14144   table = StringTable::EnsureCapacity(table, 1, key);
14145
14146   // Create string object.
14147   Handle<Object> string = key->AsHandle(isolate);
14148   // There must be no attempts to internalize strings that could throw
14149   // InvalidStringLength error.
14150   CHECK(!string.is_null());
14151
14152   // Add the new string and return it along with the string table.
14153   entry = table->FindInsertionEntry(key->Hash());
14154   table->set(EntryToIndex(entry), *string);
14155   table->ElementAdded();
14156
14157   isolate->factory()->set_string_table(table);
14158   return Handle<String>::cast(string);
14159 }
14160
14161
14162 String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
14163   Handle<StringTable> table = isolate->factory()->string_table();
14164   int entry = table->FindEntry(key);
14165   if (entry != kNotFound) return String::cast(table->KeyAt(entry));
14166   return NULL;
14167 }
14168
14169
14170 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
14171                                              Handle<Context> context,
14172                                              LanguageMode language_mode) {
14173   Isolate* isolate = GetIsolate();
14174   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14175   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14176   int entry = FindEntry(&key);
14177   if (entry == kNotFound) return isolate->factory()->undefined_value();
14178   int index = EntryToIndex(entry);
14179   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14180   return Handle<Object>(get(index + 1), isolate);
14181 }
14182
14183
14184 Handle<Object> CompilationCacheTable::LookupEval(
14185     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
14186     LanguageMode language_mode, int scope_position) {
14187   Isolate* isolate = GetIsolate();
14188   // Cache key is the tuple (source, outer shared function info, scope position)
14189   // to unambiguously identify the context chain the cached eval code assumes.
14190   StringSharedKey key(src, outer_info, language_mode, scope_position);
14191   int entry = FindEntry(&key);
14192   if (entry == kNotFound) return isolate->factory()->undefined_value();
14193   int index = EntryToIndex(entry);
14194   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14195   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14196 }
14197
14198
14199 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
14200                                                    JSRegExp::Flags flags) {
14201   Isolate* isolate = GetIsolate();
14202   DisallowHeapAllocation no_allocation;
14203   RegExpKey key(src, flags);
14204   int entry = FindEntry(&key);
14205   if (entry == kNotFound) return isolate->factory()->undefined_value();
14206   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14207 }
14208
14209
14210 Handle<CompilationCacheTable> CompilationCacheTable::Put(
14211     Handle<CompilationCacheTable> cache, Handle<String> src,
14212     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
14213   Isolate* isolate = cache->GetIsolate();
14214   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14215   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14216   {
14217     Handle<Object> k = key.AsHandle(isolate);
14218     DisallowHeapAllocation no_allocation_scope;
14219     int entry = cache->FindEntry(&key);
14220     if (entry != kNotFound) {
14221       cache->set(EntryToIndex(entry), *k);
14222       cache->set(EntryToIndex(entry) + 1, *value);
14223       return cache;
14224     }
14225   }
14226
14227   cache = EnsureCapacity(cache, 1, &key);
14228   int entry = cache->FindInsertionEntry(key.Hash());
14229   Handle<Object> k =
14230       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14231   cache->set(EntryToIndex(entry), *k);
14232   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14233   cache->ElementAdded();
14234   return cache;
14235 }
14236
14237
14238 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
14239     Handle<CompilationCacheTable> cache, Handle<String> src,
14240     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
14241     int scope_position) {
14242   Isolate* isolate = cache->GetIsolate();
14243   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
14244   {
14245     Handle<Object> k = key.AsHandle(isolate);
14246     DisallowHeapAllocation no_allocation_scope;
14247     int entry = cache->FindEntry(&key);
14248     if (entry != kNotFound) {
14249       cache->set(EntryToIndex(entry), *k);
14250       cache->set(EntryToIndex(entry) + 1, *value);
14251       return cache;
14252     }
14253   }
14254
14255   cache = EnsureCapacity(cache, 1, &key);
14256   int entry = cache->FindInsertionEntry(key.Hash());
14257   Handle<Object> k =
14258       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14259   cache->set(EntryToIndex(entry), *k);
14260   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14261   cache->ElementAdded();
14262   return cache;
14263 }
14264
14265
14266 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
14267       Handle<CompilationCacheTable> cache, Handle<String> src,
14268       JSRegExp::Flags flags, Handle<FixedArray> value) {
14269   RegExpKey key(src, flags);
14270   cache = EnsureCapacity(cache, 1, &key);
14271   int entry = cache->FindInsertionEntry(key.Hash());
14272   // We store the value in the key slot, and compare the search key
14273   // to the stored value with a custon IsMatch function during lookups.
14274   cache->set(EntryToIndex(entry), *value);
14275   cache->set(EntryToIndex(entry) + 1, *value);
14276   cache->ElementAdded();
14277   return cache;
14278 }
14279
14280
14281 void CompilationCacheTable::Age() {
14282   DisallowHeapAllocation no_allocation;
14283   Object* the_hole_value = GetHeap()->the_hole_value();
14284   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14285     int entry_index = EntryToIndex(entry);
14286     int value_index = entry_index + 1;
14287
14288     if (get(entry_index)->IsNumber()) {
14289       Smi* count = Smi::cast(get(value_index));
14290       count = Smi::FromInt(count->value() - 1);
14291       if (count->value() == 0) {
14292         NoWriteBarrierSet(this, entry_index, the_hole_value);
14293         NoWriteBarrierSet(this, value_index, the_hole_value);
14294         ElementRemoved();
14295       } else {
14296         NoWriteBarrierSet(this, value_index, count);
14297       }
14298     } else if (get(entry_index)->IsFixedArray()) {
14299       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
14300       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
14301         NoWriteBarrierSet(this, entry_index, the_hole_value);
14302         NoWriteBarrierSet(this, value_index, the_hole_value);
14303         ElementRemoved();
14304       }
14305     }
14306   }
14307 }
14308
14309
14310 void CompilationCacheTable::Remove(Object* value) {
14311   DisallowHeapAllocation no_allocation;
14312   Object* the_hole_value = GetHeap()->the_hole_value();
14313   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14314     int entry_index = EntryToIndex(entry);
14315     int value_index = entry_index + 1;
14316     if (get(value_index) == value) {
14317       NoWriteBarrierSet(this, entry_index, the_hole_value);
14318       NoWriteBarrierSet(this, value_index, the_hole_value);
14319       ElementRemoved();
14320     }
14321   }
14322   return;
14323 }
14324
14325
14326 // StringsKey used for HashTable where key is array of internalized strings.
14327 class StringsKey : public HashTableKey {
14328  public:
14329   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
14330
14331   bool IsMatch(Object* strings) override {
14332     FixedArray* o = FixedArray::cast(strings);
14333     int len = strings_->length();
14334     if (o->length() != len) return false;
14335     for (int i = 0; i < len; i++) {
14336       if (o->get(i) != strings_->get(i)) return false;
14337     }
14338     return true;
14339   }
14340
14341   uint32_t Hash() override { return HashForObject(*strings_); }
14342
14343   uint32_t HashForObject(Object* obj) override {
14344     FixedArray* strings = FixedArray::cast(obj);
14345     int len = strings->length();
14346     uint32_t hash = 0;
14347     for (int i = 0; i < len; i++) {
14348       hash ^= String::cast(strings->get(i))->Hash();
14349     }
14350     return hash;
14351   }
14352
14353   Handle<Object> AsHandle(Isolate* isolate) override { return strings_; }
14354
14355  private:
14356   Handle<FixedArray> strings_;
14357 };
14358
14359
14360 template<typename Derived, typename Shape, typename Key>
14361 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
14362     Isolate* isolate,
14363     int at_least_space_for,
14364     PretenureFlag pretenure) {
14365   DCHECK(0 <= at_least_space_for);
14366   Handle<Derived> dict = DerivedHashTable::New(isolate,
14367                                                at_least_space_for,
14368                                                USE_DEFAULT_MINIMUM_CAPACITY,
14369                                                pretenure);
14370
14371   // Initialize the next enumeration index.
14372   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14373   return dict;
14374 }
14375
14376
14377 template <typename Derived, typename Shape, typename Key>
14378 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
14379     Handle<Derived> dictionary) {
14380   Factory* factory = dictionary->GetIsolate()->factory();
14381   int length = dictionary->NumberOfElements();
14382
14383   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
14384   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
14385
14386   // Fill both the iteration order array and the enumeration order array
14387   // with property details.
14388   int capacity = dictionary->Capacity();
14389   int pos = 0;
14390   for (int i = 0; i < capacity; i++) {
14391     if (dictionary->IsKey(dictionary->KeyAt(i))) {
14392       int index = dictionary->DetailsAt(i).dictionary_index();
14393       iteration_order->set(pos, Smi::FromInt(i));
14394       enumeration_order->set(pos, Smi::FromInt(index));
14395       pos++;
14396     }
14397   }
14398   DCHECK(pos == length);
14399
14400   // Sort the arrays wrt. enumeration order.
14401   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
14402   return iteration_order;
14403 }
14404
14405
14406 template <typename Derived, typename Shape, typename Key>
14407 Handle<FixedArray>
14408 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
14409     Handle<Derived> dictionary) {
14410   int length = dictionary->NumberOfElements();
14411
14412   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
14413   DCHECK(iteration_order->length() == length);
14414
14415   // Iterate over the dictionary using the enumeration order and update
14416   // the dictionary with new enumeration indices.
14417   for (int i = 0; i < length; i++) {
14418     int index = Smi::cast(iteration_order->get(i))->value();
14419     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
14420
14421     int enum_index = PropertyDetails::kInitialIndex + i;
14422
14423     PropertyDetails details = dictionary->DetailsAt(index);
14424     PropertyDetails new_details = details.set_index(enum_index);
14425     dictionary->DetailsAtPut(index, new_details);
14426   }
14427
14428   // Set the next enumeration index.
14429   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
14430   return iteration_order;
14431 }
14432
14433
14434 template<typename Derived, typename Shape, typename Key>
14435 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
14436     Handle<Derived> dictionary, int n, Key key) {
14437   // Check whether there are enough enumeration indices to add n elements.
14438   if (Shape::kIsEnumerable &&
14439       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
14440     // If not, we generate new indices for the properties.
14441     GenerateNewEnumerationIndices(dictionary);
14442   }
14443   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
14444 }
14445
14446
14447 template <typename Derived, typename Shape, typename Key>
14448 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
14449     Handle<Derived> dictionary, int entry) {
14450   Factory* factory = dictionary->GetIsolate()->factory();
14451   PropertyDetails details = dictionary->DetailsAt(entry);
14452   if (!details.IsConfigurable()) return factory->false_value();
14453
14454   dictionary->SetEntry(
14455       entry, factory->the_hole_value(), factory->the_hole_value());
14456   dictionary->ElementRemoved();
14457   return factory->true_value();
14458 }
14459
14460
14461 template<typename Derived, typename Shape, typename Key>
14462 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
14463     Handle<Derived> dictionary, Key key, Handle<Object> value) {
14464   int entry = dictionary->FindEntry(key);
14465
14466   // If the entry is present set the value;
14467   if (entry != Dictionary::kNotFound) {
14468     dictionary->ValueAtPut(entry, *value);
14469     return dictionary;
14470   }
14471
14472   // Check whether the dictionary should be extended.
14473   dictionary = EnsureCapacity(dictionary, 1, key);
14474 #ifdef DEBUG
14475   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
14476 #endif
14477   PropertyDetails details = PropertyDetails::Empty();
14478
14479   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14480   return dictionary;
14481 }
14482
14483
14484 template<typename Derived, typename Shape, typename Key>
14485 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
14486     Handle<Derived> dictionary,
14487     Key key,
14488     Handle<Object> value,
14489     PropertyDetails details) {
14490   // Valdate key is absent.
14491   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
14492   // Check whether the dictionary should be extended.
14493   dictionary = EnsureCapacity(dictionary, 1, key);
14494
14495   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14496   return dictionary;
14497 }
14498
14499
14500 // Add a key, value pair to the dictionary.
14501 template<typename Derived, typename Shape, typename Key>
14502 void Dictionary<Derived, Shape, Key>::AddEntry(
14503     Handle<Derived> dictionary,
14504     Key key,
14505     Handle<Object> value,
14506     PropertyDetails details,
14507     uint32_t hash) {
14508   // Compute the key object.
14509   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
14510
14511   uint32_t entry = dictionary->FindInsertionEntry(hash);
14512   // Insert element at empty or deleted entry
14513   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
14514     // Assign an enumeration index to the property and update
14515     // SetNextEnumerationIndex.
14516     int index = dictionary->NextEnumerationIndex();
14517     details = details.set_index(index);
14518     dictionary->SetNextEnumerationIndex(index + 1);
14519   }
14520   dictionary->SetEntry(entry, k, value, details);
14521   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
14522           dictionary->KeyAt(entry)->IsName()));
14523   dictionary->ElementAdded();
14524 }
14525
14526
14527 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
14528   DisallowHeapAllocation no_allocation;
14529   // If the dictionary requires slow elements an element has already
14530   // been added at a high index.
14531   if (requires_slow_elements()) return;
14532   // Check if this index is high enough that we should require slow
14533   // elements.
14534   if (key > kRequiresSlowElementsLimit) {
14535     // TODO(verwaest): Remove this hack.
14536     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
14537     set_requires_slow_elements();
14538     return;
14539   }
14540   // Update max key value.
14541   Object* max_index_object = get(kMaxNumberKeyIndex);
14542   if (!max_index_object->IsSmi() || max_number_key() < key) {
14543     FixedArray::set(kMaxNumberKeyIndex,
14544                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
14545   }
14546 }
14547
14548
14549 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
14550     Handle<SeededNumberDictionary> dictionary,
14551     uint32_t key,
14552     Handle<Object> value,
14553     PropertyDetails details) {
14554   dictionary->UpdateMaxNumberKey(key);
14555   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14556   return Add(dictionary, key, value, details);
14557 }
14558
14559
14560 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
14561     Handle<UnseededNumberDictionary> dictionary,
14562     uint32_t key,
14563     Handle<Object> value) {
14564   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14565   return Add(dictionary, key, value, PropertyDetails::Empty());
14566 }
14567
14568
14569 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
14570     Handle<SeededNumberDictionary> dictionary,
14571     uint32_t key,
14572     Handle<Object> value) {
14573   dictionary->UpdateMaxNumberKey(key);
14574   return AtPut(dictionary, key, value);
14575 }
14576
14577
14578 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
14579     Handle<UnseededNumberDictionary> dictionary,
14580     uint32_t key,
14581     Handle<Object> value) {
14582   return AtPut(dictionary, key, value);
14583 }
14584
14585
14586 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
14587     Handle<SeededNumberDictionary> dictionary,
14588     uint32_t key,
14589     Handle<Object> value,
14590     PropertyDetails details) {
14591   int entry = dictionary->FindEntry(key);
14592   if (entry == kNotFound) {
14593     return AddNumberEntry(dictionary, key, value, details);
14594   }
14595   // Preserve enumeration index.
14596   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
14597   Handle<Object> object_key =
14598       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14599   dictionary->SetEntry(entry, object_key, value, details);
14600   return dictionary;
14601 }
14602
14603
14604 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
14605     Handle<UnseededNumberDictionary> dictionary,
14606     uint32_t key,
14607     Handle<Object> value) {
14608   int entry = dictionary->FindEntry(key);
14609   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
14610   Handle<Object> object_key =
14611       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14612   dictionary->SetEntry(entry, object_key, value);
14613   return dictionary;
14614 }
14615
14616
14617 template <typename Derived, typename Shape, typename Key>
14618 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
14619     PropertyAttributes filter) {
14620   int capacity = this->Capacity();
14621   int result = 0;
14622   for (int i = 0; i < capacity; i++) {
14623     Object* k = this->KeyAt(i);
14624     if (this->IsKey(k) && !FilterKey(k, filter)) {
14625       if (this->IsDeleted(i)) continue;
14626       PropertyDetails details = this->DetailsAt(i);
14627       PropertyAttributes attr = details.attributes();
14628       if ((attr & filter) == 0) result++;
14629     }
14630   }
14631   return result;
14632 }
14633
14634
14635 template <typename Derived, typename Shape, typename Key>
14636 bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
14637   int capacity = this->Capacity();
14638   for (int i = 0; i < capacity; i++) {
14639     Object* k = this->KeyAt(i);
14640     if (this->IsKey(k) && !FilterKey(k, NONE)) {
14641       if (this->IsDeleted(i)) continue;
14642       PropertyDetails details = this->DetailsAt(i);
14643       if (details.type() == ACCESSOR_CONSTANT) return true;
14644       PropertyAttributes attr = details.attributes();
14645       if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true;
14646     }
14647   }
14648   return false;
14649 }
14650
14651
14652 template <typename Dictionary>
14653 struct EnumIndexComparator {
14654   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
14655   bool operator() (Smi* a, Smi* b) {
14656     PropertyDetails da(dict->DetailsAt(a->value()));
14657     PropertyDetails db(dict->DetailsAt(b->value()));
14658     return da.dictionary_index() < db.dictionary_index();
14659   }
14660   Dictionary* dict;
14661 };
14662
14663
14664 template <typename Derived, typename Shape, typename Key>
14665 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
14666   int length = storage->length();
14667   int capacity = this->Capacity();
14668   int properties = 0;
14669   for (int i = 0; i < capacity; i++) {
14670     Object* k = this->KeyAt(i);
14671     if (this->IsKey(k) && !k->IsSymbol()) {
14672       PropertyDetails details = this->DetailsAt(i);
14673       if (details.IsDontEnum() || this->IsDeleted(i)) continue;
14674       storage->set(properties, Smi::FromInt(i));
14675       properties++;
14676       if (properties == length) break;
14677     }
14678   }
14679   CHECK_EQ(length, properties);
14680   EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
14681   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
14682   std::sort(start, start + length, cmp);
14683   for (int i = 0; i < length; i++) {
14684     int index = Smi::cast(storage->get(i))->value();
14685     storage->set(i, this->KeyAt(index));
14686   }
14687 }
14688
14689
14690 template <typename Derived, typename Shape, typename Key>
14691 int Dictionary<Derived, Shape, Key>::CopyKeysTo(
14692     FixedArray* storage, int index, PropertyAttributes filter,
14693     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
14694   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
14695   int start_index = index;
14696   int capacity = this->Capacity();
14697   for (int i = 0; i < capacity; i++) {
14698     Object* k = this->KeyAt(i);
14699     if (this->IsKey(k) && !FilterKey(k, filter)) {
14700       if (this->IsDeleted(i)) continue;
14701       PropertyDetails details = this->DetailsAt(i);
14702       PropertyAttributes attr = details.attributes();
14703       if ((attr & filter) == 0) storage->set(index++, k);
14704     }
14705   }
14706   if (sort_mode == Dictionary::SORTED) {
14707     storage->SortPairs(storage, index);
14708   }
14709   DCHECK(storage->length() >= index);
14710   return index - start_index;
14711 }
14712
14713
14714 // Backwards lookup (slow).
14715 template<typename Derived, typename Shape, typename Key>
14716 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
14717   int capacity = this->Capacity();
14718   for (int i = 0; i < capacity; i++) {
14719     Object* k = this->KeyAt(i);
14720     if (this->IsKey(k)) {
14721       Object* e = this->ValueAt(i);
14722       // TODO(dcarney): this should be templatized.
14723       if (e->IsPropertyCell()) {
14724         e = PropertyCell::cast(e)->value();
14725       }
14726       if (e == value) return k;
14727     }
14728   }
14729   Heap* heap = Dictionary::GetHeap();
14730   return heap->undefined_value();
14731 }
14732
14733
14734 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
14735                                 int32_t hash) {
14736   DisallowHeapAllocation no_gc;
14737   DCHECK(IsKey(*key));
14738
14739   int entry = FindEntry(isolate, key, hash);
14740   if (entry == kNotFound) return isolate->heap()->the_hole_value();
14741   return get(EntryToIndex(entry) + 1);
14742 }
14743
14744
14745 Object* ObjectHashTable::Lookup(Handle<Object> key) {
14746   DisallowHeapAllocation no_gc;
14747   DCHECK(IsKey(*key));
14748
14749   Isolate* isolate = GetIsolate();
14750
14751   // If the object does not have an identity hash, it was never used as a key.
14752   Object* hash = key->GetHash();
14753   if (hash->IsUndefined()) {
14754     return isolate->heap()->the_hole_value();
14755   }
14756   return Lookup(isolate, key, Smi::cast(hash)->value());
14757 }
14758
14759
14760 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
14761   return Lookup(GetIsolate(), key, hash);
14762 }
14763
14764
14765 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14766                                              Handle<Object> key,
14767                                              Handle<Object> value) {
14768   DCHECK(table->IsKey(*key));
14769   DCHECK(!value->IsTheHole());
14770
14771   Isolate* isolate = table->GetIsolate();
14772   // Make sure the key object has an identity hash code.
14773   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
14774
14775   return Put(table, key, value, hash);
14776 }
14777
14778
14779 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14780                                              Handle<Object> key,
14781                                              Handle<Object> value,
14782                                              int32_t hash) {
14783   DCHECK(table->IsKey(*key));
14784   DCHECK(!value->IsTheHole());
14785
14786   Isolate* isolate = table->GetIsolate();
14787
14788   int entry = table->FindEntry(isolate, key, hash);
14789
14790   // Key is already in table, just overwrite value.
14791   if (entry != kNotFound) {
14792     table->set(EntryToIndex(entry) + 1, *value);
14793     return table;
14794   }
14795
14796   // Check whether the hash table should be extended.
14797   table = EnsureCapacity(table, 1, key);
14798   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
14799   return table;
14800 }
14801
14802
14803 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14804                                                 Handle<Object> key,
14805                                                 bool* was_present) {
14806   DCHECK(table->IsKey(*key));
14807
14808   Object* hash = key->GetHash();
14809   if (hash->IsUndefined()) {
14810     *was_present = false;
14811     return table;
14812   }
14813
14814   return Remove(table, key, was_present, Smi::cast(hash)->value());
14815 }
14816
14817
14818 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14819                                                 Handle<Object> key,
14820                                                 bool* was_present,
14821                                                 int32_t hash) {
14822   DCHECK(table->IsKey(*key));
14823
14824   int entry = table->FindEntry(table->GetIsolate(), key, hash);
14825   if (entry == kNotFound) {
14826     *was_present = false;
14827     return table;
14828   }
14829
14830   *was_present = true;
14831   table->RemoveEntry(entry);
14832   return Shrink(table, key);
14833 }
14834
14835
14836 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
14837   set(EntryToIndex(entry), key);
14838   set(EntryToIndex(entry) + 1, value);
14839   ElementAdded();
14840 }
14841
14842
14843 void ObjectHashTable::RemoveEntry(int entry) {
14844   set_the_hole(EntryToIndex(entry));
14845   set_the_hole(EntryToIndex(entry) + 1);
14846   ElementRemoved();
14847 }
14848
14849
14850 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
14851   DisallowHeapAllocation no_gc;
14852   DCHECK(IsKey(*key));
14853   int entry = FindEntry(key);
14854   if (entry == kNotFound) return GetHeap()->the_hole_value();
14855   return get(EntryToValueIndex(entry));
14856 }
14857
14858
14859 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
14860                                          Handle<HeapObject> key,
14861                                          Handle<HeapObject> value) {
14862   DCHECK(table->IsKey(*key));
14863   int entry = table->FindEntry(key);
14864   // Key is already in table, just overwrite value.
14865   if (entry != kNotFound) {
14866     table->set(EntryToValueIndex(entry), *value);
14867     return table;
14868   }
14869
14870   Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
14871
14872   // Check whether the hash table should be extended.
14873   table = EnsureCapacity(table, 1, key, TENURED);
14874
14875   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
14876   return table;
14877 }
14878
14879
14880 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
14881                              Handle<HeapObject> value) {
14882   DisallowHeapAllocation no_allocation;
14883   set(EntryToIndex(entry), *key_cell);
14884   set(EntryToValueIndex(entry), *value);
14885   ElementAdded();
14886 }
14887
14888
14889 #ifdef DEBUG
14890 Object* WeakValueHashTable::LookupWeak(Handle<Object> key) {
14891   Object* value = Lookup(key);
14892   if (value->IsWeakCell() && !WeakCell::cast(value)->cleared()) {
14893     value = WeakCell::cast(value)->value();
14894   }
14895   return value;
14896 }
14897 #endif  // DEBUG
14898
14899
14900 Handle<WeakValueHashTable> WeakValueHashTable::PutWeak(
14901     Handle<WeakValueHashTable> table, Handle<Object> key,
14902     Handle<HeapObject> value) {
14903   Handle<WeakCell> cell = value->GetIsolate()->factory()->NewWeakCell(value);
14904   return Handle<WeakValueHashTable>::cast(
14905       Put(Handle<ObjectHashTable>::cast(table), key, cell));
14906 }
14907
14908
14909 Handle<FixedArray> WeakValueHashTable::GetWeakValues(
14910     Handle<WeakValueHashTable> table) {
14911   Isolate* isolate = table->GetIsolate();
14912   uint32_t capacity = table->Capacity();
14913   Handle<FixedArray> results = isolate->factory()->NewFixedArray(capacity);
14914   int length = 0;
14915   for (uint32_t i = 0; i < capacity; i++) {
14916     uint32_t key_index = table->EntryToIndex(i);
14917     Object* key = table->get(key_index);
14918     if (!table->IsKey(key)) continue;
14919     uint32_t value_index = table->EntryToValueIndex(i);
14920     WeakCell* value_cell = WeakCell::cast(table->get(value_index));
14921     if (value_cell->cleared()) {
14922       table->RemoveEntry(i);
14923     } else {
14924       results->set(length++, value_cell->value());
14925     }
14926   }
14927   results->Shrink(length);
14928   return results;
14929 }
14930
14931
14932 template<class Derived, class Iterator, int entrysize>
14933 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
14934     Isolate* isolate, int capacity, PretenureFlag pretenure) {
14935   // Capacity must be a power of two, since we depend on being able
14936   // to divide and multiple by 2 (kLoadFactor) to derive capacity
14937   // from number of buckets. If we decide to change kLoadFactor
14938   // to something other than 2, capacity should be stored as another
14939   // field of this object.
14940   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
14941   if (capacity > kMaxCapacity) {
14942     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
14943   }
14944   int num_buckets = capacity / kLoadFactor;
14945   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
14946       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
14947   backing_store->set_map_no_write_barrier(
14948       isolate->heap()->ordered_hash_table_map());
14949   Handle<Derived> table = Handle<Derived>::cast(backing_store);
14950   for (int i = 0; i < num_buckets; ++i) {
14951     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
14952   }
14953   table->SetNumberOfBuckets(num_buckets);
14954   table->SetNumberOfElements(0);
14955   table->SetNumberOfDeletedElements(0);
14956   return table;
14957 }
14958
14959
14960 template<class Derived, class Iterator, int entrysize>
14961 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
14962     Handle<Derived> table) {
14963   DCHECK(!table->IsObsolete());
14964
14965   int nof = table->NumberOfElements();
14966   int nod = table->NumberOfDeletedElements();
14967   int capacity = table->Capacity();
14968   if ((nof + nod) < capacity) return table;
14969   // Don't need to grow if we can simply clear out deleted entries instead.
14970   // Note that we can't compact in place, though, so we always allocate
14971   // a new table.
14972   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
14973 }
14974
14975
14976 template<class Derived, class Iterator, int entrysize>
14977 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
14978     Handle<Derived> table) {
14979   DCHECK(!table->IsObsolete());
14980
14981   int nof = table->NumberOfElements();
14982   int capacity = table->Capacity();
14983   if (nof >= (capacity >> 2)) return table;
14984   return Rehash(table, capacity / 2);
14985 }
14986
14987
14988 template<class Derived, class Iterator, int entrysize>
14989 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
14990     Handle<Derived> table) {
14991   DCHECK(!table->IsObsolete());
14992
14993   Handle<Derived> new_table =
14994       Allocate(table->GetIsolate(),
14995                kMinCapacity,
14996                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
14997
14998   table->SetNextTable(*new_table);
14999   table->SetNumberOfDeletedElements(kClearedTableSentinel);
15000
15001   return new_table;
15002 }
15003
15004
15005 template<class Derived, class Iterator, int entrysize>
15006 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15007     Handle<Derived> table, int new_capacity) {
15008   DCHECK(!table->IsObsolete());
15009
15010   Handle<Derived> new_table =
15011       Allocate(table->GetIsolate(),
15012                new_capacity,
15013                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15014   int nof = table->NumberOfElements();
15015   int nod = table->NumberOfDeletedElements();
15016   int new_buckets = new_table->NumberOfBuckets();
15017   int new_entry = 0;
15018   int removed_holes_index = 0;
15019
15020   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
15021     Object* key = table->KeyAt(old_entry);
15022     if (key->IsTheHole()) {
15023       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
15024       continue;
15025     }
15026
15027     Object* hash = key->GetHash();
15028     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
15029     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
15030     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15031     int new_index = new_table->EntryToIndex(new_entry);
15032     int old_index = table->EntryToIndex(old_entry);
15033     for (int i = 0; i < entrysize; ++i) {
15034       Object* value = table->get(old_index + i);
15035       new_table->set(new_index + i, value);
15036     }
15037     new_table->set(new_index + kChainOffset, chain_entry);
15038     ++new_entry;
15039   }
15040
15041   DCHECK_EQ(nod, removed_holes_index);
15042
15043   new_table->SetNumberOfElements(nof);
15044   table->SetNextTable(*new_table);
15045
15046   return new_table;
15047 }
15048
15049
15050 template Handle<OrderedHashSet>
15051 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
15052     Isolate* isolate, int capacity, PretenureFlag pretenure);
15053
15054 template Handle<OrderedHashSet>
15055 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
15056     Handle<OrderedHashSet> table);
15057
15058 template Handle<OrderedHashSet>
15059 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15060     Handle<OrderedHashSet> table);
15061
15062 template Handle<OrderedHashSet>
15063 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15064     Handle<OrderedHashSet> table);
15065
15066
15067 template Handle<OrderedHashMap>
15068 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15069     Isolate* isolate, int capacity, PretenureFlag pretenure);
15070
15071 template Handle<OrderedHashMap>
15072 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15073     Handle<OrderedHashMap> table);
15074
15075 template Handle<OrderedHashMap>
15076 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15077     Handle<OrderedHashMap> table);
15078
15079 template Handle<OrderedHashMap>
15080 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15081     Handle<OrderedHashMap> table);
15082
15083
15084 template<class Derived, class TableType>
15085 void OrderedHashTableIterator<Derived, TableType>::Transition() {
15086   DisallowHeapAllocation no_allocation;
15087   TableType* table = TableType::cast(this->table());
15088   if (!table->IsObsolete()) return;
15089
15090   int index = Smi::cast(this->index())->value();
15091   while (table->IsObsolete()) {
15092     TableType* next_table = table->NextTable();
15093
15094     if (index > 0) {
15095       int nod = table->NumberOfDeletedElements();
15096
15097       if (nod == TableType::kClearedTableSentinel) {
15098         index = 0;
15099       } else {
15100         int old_index = index;
15101         for (int i = 0; i < nod; ++i) {
15102           int removed_index = table->RemovedIndexAt(i);
15103           if (removed_index >= old_index) break;
15104           --index;
15105         }
15106       }
15107     }
15108
15109     table = next_table;
15110   }
15111
15112   set_table(table);
15113   set_index(Smi::FromInt(index));
15114 }
15115
15116
15117 template<class Derived, class TableType>
15118 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
15119   DisallowHeapAllocation no_allocation;
15120   if (this->table()->IsUndefined()) return false;
15121
15122   Transition();
15123
15124   TableType* table = TableType::cast(this->table());
15125   int index = Smi::cast(this->index())->value();
15126   int used_capacity = table->UsedCapacity();
15127
15128   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
15129     index++;
15130   }
15131
15132   set_index(Smi::FromInt(index));
15133
15134   if (index < used_capacity) return true;
15135
15136   set_table(GetHeap()->undefined_value());
15137   return false;
15138 }
15139
15140
15141 template<class Derived, class TableType>
15142 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
15143   DisallowHeapAllocation no_allocation;
15144   if (HasMore()) {
15145     FixedArray* array = FixedArray::cast(value_array->elements());
15146     static_cast<Derived*>(this)->PopulateValueArray(array);
15147     MoveNext();
15148     return Smi::cast(kind());
15149   }
15150   return Smi::FromInt(0);
15151 }
15152
15153
15154 template Smi*
15155 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
15156     JSArray* value_array);
15157
15158 template bool
15159 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
15160
15161 template void
15162 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
15163
15164 template Object*
15165 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
15166
15167 template void
15168 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
15169
15170
15171 template Smi*
15172 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
15173     JSArray* value_array);
15174
15175 template bool
15176 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
15177
15178 template void
15179 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
15180
15181 template Object*
15182 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
15183
15184 template void
15185 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
15186
15187
15188 // Check if there is a break point at this code position.
15189 bool DebugInfo::HasBreakPoint(int code_position) {
15190   // Get the break point info object for this code position.
15191   Object* break_point_info = GetBreakPointInfo(code_position);
15192
15193   // If there is no break point info object or no break points in the break
15194   // point info object there is no break point at this code position.
15195   if (break_point_info->IsUndefined()) return false;
15196   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
15197 }
15198
15199
15200 // Get the break point info object for this code position.
15201 Object* DebugInfo::GetBreakPointInfo(int code_position) {
15202   // Find the index of the break point info object for this code position.
15203   int index = GetBreakPointInfoIndex(code_position);
15204
15205   // Return the break point info object if any.
15206   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
15207   return BreakPointInfo::cast(break_points()->get(index));
15208 }
15209
15210
15211 // Clear a break point at the specified code position.
15212 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
15213                                 int code_position,
15214                                 Handle<Object> break_point_object) {
15215   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15216                                   debug_info->GetIsolate());
15217   if (break_point_info->IsUndefined()) return;
15218   BreakPointInfo::ClearBreakPoint(
15219       Handle<BreakPointInfo>::cast(break_point_info),
15220       break_point_object);
15221 }
15222
15223
15224 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
15225                               int code_position,
15226                               int source_position,
15227                               int statement_position,
15228                               Handle<Object> break_point_object) {
15229   Isolate* isolate = debug_info->GetIsolate();
15230   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15231                                   isolate);
15232   if (!break_point_info->IsUndefined()) {
15233     BreakPointInfo::SetBreakPoint(
15234         Handle<BreakPointInfo>::cast(break_point_info),
15235         break_point_object);
15236     return;
15237   }
15238
15239   // Adding a new break point for a code position which did not have any
15240   // break points before. Try to find a free slot.
15241   int index = kNoBreakPointInfo;
15242   for (int i = 0; i < debug_info->break_points()->length(); i++) {
15243     if (debug_info->break_points()->get(i)->IsUndefined()) {
15244       index = i;
15245       break;
15246     }
15247   }
15248   if (index == kNoBreakPointInfo) {
15249     // No free slot - extend break point info array.
15250     Handle<FixedArray> old_break_points =
15251         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
15252     Handle<FixedArray> new_break_points =
15253         isolate->factory()->NewFixedArray(
15254             old_break_points->length() +
15255             DebugInfo::kEstimatedNofBreakPointsInFunction);
15256
15257     debug_info->set_break_points(*new_break_points);
15258     for (int i = 0; i < old_break_points->length(); i++) {
15259       new_break_points->set(i, old_break_points->get(i));
15260     }
15261     index = old_break_points->length();
15262   }
15263   DCHECK(index != kNoBreakPointInfo);
15264
15265   // Allocate new BreakPointInfo object and set the break point.
15266   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
15267       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
15268   new_break_point_info->set_code_position(Smi::FromInt(code_position));
15269   new_break_point_info->set_source_position(Smi::FromInt(source_position));
15270   new_break_point_info->
15271       set_statement_position(Smi::FromInt(statement_position));
15272   new_break_point_info->set_break_point_objects(
15273       isolate->heap()->undefined_value());
15274   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
15275   debug_info->break_points()->set(index, *new_break_point_info);
15276 }
15277
15278
15279 // Get the break point objects for a code position.
15280 Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
15281   Object* break_point_info = GetBreakPointInfo(code_position);
15282   if (break_point_info->IsUndefined()) {
15283     return GetIsolate()->factory()->undefined_value();
15284   }
15285   return Handle<Object>(
15286       BreakPointInfo::cast(break_point_info)->break_point_objects(),
15287       GetIsolate());
15288 }
15289
15290
15291 // Get the total number of break points.
15292 int DebugInfo::GetBreakPointCount() {
15293   if (break_points()->IsUndefined()) return 0;
15294   int count = 0;
15295   for (int i = 0; i < break_points()->length(); i++) {
15296     if (!break_points()->get(i)->IsUndefined()) {
15297       BreakPointInfo* break_point_info =
15298           BreakPointInfo::cast(break_points()->get(i));
15299       count += break_point_info->GetBreakPointCount();
15300     }
15301   }
15302   return count;
15303 }
15304
15305
15306 Handle<Object> DebugInfo::FindBreakPointInfo(
15307     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
15308   Isolate* isolate = debug_info->GetIsolate();
15309   if (!debug_info->break_points()->IsUndefined()) {
15310     for (int i = 0; i < debug_info->break_points()->length(); i++) {
15311       if (!debug_info->break_points()->get(i)->IsUndefined()) {
15312         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
15313             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
15314         if (BreakPointInfo::HasBreakPointObject(break_point_info,
15315                                                 break_point_object)) {
15316           return break_point_info;
15317         }
15318       }
15319     }
15320   }
15321   return isolate->factory()->undefined_value();
15322 }
15323
15324
15325 // Find the index of the break point info object for the specified code
15326 // position.
15327 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
15328   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
15329   for (int i = 0; i < break_points()->length(); i++) {
15330     if (!break_points()->get(i)->IsUndefined()) {
15331       BreakPointInfo* break_point_info =
15332           BreakPointInfo::cast(break_points()->get(i));
15333       if (break_point_info->code_position()->value() == code_position) {
15334         return i;
15335       }
15336     }
15337   }
15338   return kNoBreakPointInfo;
15339 }
15340
15341
15342 // Remove the specified break point object.
15343 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
15344                                      Handle<Object> break_point_object) {
15345   Isolate* isolate = break_point_info->GetIsolate();
15346   // If there are no break points just ignore.
15347   if (break_point_info->break_point_objects()->IsUndefined()) return;
15348   // If there is a single break point clear it if it is the same.
15349   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15350     if (break_point_info->break_point_objects() == *break_point_object) {
15351       break_point_info->set_break_point_objects(
15352           isolate->heap()->undefined_value());
15353     }
15354     return;
15355   }
15356   // If there are multiple break points shrink the array
15357   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
15358   Handle<FixedArray> old_array =
15359       Handle<FixedArray>(
15360           FixedArray::cast(break_point_info->break_point_objects()));
15361   Handle<FixedArray> new_array =
15362       isolate->factory()->NewFixedArray(old_array->length() - 1);
15363   int found_count = 0;
15364   for (int i = 0; i < old_array->length(); i++) {
15365     if (old_array->get(i) == *break_point_object) {
15366       DCHECK(found_count == 0);
15367       found_count++;
15368     } else {
15369       new_array->set(i - found_count, old_array->get(i));
15370     }
15371   }
15372   // If the break point was found in the list change it.
15373   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
15374 }
15375
15376
15377 // Add the specified break point object.
15378 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
15379                                    Handle<Object> break_point_object) {
15380   Isolate* isolate = break_point_info->GetIsolate();
15381
15382   // If there was no break point objects before just set it.
15383   if (break_point_info->break_point_objects()->IsUndefined()) {
15384     break_point_info->set_break_point_objects(*break_point_object);
15385     return;
15386   }
15387   // If the break point object is the same as before just ignore.
15388   if (break_point_info->break_point_objects() == *break_point_object) return;
15389   // If there was one break point object before replace with array.
15390   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15391     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
15392     array->set(0, break_point_info->break_point_objects());
15393     array->set(1, *break_point_object);
15394     break_point_info->set_break_point_objects(*array);
15395     return;
15396   }
15397   // If there was more than one break point before extend array.
15398   Handle<FixedArray> old_array =
15399       Handle<FixedArray>(
15400           FixedArray::cast(break_point_info->break_point_objects()));
15401   Handle<FixedArray> new_array =
15402       isolate->factory()->NewFixedArray(old_array->length() + 1);
15403   for (int i = 0; i < old_array->length(); i++) {
15404     // If the break point was there before just ignore.
15405     if (old_array->get(i) == *break_point_object) return;
15406     new_array->set(i, old_array->get(i));
15407   }
15408   // Add the new break point.
15409   new_array->set(old_array->length(), *break_point_object);
15410   break_point_info->set_break_point_objects(*new_array);
15411 }
15412
15413
15414 bool BreakPointInfo::HasBreakPointObject(
15415     Handle<BreakPointInfo> break_point_info,
15416     Handle<Object> break_point_object) {
15417   // No break point.
15418   if (break_point_info->break_point_objects()->IsUndefined()) return false;
15419   // Single break point.
15420   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15421     return break_point_info->break_point_objects() == *break_point_object;
15422   }
15423   // Multiple break points.
15424   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
15425   for (int i = 0; i < array->length(); i++) {
15426     if (array->get(i) == *break_point_object) {
15427       return true;
15428     }
15429   }
15430   return false;
15431 }
15432
15433
15434 // Get the number of break points.
15435 int BreakPointInfo::GetBreakPointCount() {
15436   // No break point.
15437   if (break_point_objects()->IsUndefined()) return 0;
15438   // Single break point.
15439   if (!break_point_objects()->IsFixedArray()) return 1;
15440   // Multiple break points.
15441   return FixedArray::cast(break_point_objects())->length();
15442 }
15443
15444
15445 Object* JSDate::GetField(Object* object, Smi* index) {
15446   return JSDate::cast(object)->DoGetField(
15447       static_cast<FieldIndex>(index->value()));
15448 }
15449
15450
15451 Object* JSDate::DoGetField(FieldIndex index) {
15452   DCHECK(index != kDateValue);
15453
15454   DateCache* date_cache = GetIsolate()->date_cache();
15455
15456   if (index < kFirstUncachedField) {
15457     Object* stamp = cache_stamp();
15458     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
15459       // Since the stamp is not NaN, the value is also not NaN.
15460       int64_t local_time_ms =
15461           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
15462       SetCachedFields(local_time_ms, date_cache);
15463     }
15464     switch (index) {
15465       case kYear: return year();
15466       case kMonth: return month();
15467       case kDay: return day();
15468       case kWeekday: return weekday();
15469       case kHour: return hour();
15470       case kMinute: return min();
15471       case kSecond: return sec();
15472       default: UNREACHABLE();
15473     }
15474   }
15475
15476   if (index >= kFirstUTCField) {
15477     return GetUTCField(index, value()->Number(), date_cache);
15478   }
15479
15480   double time = value()->Number();
15481   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
15482
15483   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
15484   int days = DateCache::DaysFromTime(local_time_ms);
15485
15486   if (index == kDays) return Smi::FromInt(days);
15487
15488   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15489   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
15490   DCHECK(index == kTimeInDay);
15491   return Smi::FromInt(time_in_day_ms);
15492 }
15493
15494
15495 Object* JSDate::GetUTCField(FieldIndex index,
15496                             double value,
15497                             DateCache* date_cache) {
15498   DCHECK(index >= kFirstUTCField);
15499
15500   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
15501
15502   int64_t time_ms = static_cast<int64_t>(value);
15503
15504   if (index == kTimezoneOffset) {
15505     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
15506   }
15507
15508   int days = DateCache::DaysFromTime(time_ms);
15509
15510   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
15511
15512   if (index <= kDayUTC) {
15513     int year, month, day;
15514     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15515     if (index == kYearUTC) return Smi::FromInt(year);
15516     if (index == kMonthUTC) return Smi::FromInt(month);
15517     DCHECK(index == kDayUTC);
15518     return Smi::FromInt(day);
15519   }
15520
15521   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
15522   switch (index) {
15523     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
15524     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
15525     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
15526     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
15527     case kDaysUTC: return Smi::FromInt(days);
15528     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
15529     default: UNREACHABLE();
15530   }
15531
15532   UNREACHABLE();
15533   return NULL;
15534 }
15535
15536
15537 void JSDate::SetValue(Object* value, bool is_value_nan) {
15538   set_value(value);
15539   if (is_value_nan) {
15540     HeapNumber* nan = GetIsolate()->heap()->nan_value();
15541     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
15542     set_year(nan, SKIP_WRITE_BARRIER);
15543     set_month(nan, SKIP_WRITE_BARRIER);
15544     set_day(nan, SKIP_WRITE_BARRIER);
15545     set_hour(nan, SKIP_WRITE_BARRIER);
15546     set_min(nan, SKIP_WRITE_BARRIER);
15547     set_sec(nan, SKIP_WRITE_BARRIER);
15548     set_weekday(nan, SKIP_WRITE_BARRIER);
15549   } else {
15550     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
15551   }
15552 }
15553
15554
15555 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
15556   int days = DateCache::DaysFromTime(local_time_ms);
15557   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15558   int year, month, day;
15559   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15560   int weekday = date_cache->Weekday(days);
15561   int hour = time_in_day_ms / (60 * 60 * 1000);
15562   int min = (time_in_day_ms / (60 * 1000)) % 60;
15563   int sec = (time_in_day_ms / 1000) % 60;
15564   set_cache_stamp(date_cache->stamp());
15565   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15566   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15567   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15568   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15569   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15570   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15571   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15572 }
15573
15574
15575 void JSArrayBuffer::Neuter() {
15576   CHECK(is_neuterable());
15577   CHECK(is_external());
15578   set_backing_store(NULL);
15579   set_byte_length(Smi::FromInt(0));
15580   set_was_neutered(true);
15581 }
15582
15583
15584 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
15585     Handle<JSTypedArray> typed_array) {
15586
15587   Handle<Map> map(typed_array->map());
15588   Isolate* isolate = typed_array->GetIsolate();
15589
15590   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
15591
15592   Handle<FixedTypedArrayBase> fixed_typed_array(
15593       FixedTypedArrayBase::cast(typed_array->elements()));
15594
15595   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
15596                                isolate);
15597   void* backing_store =
15598       isolate->array_buffer_allocator()->AllocateUninitialized(
15599           fixed_typed_array->DataSize());
15600   buffer->set_backing_store(backing_store);
15601   buffer->set_is_external(false);
15602   isolate->heap()->RegisterNewArrayBuffer(isolate->heap()->InNewSpace(*buffer),
15603                                           backing_store,
15604                                           fixed_typed_array->DataSize());
15605   memcpy(buffer->backing_store(),
15606          fixed_typed_array->DataPtr(),
15607          fixed_typed_array->DataSize());
15608   Handle<FixedTypedArrayBase> new_elements =
15609       isolate->factory()->NewFixedTypedArrayWithExternalPointer(
15610           fixed_typed_array->length(), typed_array->type(),
15611           static_cast<uint8_t*>(buffer->backing_store()));
15612
15613   typed_array->set_elements(*new_elements);
15614
15615   return buffer;
15616 }
15617
15618
15619 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
15620   Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
15621                                      GetIsolate());
15622   if (array_buffer->was_neutered() ||
15623       array_buffer->backing_store() != nullptr) {
15624     return array_buffer;
15625   }
15626   Handle<JSTypedArray> self(this);
15627   return MaterializeArrayBuffer(self);
15628 }
15629
15630
15631 Handle<PropertyCell> PropertyCell::InvalidateEntry(
15632     Handle<GlobalDictionary> dictionary, int entry) {
15633   Isolate* isolate = dictionary->GetIsolate();
15634   // Swap with a copy.
15635   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15636   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15637   auto new_cell = isolate->factory()->NewPropertyCell();
15638   new_cell->set_value(cell->value());
15639   dictionary->ValueAtPut(entry, *new_cell);
15640   bool is_the_hole = cell->value()->IsTheHole();
15641   // Cell is officially mutable henceforth.
15642   PropertyDetails details = cell->property_details();
15643   details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
15644                                               : PropertyCellType::kMutable);
15645   new_cell->set_property_details(details);
15646   // Old cell is ready for invalidation.
15647   if (is_the_hole) {
15648     cell->set_value(isolate->heap()->undefined_value());
15649   } else {
15650     cell->set_value(isolate->heap()->the_hole_value());
15651   }
15652   details = details.set_cell_type(PropertyCellType::kInvalidated);
15653   cell->set_property_details(details);
15654   cell->dependent_code()->DeoptimizeDependentCodeGroup(
15655       isolate, DependentCode::kPropertyCellChangedGroup);
15656   return new_cell;
15657 }
15658
15659
15660 PropertyCellConstantType PropertyCell::GetConstantType() {
15661   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
15662   return PropertyCellConstantType::kStableMap;
15663 }
15664
15665
15666 static bool RemainsConstantType(Handle<PropertyCell> cell,
15667                                 Handle<Object> value) {
15668   // TODO(dcarney): double->smi and smi->double transition from kConstant
15669   if (cell->value()->IsSmi() && value->IsSmi()) {
15670     return true;
15671   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
15672     return HeapObject::cast(cell->value())->map() ==
15673                HeapObject::cast(*value)->map() &&
15674            HeapObject::cast(*value)->map()->is_stable();
15675   }
15676   return false;
15677 }
15678
15679
15680 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
15681                                            Handle<Object> value,
15682                                            PropertyDetails details) {
15683   PropertyCellType type = details.cell_type();
15684   DCHECK(!value->IsTheHole());
15685   if (cell->value()->IsTheHole()) {
15686     switch (type) {
15687       // Only allow a cell to transition once into constant state.
15688       case PropertyCellType::kUninitialized:
15689         if (value->IsUndefined()) return PropertyCellType::kUndefined;
15690         return PropertyCellType::kConstant;
15691       case PropertyCellType::kInvalidated:
15692         return PropertyCellType::kMutable;
15693       default:
15694         UNREACHABLE();
15695         return PropertyCellType::kMutable;
15696     }
15697   }
15698   switch (type) {
15699     case PropertyCellType::kUndefined:
15700       return PropertyCellType::kConstant;
15701     case PropertyCellType::kConstant:
15702       if (*value == cell->value()) return PropertyCellType::kConstant;
15703     // Fall through.
15704     case PropertyCellType::kConstantType:
15705       if (RemainsConstantType(cell, value)) {
15706         return PropertyCellType::kConstantType;
15707       }
15708     // Fall through.
15709     case PropertyCellType::kMutable:
15710       return PropertyCellType::kMutable;
15711   }
15712   UNREACHABLE();
15713   return PropertyCellType::kMutable;
15714 }
15715
15716
15717 void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
15718                               Handle<Object> value, PropertyDetails details) {
15719   DCHECK(!value->IsTheHole());
15720   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15721   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15722   const PropertyDetails original_details = cell->property_details();
15723   // Data accesses could be cached in ics or optimized code.
15724   bool invalidate =
15725       original_details.kind() == kData && details.kind() == kAccessor;
15726   int index = original_details.dictionary_index();
15727   PropertyCellType old_type = original_details.cell_type();
15728   // Preserve the enumeration index unless the property was deleted or never
15729   // initialized.
15730   if (cell->value()->IsTheHole()) {
15731     index = dictionary->NextEnumerationIndex();
15732     dictionary->SetNextEnumerationIndex(index + 1);
15733     // Negative lookup cells must be invalidated.
15734     invalidate = true;
15735   }
15736   DCHECK(index > 0);
15737   details = details.set_index(index);
15738
15739   PropertyCellType new_type = UpdatedType(cell, value, original_details);
15740   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
15741
15742   // Install new property details and cell value.
15743   details = details.set_cell_type(new_type);
15744   cell->set_property_details(details);
15745   cell->set_value(*value);
15746
15747   // Deopt when transitioning from a constant type.
15748   if (!invalidate && (old_type != new_type ||
15749                       original_details.IsReadOnly() != details.IsReadOnly())) {
15750     Isolate* isolate = dictionary->GetIsolate();
15751     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15752         isolate, DependentCode::kPropertyCellChangedGroup);
15753   }
15754 }
15755
15756
15757 // static
15758 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
15759                                             Handle<Object> new_value) {
15760   if (cell->value() != *new_value) {
15761     cell->set_value(*new_value);
15762     Isolate* isolate = cell->GetIsolate();
15763     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15764         isolate, DependentCode::kPropertyCellChangedGroup);
15765   }
15766 }
15767
15768 }  // namespace internal
15769 }  // namespace v8