2e1443ab47ed246fd65e657905f35b21568169ba
[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 EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1285     os << "<External" #Type "Array["                                          \
1286        << External##Type##Array::cast(this)->length() << "]>";                \
1287     break;                                                                    \
1288   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1289     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1290        << "]>";                                                               \
1291     break;
1292
1293     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1294 #undef TYPED_ARRAY_SHORT_PRINT
1295
1296     case SHARED_FUNCTION_INFO_TYPE: {
1297       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1298       base::SmartArrayPointer<char> debug_name =
1299           shared->DebugName()->ToCString();
1300       if (debug_name[0] != 0) {
1301         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1302       } else {
1303         os << "<SharedFunctionInfo>";
1304       }
1305       break;
1306     }
1307     case JS_MESSAGE_OBJECT_TYPE:
1308       os << "<JSMessageObject>";
1309       break;
1310 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1311   case NAME##_TYPE:                        \
1312     os << "<" #Name ">";                   \
1313     break;
1314   STRUCT_LIST(MAKE_STRUCT_CASE)
1315 #undef MAKE_STRUCT_CASE
1316     case CODE_TYPE: {
1317       Code* code = Code::cast(this);
1318       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1319       break;
1320     }
1321     case ODDBALL_TYPE: {
1322       if (IsUndefined()) {
1323         os << "<undefined>";
1324       } else if (IsTheHole()) {
1325         os << "<the hole>";
1326       } else if (IsNull()) {
1327         os << "<null>";
1328       } else if (IsTrue()) {
1329         os << "<true>";
1330       } else if (IsFalse()) {
1331         os << "<false>";
1332       } else {
1333         os << "<Odd Oddball>";
1334       }
1335       break;
1336     }
1337     case SYMBOL_TYPE: {
1338       Symbol* symbol = Symbol::cast(this);
1339       symbol->SymbolShortPrint(os);
1340       break;
1341     }
1342     case HEAP_NUMBER_TYPE: {
1343       os << "<Number: ";
1344       HeapNumber::cast(this)->HeapNumberPrint(os);
1345       os << ">";
1346       break;
1347     }
1348     case MUTABLE_HEAP_NUMBER_TYPE: {
1349       os << "<MutableNumber: ";
1350       HeapNumber::cast(this)->HeapNumberPrint(os);
1351       os << '>';
1352       break;
1353     }
1354     case FLOAT32X4_TYPE: {
1355       os << "<Float32x4: ";
1356       Float32x4::cast(this)->Float32x4Print(os);
1357       os << ">";
1358       break;
1359     }
1360     case JS_PROXY_TYPE:
1361       os << "<JSProxy>";
1362       break;
1363     case JS_FUNCTION_PROXY_TYPE:
1364       os << "<JSFunctionProxy>";
1365       break;
1366     case FOREIGN_TYPE:
1367       os << "<Foreign>";
1368       break;
1369     case CELL_TYPE: {
1370       os << "Cell for ";
1371       HeapStringAllocator allocator;
1372       StringStream accumulator(&allocator);
1373       Cell::cast(this)->value()->ShortPrint(&accumulator);
1374       os << accumulator.ToCString().get();
1375       break;
1376     }
1377     case PROPERTY_CELL_TYPE: {
1378       os << "PropertyCell for ";
1379       HeapStringAllocator allocator;
1380       StringStream accumulator(&allocator);
1381       PropertyCell* cell = PropertyCell::cast(this);
1382       cell->value()->ShortPrint(&accumulator);
1383       os << accumulator.ToCString().get() << " " << cell->property_details();
1384       break;
1385     }
1386     case WEAK_CELL_TYPE: {
1387       os << "WeakCell for ";
1388       HeapStringAllocator allocator;
1389       StringStream accumulator(&allocator);
1390       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
1391       os << accumulator.ToCString().get();
1392       break;
1393     }
1394     default:
1395       os << "<Other heap object (" << map()->instance_type() << ")>";
1396       break;
1397   }
1398 }
1399
1400
1401 void HeapObject::Iterate(ObjectVisitor* v) {
1402   // Handle header
1403   IteratePointer(v, kMapOffset);
1404   // Handle object body
1405   Map* m = map();
1406   IterateBody(m->instance_type(), SizeFromMap(m), v);
1407 }
1408
1409
1410 void HeapObject::IterateBody(InstanceType type, int object_size,
1411                              ObjectVisitor* v) {
1412   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1413   // During GC, the map pointer field is encoded.
1414   if (type < FIRST_NONSTRING_TYPE) {
1415     switch (type & kStringRepresentationMask) {
1416       case kSeqStringTag:
1417         break;
1418       case kConsStringTag:
1419         ConsString::BodyDescriptor::IterateBody(this, v);
1420         break;
1421       case kSlicedStringTag:
1422         SlicedString::BodyDescriptor::IterateBody(this, v);
1423         break;
1424       case kExternalStringTag:
1425         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1426           reinterpret_cast<ExternalOneByteString*>(this)
1427               ->ExternalOneByteStringIterateBody(v);
1428         } else {
1429           reinterpret_cast<ExternalTwoByteString*>(this)->
1430               ExternalTwoByteStringIterateBody(v);
1431         }
1432         break;
1433     }
1434     return;
1435   }
1436
1437   switch (type) {
1438     case FIXED_ARRAY_TYPE:
1439       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1440       break;
1441     case FIXED_DOUBLE_ARRAY_TYPE:
1442       break;
1443     case JS_OBJECT_TYPE:
1444     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1445     case JS_GENERATOR_OBJECT_TYPE:
1446     case JS_MODULE_TYPE:
1447     case JS_VALUE_TYPE:
1448     case JS_DATE_TYPE:
1449     case JS_ARRAY_TYPE:
1450     case JS_ARRAY_BUFFER_TYPE:
1451     case JS_TYPED_ARRAY_TYPE:
1452     case JS_DATA_VIEW_TYPE:
1453     case JS_SET_TYPE:
1454     case JS_MAP_TYPE:
1455     case JS_SET_ITERATOR_TYPE:
1456     case JS_MAP_ITERATOR_TYPE:
1457     case JS_WEAK_MAP_TYPE:
1458     case JS_WEAK_SET_TYPE:
1459     case JS_REGEXP_TYPE:
1460     case JS_GLOBAL_PROXY_TYPE:
1461     case JS_GLOBAL_OBJECT_TYPE:
1462     case JS_BUILTINS_OBJECT_TYPE:
1463     case JS_MESSAGE_OBJECT_TYPE:
1464       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1465       break;
1466     case JS_FUNCTION_TYPE:
1467       reinterpret_cast<JSFunction*>(this)
1468           ->JSFunctionIterateBody(object_size, v);
1469       break;
1470     case ODDBALL_TYPE:
1471       Oddball::BodyDescriptor::IterateBody(this, v);
1472       break;
1473     case JS_PROXY_TYPE:
1474       JSProxy::BodyDescriptor::IterateBody(this, v);
1475       break;
1476     case JS_FUNCTION_PROXY_TYPE:
1477       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1478       break;
1479     case FOREIGN_TYPE:
1480       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1481       break;
1482     case MAP_TYPE:
1483       Map::BodyDescriptor::IterateBody(this, v);
1484       break;
1485     case CODE_TYPE:
1486       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1487       break;
1488     case CELL_TYPE:
1489       Cell::BodyDescriptor::IterateBody(this, v);
1490       break;
1491     case PROPERTY_CELL_TYPE:
1492       PropertyCell::BodyDescriptor::IterateBody(this, v);
1493       break;
1494     case WEAK_CELL_TYPE:
1495       WeakCell::BodyDescriptor::IterateBody(this, v);
1496       break;
1497     case SYMBOL_TYPE:
1498       Symbol::BodyDescriptor::IterateBody(this, v);
1499       break;
1500
1501     case HEAP_NUMBER_TYPE:
1502     case MUTABLE_HEAP_NUMBER_TYPE:
1503     case FLOAT32X4_TYPE:
1504     case FILLER_TYPE:
1505     case BYTE_ARRAY_TYPE:
1506     case BYTECODE_ARRAY_TYPE:
1507     case FREE_SPACE_TYPE:
1508       break;
1509
1510 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1511   case EXTERNAL_##TYPE##_ARRAY_TYPE:                    \
1512     break;                                              \
1513                                                         \
1514   case FIXED_##TYPE##_ARRAY_TYPE:                       \
1515     reinterpret_cast<FixedTypedArrayBase*>(this)        \
1516         ->FixedTypedArrayBaseIterateBody(v);            \
1517     break;
1518
1519
1520     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1521 #undef TYPED_ARRAY_CASE
1522
1523     case SHARED_FUNCTION_INFO_TYPE: {
1524       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1525       break;
1526     }
1527
1528 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1529         case NAME##_TYPE:
1530       STRUCT_LIST(MAKE_STRUCT_CASE)
1531 #undef MAKE_STRUCT_CASE
1532       if (type == ALLOCATION_SITE_TYPE) {
1533         AllocationSite::BodyDescriptor::IterateBody(this, v);
1534       } else {
1535         StructBodyDescriptor::IterateBody(this, object_size, v);
1536       }
1537       break;
1538     default:
1539       PrintF("Unknown type: %d\n", type);
1540       UNREACHABLE();
1541   }
1542 }
1543
1544
1545 bool HeapNumber::HeapNumberBooleanValue() {
1546   return DoubleToBoolean(value());
1547 }
1548
1549
1550 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
1551   os << value();
1552 }
1553
1554
1555 void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
1556   char arr[100];
1557   Vector<char> buffer(arr, arraysize(arr));
1558   os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
1559      << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
1560      << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
1561      << std::string(DoubleToCString(get_lane(3), buffer));
1562 }
1563
1564
1565 String* JSReceiver::class_name() {
1566   if (IsJSFunction() || IsJSFunctionProxy()) {
1567     return GetHeap()->Function_string();
1568   }
1569   Object* maybe_constructor = map()->GetConstructor();
1570   if (maybe_constructor->IsJSFunction()) {
1571     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1572     return String::cast(constructor->shared()->instance_class_name());
1573   }
1574   // If the constructor is not present, return "Object".
1575   return GetHeap()->Object_string();
1576 }
1577
1578
1579 String* Map::constructor_name() {
1580   if (is_prototype_map() && prototype_info()->IsPrototypeInfo()) {
1581     PrototypeInfo* proto_info = PrototypeInfo::cast(prototype_info());
1582     if (proto_info->constructor_name()->IsString()) {
1583       return String::cast(proto_info->constructor_name());
1584     }
1585   }
1586   Object* maybe_constructor = GetConstructor();
1587   if (maybe_constructor->IsJSFunction()) {
1588     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1589     String* name = String::cast(constructor->shared()->name());
1590     if (name->length() > 0) return name;
1591     String* inferred_name = constructor->shared()->inferred_name();
1592     if (inferred_name->length() > 0) return inferred_name;
1593     Object* proto = prototype();
1594     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1595   }
1596   // TODO(rossberg): what about proxies?
1597   // If the constructor is not present, return "Object".
1598   return GetHeap()->Object_string();
1599 }
1600
1601
1602 String* JSReceiver::constructor_name() {
1603   return map()->constructor_name();
1604 }
1605
1606
1607 static Handle<Object> WrapType(Handle<HeapType> type) {
1608   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
1609   return type;
1610 }
1611
1612
1613 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1614                                     Handle<Name> name,
1615                                     Handle<HeapType> type,
1616                                     PropertyAttributes attributes,
1617                                     Representation representation,
1618                                     TransitionFlag flag) {
1619   DCHECK(DescriptorArray::kNotFound ==
1620          map->instance_descriptors()->Search(
1621              *name, map->NumberOfOwnDescriptors()));
1622
1623   // Ensure the descriptor array does not get too big.
1624   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1625     return MaybeHandle<Map>();
1626   }
1627
1628   Isolate* isolate = map->GetIsolate();
1629
1630   // Compute the new index for new field.
1631   int index = map->NextFreePropertyIndex();
1632
1633   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1634     representation = Representation::Tagged();
1635     type = HeapType::Any(isolate);
1636   }
1637
1638   Handle<Object> wrapped_type(WrapType(type));
1639
1640   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
1641                                 representation);
1642   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1643   int unused_property_fields = new_map->unused_property_fields() - 1;
1644   if (unused_property_fields < 0) {
1645     unused_property_fields += JSObject::kFieldsAdded;
1646   }
1647   new_map->set_unused_property_fields(unused_property_fields);
1648   return new_map;
1649 }
1650
1651
1652 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1653                                        Handle<Name> name,
1654                                        Handle<Object> constant,
1655                                        PropertyAttributes attributes,
1656                                        TransitionFlag flag) {
1657   // Ensure the descriptor array does not get too big.
1658   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1659     return MaybeHandle<Map>();
1660   }
1661
1662   // Allocate new instance descriptors with (name, constant) added.
1663   DataConstantDescriptor new_constant_desc(name, constant, attributes);
1664   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1665 }
1666
1667
1668 void JSObject::AddSlowProperty(Handle<JSObject> object,
1669                                Handle<Name> name,
1670                                Handle<Object> value,
1671                                PropertyAttributes attributes) {
1672   DCHECK(!object->HasFastProperties());
1673   Isolate* isolate = object->GetIsolate();
1674   if (object->IsGlobalObject()) {
1675     Handle<GlobalDictionary> dict(object->global_dictionary());
1676     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1677     int entry = dict->FindEntry(name);
1678     // If there's a cell there, just invalidate and set the property.
1679     if (entry != GlobalDictionary::kNotFound) {
1680       PropertyCell::UpdateCell(dict, entry, value, details);
1681       // TODO(ishell): move this to UpdateCell.
1682       // Need to adjust the details.
1683       int index = dict->NextEnumerationIndex();
1684       dict->SetNextEnumerationIndex(index + 1);
1685       PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
1686       details = cell->property_details().set_index(index);
1687       cell->set_property_details(details);
1688
1689     } else {
1690       auto cell = isolate->factory()->NewPropertyCell();
1691       cell->set_value(*value);
1692       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
1693                                             : PropertyCellType::kConstant;
1694       details = details.set_cell_type(cell_type);
1695       value = cell;
1696
1697       Handle<GlobalDictionary> result =
1698           GlobalDictionary::Add(dict, name, value, details);
1699       if (*dict != *result) object->set_properties(*result);
1700     }
1701   } else {
1702     Handle<NameDictionary> dict(object->property_dictionary());
1703     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1704     Handle<NameDictionary> result =
1705         NameDictionary::Add(dict, name, value, details);
1706     if (*dict != *result) object->set_properties(*result);
1707   }
1708 }
1709
1710
1711 Context* JSObject::GetCreationContext() {
1712   Object* constructor = this->map()->GetConstructor();
1713   JSFunction* function;
1714   if (!constructor->IsJSFunction()) {
1715     // Functions have null as a constructor,
1716     // but any JSFunction knows its context immediately.
1717     function = JSFunction::cast(this);
1718   } else {
1719     function = JSFunction::cast(constructor);
1720   }
1721
1722   return function->context()->native_context();
1723 }
1724
1725
1726 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1727                                                   const char* type_str,
1728                                                   Handle<Name> name,
1729                                                   Handle<Object> old_value) {
1730   DCHECK(!object->IsJSGlobalProxy());
1731   DCHECK(!object->IsJSGlobalObject());
1732   Isolate* isolate = object->GetIsolate();
1733   HandleScope scope(isolate);
1734   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1735   Handle<Object> args[] = { type, object, name, old_value };
1736   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1737
1738   return Execution::Call(isolate,
1739                          Handle<JSFunction>(isolate->observers_notify_change()),
1740                          isolate->factory()->undefined_value(), argc, args);
1741 }
1742
1743
1744 const char* Representation::Mnemonic() const {
1745   switch (kind_) {
1746     case kNone: return "v";
1747     case kTagged: return "t";
1748     case kSmi: return "s";
1749     case kDouble: return "d";
1750     case kInteger32: return "i";
1751     case kHeapObject: return "h";
1752     case kExternal: return "x";
1753     default:
1754       UNREACHABLE();
1755       return NULL;
1756   }
1757 }
1758
1759
1760 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1761                                  int target_inobject, int target_unused,
1762                                  int* old_number_of_fields) {
1763   // If fields were added (or removed), rewrite the instance.
1764   *old_number_of_fields = NumberOfFields();
1765   DCHECK(target_number_of_fields >= *old_number_of_fields);
1766   if (target_number_of_fields != *old_number_of_fields) return true;
1767
1768   // If smi descriptors were replaced by double descriptors, rewrite.
1769   DescriptorArray* old_desc = instance_descriptors();
1770   DescriptorArray* new_desc = target->instance_descriptors();
1771   int limit = NumberOfOwnDescriptors();
1772   for (int i = 0; i < limit; i++) {
1773     if (new_desc->GetDetails(i).representation().IsDouble() !=
1774         old_desc->GetDetails(i).representation().IsDouble()) {
1775       return true;
1776     }
1777   }
1778
1779   // If no fields were added, and no inobject properties were removed, setting
1780   // the map is sufficient.
1781   if (target_inobject == inobject_properties()) return false;
1782   // In-object slack tracking may have reduced the object size of the new map.
1783   // In that case, succeed if all existing fields were inobject, and they still
1784   // fit within the new inobject size.
1785   DCHECK(target_inobject < inobject_properties());
1786   if (target_number_of_fields <= target_inobject) {
1787     DCHECK(target_number_of_fields + target_unused == target_inobject);
1788     return false;
1789   }
1790   // Otherwise, properties will need to be moved to the backing store.
1791   return true;
1792 }
1793
1794
1795 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1796                             int expected_additional_properties) {
1797   if (object->map() == *new_map) return;
1798   // If this object is a prototype (the callee will check), invalidate any
1799   // prototype chains involving it.
1800   InvalidatePrototypeChains(object->map());
1801   Handle<Map> old_map(object->map());
1802
1803   // If the map was registered with its prototype before, ensure that it
1804   // registers with its new prototype now. This preserves the invariant that
1805   // when a map on a prototype chain is registered with its prototype, then
1806   // all prototypes further up the chain are also registered with their
1807   // respective prototypes.
1808   Object* maybe_old_prototype = old_map->prototype();
1809   if (FLAG_track_prototype_users && old_map->is_prototype_map() &&
1810       maybe_old_prototype->IsJSObject()) {
1811     Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
1812     bool was_registered =
1813         JSObject::UnregisterPrototypeUser(old_prototype, old_map);
1814     if (was_registered) {
1815       JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate());
1816     }
1817   }
1818
1819   if (object->HasFastProperties()) {
1820     if (!new_map->is_dictionary_map()) {
1821       MigrateFastToFast(object, new_map);
1822       if (old_map->is_prototype_map()) {
1823         // Clear out the old descriptor array to avoid problems to sharing
1824         // the descriptor array without using an explicit.
1825         old_map->InitializeDescriptors(
1826             old_map->GetHeap()->empty_descriptor_array(),
1827             LayoutDescriptor::FastPointerLayout());
1828         // Ensure that no transition was inserted for prototype migrations.
1829         DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1830                          old_map->raw_transitions()));
1831         DCHECK(new_map->GetBackPointer()->IsUndefined());
1832       }
1833     } else {
1834       MigrateFastToSlow(object, new_map, expected_additional_properties);
1835     }
1836   } else {
1837     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1838     // must be used instead.
1839     CHECK(new_map->is_dictionary_map());
1840
1841     // Slow-to-slow migration is trivial.
1842     object->set_map(*new_map);
1843   }
1844
1845   // Careful: Don't allocate here!
1846   // For some callers of this method, |object| might be in an inconsistent
1847   // state now: the new map might have a new elements_kind, but the object's
1848   // elements pointer hasn't been updated yet. Callers will fix this, but in
1849   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
1850   DisallowHeapAllocation no_object_verification;
1851
1852   if (old_map->is_prototype_map() && FLAG_track_prototype_users) {
1853     DCHECK(new_map->is_prototype_map());
1854     DCHECK(object->map() == *new_map);
1855     new_map->set_prototype_info(old_map->prototype_info());
1856     old_map->set_prototype_info(Smi::FromInt(0));
1857     if (FLAG_trace_prototype_users) {
1858       PrintF("Moving prototype_info %p from map %p to map %p.\n",
1859              reinterpret_cast<void*>(new_map->prototype_info()),
1860              reinterpret_cast<void*>(*old_map),
1861              reinterpret_cast<void*>(*new_map));
1862     }
1863   }
1864 }
1865
1866
1867 // To migrate a fast instance to a fast map:
1868 // - First check whether the instance needs to be rewritten. If not, simply
1869 //   change the map.
1870 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1871 //   addition to unused space.
1872 // - Copy all existing properties in, in the following order: backing store
1873 //   properties, unused fields, inobject properties.
1874 // - If all allocation succeeded, commit the state atomically:
1875 //   * Copy inobject properties from the backing store back into the object.
1876 //   * Trim the difference in instance size of the object. This also cleanly
1877 //     frees inobject properties that moved to the backing store.
1878 //   * If there are properties left in the backing store, trim of the space used
1879 //     to temporarily store the inobject properties.
1880 //   * If there are properties left in the backing store, install the backing
1881 //     store.
1882 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1883   Isolate* isolate = object->GetIsolate();
1884   Handle<Map> old_map(object->map());
1885   int old_number_of_fields;
1886   int number_of_fields = new_map->NumberOfFields();
1887   int inobject = new_map->inobject_properties();
1888   int unused = new_map->unused_property_fields();
1889
1890   // Nothing to do if no functions were converted to fields and no smis were
1891   // converted to doubles.
1892   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1893                                        unused, &old_number_of_fields)) {
1894     object->synchronized_set_map(*new_map);
1895     return;
1896   }
1897
1898   int total_size = number_of_fields + unused;
1899   int external = total_size - inobject;
1900
1901   if (number_of_fields != old_number_of_fields &&
1902       new_map->GetBackPointer() == *old_map) {
1903     PropertyDetails details = new_map->GetLastDescriptorDetails();
1904
1905     if (old_map->unused_property_fields() > 0) {
1906       if (details.representation().IsDouble()) {
1907         FieldIndex index =
1908             FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1909         if (new_map->IsUnboxedDoubleField(index)) {
1910           object->RawFastDoublePropertyAtPut(index, 0);
1911         } else {
1912           Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1913           object->RawFastPropertyAtPut(index, *value);
1914         }
1915       }
1916       object->synchronized_set_map(*new_map);
1917       return;
1918     }
1919
1920     DCHECK(number_of_fields == old_number_of_fields + 1);
1921     // This migration is a transition from a map that has run out of property
1922     // space. Therefore it could be done by extending the backing store.
1923     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1924     Handle<FixedArray> new_storage =
1925         FixedArray::CopySize(old_storage, external);
1926
1927     // Properly initialize newly added property.
1928     Handle<Object> value;
1929     if (details.representation().IsDouble()) {
1930       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1931     } else {
1932       value = isolate->factory()->uninitialized_value();
1933     }
1934     DCHECK(details.type() == DATA);
1935     int target_index = details.field_index() - inobject;
1936     DCHECK(target_index >= 0);  // Must be a backing store index.
1937     new_storage->set(target_index, *value);
1938
1939     // From here on we cannot fail and we shouldn't GC anymore.
1940     DisallowHeapAllocation no_allocation;
1941
1942     // Set the new property value and do the map transition.
1943     object->set_properties(*new_storage);
1944     object->synchronized_set_map(*new_map);
1945     return;
1946   }
1947   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
1948
1949   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
1950   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
1951   int old_nof = old_map->NumberOfOwnDescriptors();
1952   int new_nof = new_map->NumberOfOwnDescriptors();
1953
1954   // This method only supports generalizing instances to at least the same
1955   // number of properties.
1956   DCHECK(old_nof <= new_nof);
1957
1958   for (int i = 0; i < old_nof; i++) {
1959     PropertyDetails details = new_descriptors->GetDetails(i);
1960     if (details.type() != DATA) continue;
1961     PropertyDetails old_details = old_descriptors->GetDetails(i);
1962     Representation old_representation = old_details.representation();
1963     Representation representation = details.representation();
1964     Handle<Object> value;
1965     if (old_details.type() == ACCESSOR_CONSTANT) {
1966       // In case of kAccessor -> kData property reconfiguration, the property
1967       // must already be prepared for data or certain type.
1968       DCHECK(!details.representation().IsNone());
1969       if (details.representation().IsDouble()) {
1970         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1971       } else {
1972         value = isolate->factory()->uninitialized_value();
1973       }
1974     } else if (old_details.type() == DATA_CONSTANT) {
1975       value = handle(old_descriptors->GetValue(i), isolate);
1976       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
1977     } else {
1978       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
1979       if (object->IsUnboxedDoubleField(index)) {
1980         double old = object->RawFastDoublePropertyAt(index);
1981         value = isolate->factory()->NewHeapNumber(
1982             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
1983
1984       } else {
1985         value = handle(object->RawFastPropertyAt(index), isolate);
1986         if (!old_representation.IsDouble() && representation.IsDouble()) {
1987           if (old_representation.IsNone()) {
1988             value = handle(Smi::FromInt(0), isolate);
1989           }
1990           value = Object::NewStorageFor(isolate, value, representation);
1991         } else if (old_representation.IsDouble() &&
1992                    !representation.IsDouble()) {
1993           value = Object::WrapForRead(isolate, value, old_representation);
1994         }
1995       }
1996     }
1997     DCHECK(!(representation.IsDouble() && value->IsSmi()));
1998     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
1999     if (target_index < 0) target_index += total_size;
2000     array->set(target_index, *value);
2001   }
2002
2003   for (int i = old_nof; i < new_nof; i++) {
2004     PropertyDetails details = new_descriptors->GetDetails(i);
2005     if (details.type() != DATA) continue;
2006     Handle<Object> value;
2007     if (details.representation().IsDouble()) {
2008       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2009     } else {
2010       value = isolate->factory()->uninitialized_value();
2011     }
2012     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2013     if (target_index < 0) target_index += total_size;
2014     array->set(target_index, *value);
2015   }
2016
2017   // From here on we cannot fail and we shouldn't GC anymore.
2018   DisallowHeapAllocation no_allocation;
2019
2020   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2021   // avoid overwriting |one_pointer_filler_map|.
2022   int limit = Min(inobject, number_of_fields);
2023   for (int i = 0; i < limit; i++) {
2024     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2025     Object* value = array->get(external + i);
2026     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
2027     // yet.
2028     if (new_map->IsUnboxedDoubleField(index)) {
2029       DCHECK(value->IsMutableHeapNumber());
2030       object->RawFastDoublePropertyAtPut(index,
2031                                          HeapNumber::cast(value)->value());
2032     } else {
2033       object->RawFastPropertyAtPut(index, value);
2034     }
2035   }
2036
2037   Heap* heap = isolate->heap();
2038
2039   // If there are properties in the new backing store, trim it to the correct
2040   // size and install the backing store into the object.
2041   if (external > 0) {
2042     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
2043     object->set_properties(*array);
2044   }
2045
2046   // Create filler object past the new instance size.
2047   int new_instance_size = new_map->instance_size();
2048   int instance_size_delta = old_map->instance_size() - new_instance_size;
2049   DCHECK(instance_size_delta >= 0);
2050
2051   if (instance_size_delta > 0) {
2052     Address address = object->address();
2053     heap->CreateFillerObjectAt(
2054         address + new_instance_size, instance_size_delta);
2055     heap->AdjustLiveBytes(address, -instance_size_delta,
2056                           Heap::CONCURRENT_TO_SWEEPER);
2057   }
2058
2059   // We are storing the new map using release store after creating a filler for
2060   // the left-over space to avoid races with the sweeper thread.
2061   object->synchronized_set_map(*new_map);
2062 }
2063
2064
2065 int Map::NumberOfFields() {
2066   DescriptorArray* descriptors = instance_descriptors();
2067   int result = 0;
2068   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2069     if (descriptors->GetDetails(i).location() == kField) result++;
2070   }
2071   return result;
2072 }
2073
2074
2075 Handle<Map> Map::CopyGeneralizeAllRepresentations(
2076     Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
2077     PropertyAttributes attributes, const char* reason) {
2078   Isolate* isolate = map->GetIsolate();
2079   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2080   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2081   Handle<DescriptorArray> descriptors =
2082       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
2083
2084   for (int i = 0; i < number_of_own_descriptors; i++) {
2085     descriptors->SetRepresentation(i, Representation::Tagged());
2086     if (descriptors->GetDetails(i).type() == DATA) {
2087       descriptors->SetValue(i, HeapType::Any());
2088     }
2089   }
2090
2091   Handle<LayoutDescriptor> new_layout_descriptor(
2092       LayoutDescriptor::FastPointerLayout(), isolate);
2093   Handle<Map> new_map = CopyReplaceDescriptors(
2094       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
2095       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
2096
2097   // Unless the instance is being migrated, ensure that modify_index is a field.
2098   if (modify_index >= 0) {
2099     PropertyDetails details = descriptors->GetDetails(modify_index);
2100     if (store_mode == FORCE_FIELD &&
2101         (details.type() != DATA || details.attributes() != attributes)) {
2102       int field_index = details.type() == DATA ? details.field_index()
2103                                                : new_map->NumberOfFields();
2104       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2105                        field_index, attributes, Representation::Tagged());
2106       descriptors->Replace(modify_index, &d);
2107       if (details.type() != DATA) {
2108         int unused_property_fields = new_map->unused_property_fields() - 1;
2109         if (unused_property_fields < 0) {
2110           unused_property_fields += JSObject::kFieldsAdded;
2111         }
2112         new_map->set_unused_property_fields(unused_property_fields);
2113       }
2114     } else {
2115       DCHECK(details.attributes() == attributes);
2116     }
2117
2118     if (FLAG_trace_generalization) {
2119       HeapType* field_type =
2120           (details.type() == DATA)
2121               ? map->instance_descriptors()->GetFieldType(modify_index)
2122               : NULL;
2123       map->PrintGeneralization(
2124           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
2125           new_map->NumberOfOwnDescriptors(),
2126           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
2127           details.representation(), Representation::Tagged(), field_type,
2128           HeapType::Any());
2129     }
2130   }
2131   return new_map;
2132 }
2133
2134
2135 void Map::DeprecateTransitionTree() {
2136   if (is_deprecated()) return;
2137   Object* transitions = raw_transitions();
2138   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2139   for (int i = 0; i < num_transitions; ++i) {
2140     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
2141   }
2142   deprecate();
2143   dependent_code()->DeoptimizeDependentCodeGroup(
2144       GetIsolate(), DependentCode::kTransitionGroup);
2145   NotifyLeafMapLayoutChange();
2146 }
2147
2148
2149 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2150   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
2151   // TODO(ishell): compare AccessorPairs.
2152   return false;
2153 }
2154
2155
2156 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2157 // the current instance_descriptors to ensure proper sharing of descriptor
2158 // arrays.
2159 // Returns true if the transition target at given key was deprecated.
2160 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2161                           PropertyAttributes attributes,
2162                           DescriptorArray* new_descriptors,
2163                           LayoutDescriptor* new_layout_descriptor) {
2164   bool transition_target_deprecated = false;
2165   Map* maybe_transition =
2166       TransitionArray::SearchTransition(this, kind, key, attributes);
2167   if (maybe_transition != NULL) {
2168     maybe_transition->DeprecateTransitionTree();
2169     transition_target_deprecated = true;
2170   }
2171
2172   // Don't overwrite the empty descriptor array.
2173   if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
2174
2175   DescriptorArray* to_replace = instance_descriptors();
2176   Map* current = this;
2177   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2178   while (current->instance_descriptors() == to_replace) {
2179     current->SetEnumLength(kInvalidEnumCacheSentinel);
2180     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2181     Object* next = current->GetBackPointer();
2182     if (next->IsUndefined()) break;
2183     current = Map::cast(next);
2184   }
2185
2186   set_owns_descriptors(false);
2187   return transition_target_deprecated;
2188 }
2189
2190
2191 Map* Map::FindRootMap() {
2192   Map* result = this;
2193   while (true) {
2194     Object* back = result->GetBackPointer();
2195     if (back->IsUndefined()) return result;
2196     result = Map::cast(back);
2197   }
2198 }
2199
2200
2201 Map* Map::FindLastMatchMap(int verbatim,
2202                            int length,
2203                            DescriptorArray* descriptors) {
2204   DisallowHeapAllocation no_allocation;
2205
2206   // This can only be called on roots of transition trees.
2207   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
2208
2209   Map* current = this;
2210
2211   for (int i = verbatim; i < length; i++) {
2212     Name* name = descriptors->GetKey(i);
2213     PropertyDetails details = descriptors->GetDetails(i);
2214     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
2215                                                   details.attributes());
2216     if (next == NULL) break;
2217     DescriptorArray* next_descriptors = next->instance_descriptors();
2218
2219     PropertyDetails next_details = next_descriptors->GetDetails(i);
2220     DCHECK_EQ(details.kind(), next_details.kind());
2221     DCHECK_EQ(details.attributes(), next_details.attributes());
2222     if (details.location() != next_details.location()) break;
2223     if (!details.representation().Equals(next_details.representation())) break;
2224
2225     if (next_details.location() == kField) {
2226       HeapType* next_field_type = next_descriptors->GetFieldType(i);
2227       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
2228         break;
2229       }
2230     } else {
2231       if (!EqualImmutableValues(descriptors->GetValue(i),
2232                                 next_descriptors->GetValue(i))) {
2233         break;
2234       }
2235     }
2236     current = next;
2237   }
2238   return current;
2239 }
2240
2241
2242 Map* Map::FindFieldOwner(int descriptor) {
2243   DisallowHeapAllocation no_allocation;
2244   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
2245   Map* result = this;
2246   while (true) {
2247     Object* back = result->GetBackPointer();
2248     if (back->IsUndefined()) break;
2249     Map* parent = Map::cast(back);
2250     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2251     result = parent;
2252   }
2253   return result;
2254 }
2255
2256
2257 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2258                           Representation new_representation,
2259                           Handle<Object> new_wrapped_type) {
2260   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
2261   DisallowHeapAllocation no_allocation;
2262   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2263   if (details.type() != DATA) return;
2264   Object* transitions = raw_transitions();
2265   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2266   for (int i = 0; i < num_transitions; ++i) {
2267     Map* target = TransitionArray::GetTarget(transitions, i);
2268     target->UpdateFieldType(descriptor, name, new_representation,
2269                             new_wrapped_type);
2270   }
2271   // It is allowed to change representation here only from None to something.
2272   DCHECK(details.representation().Equals(new_representation) ||
2273          details.representation().IsNone());
2274
2275   // Skip if already updated the shared descriptor.
2276   if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return;
2277   DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2278                    new_wrapped_type, details.attributes(), new_representation);
2279   instance_descriptors()->Replace(descriptor, &d);
2280 }
2281
2282
2283 // static
2284 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2285                                           Handle<HeapType> type2,
2286                                           Isolate* isolate) {
2287   if (type1->NowIs(type2)) return type2;
2288   if (type2->NowIs(type1)) return type1;
2289   return HeapType::Any(isolate);
2290 }
2291
2292
2293 // static
2294 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
2295                               Representation new_representation,
2296                               Handle<HeapType> new_field_type) {
2297   Isolate* isolate = map->GetIsolate();
2298
2299   // Check if we actually need to generalize the field type at all.
2300   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2301   Representation old_representation =
2302       old_descriptors->GetDetails(modify_index).representation();
2303   Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
2304                                   isolate);
2305
2306   if (old_representation.Equals(new_representation) &&
2307       new_field_type->NowIs(old_field_type)) {
2308     DCHECK(Map::GeneralizeFieldType(old_field_type,
2309                                     new_field_type,
2310                                     isolate)->NowIs(old_field_type));
2311     return;
2312   }
2313
2314   // Determine the field owner.
2315   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2316   Handle<DescriptorArray> descriptors(
2317       field_owner->instance_descriptors(), isolate);
2318   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2319   bool old_field_type_was_cleared =
2320       old_field_type->Is(HeapType::None()) && old_representation.IsHeapObject();
2321
2322   // Determine the generalized new field type. Conservatively assume type Any
2323   // for cleared field types because the cleared type could have been a
2324   // deprecated map and there still could be live instances with a non-
2325   // deprecated version of the map.
2326   new_field_type =
2327       old_field_type_was_cleared
2328           ? HeapType::Any(isolate)
2329           : Map::GeneralizeFieldType(old_field_type, new_field_type, isolate);
2330
2331   PropertyDetails details = descriptors->GetDetails(modify_index);
2332   Handle<Name> name(descriptors->GetKey(modify_index));
2333
2334   Handle<Object> wrapped_type(WrapType(new_field_type));
2335   field_owner->UpdateFieldType(modify_index, name, new_representation,
2336                                wrapped_type);
2337   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2338       isolate, DependentCode::kFieldTypeGroup);
2339
2340   if (FLAG_trace_generalization) {
2341     map->PrintGeneralization(
2342         stdout, "field type generalization",
2343         modify_index, map->NumberOfOwnDescriptors(),
2344         map->NumberOfOwnDescriptors(), false,
2345         details.representation(), details.representation(),
2346         *old_field_type, *new_field_type);
2347   }
2348 }
2349
2350
2351 static inline Handle<HeapType> GetFieldType(Isolate* isolate,
2352                                             Handle<DescriptorArray> descriptors,
2353                                             int descriptor,
2354                                             PropertyLocation location,
2355                                             Representation representation) {
2356 #ifdef DEBUG
2357   PropertyDetails details = descriptors->GetDetails(descriptor);
2358   DCHECK_EQ(kData, details.kind());
2359   DCHECK_EQ(details.location(), location);
2360 #endif
2361   if (location == kField) {
2362     return handle(descriptors->GetFieldType(descriptor), isolate);
2363   } else {
2364     return descriptors->GetValue(descriptor)
2365         ->OptimalType(isolate, representation);
2366   }
2367 }
2368
2369
2370 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
2371 // |store_mode| and/or |new_representation|/|new_field_type|.
2372 // If |modify_index| is negative then no properties are reconfigured but the
2373 // map is migrated to the up-to-date non-deprecated state.
2374 //
2375 // This method rewrites or completes the transition tree to reflect the new
2376 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
2377 // on every rewrite the new type is deduced by merging the current type with
2378 // any potential new (partial) version of the type in the transition tree.
2379 // To do this, on each rewrite:
2380 // - Search the root of the transition tree using FindRootMap.
2381 // - Find |target_map|, the newest matching version of this map using the
2382 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
2383 //   |modify_index| is considered to be of |new_kind| and having
2384 //   |new_attributes|) to walk the transition tree.
2385 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
2386 //   descriptor array of the |target_map|.
2387 // - Generalize the |modify_index| descriptor using |new_representation| and
2388 //   |new_field_type|.
2389 // - Walk the tree again starting from the root towards |target_map|. Stop at
2390 //   |split_map|, the first map who's descriptor array does not match the merged
2391 //   descriptor array.
2392 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2393 //   Return it.
2394 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2395 //   replace its transition tree with a new branch for the updated descriptors.
2396 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2397                                      PropertyKind new_kind,
2398                                      PropertyAttributes new_attributes,
2399                                      Representation new_representation,
2400                                      Handle<HeapType> new_field_type,
2401                                      StoreMode store_mode) {
2402   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
2403   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2404   Isolate* isolate = old_map->GetIsolate();
2405
2406   Handle<DescriptorArray> old_descriptors(
2407       old_map->instance_descriptors(), isolate);
2408   int old_nof = old_map->NumberOfOwnDescriptors();
2409
2410   // If it's just a representation generalization case (i.e. property kind and
2411   // attributes stays unchanged) it's fine to transition from None to anything
2412   // but double without any modification to the object, because the default
2413   // uninitialized value for representation None can be overwritten by both
2414   // smi and tagged values. Doubles, however, would require a box allocation.
2415   if (modify_index >= 0 && !new_representation.IsNone() &&
2416       !new_representation.IsDouble()) {
2417     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2418     Representation old_representation = old_details.representation();
2419
2420     if (old_representation.IsNone()) {
2421       DCHECK_EQ(new_kind, old_details.kind());
2422       DCHECK_EQ(new_attributes, old_details.attributes());
2423       DCHECK_EQ(DATA, old_details.type());
2424       if (FLAG_trace_generalization) {
2425         old_map->PrintGeneralization(
2426             stdout, "uninitialized field", modify_index,
2427             old_map->NumberOfOwnDescriptors(),
2428             old_map->NumberOfOwnDescriptors(), false, old_representation,
2429             new_representation, old_descriptors->GetFieldType(modify_index),
2430             *new_field_type);
2431       }
2432       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2433
2434       GeneralizeFieldType(field_owner, modify_index, new_representation,
2435                           new_field_type);
2436       DCHECK(old_descriptors->GetDetails(modify_index)
2437                  .representation()
2438                  .Equals(new_representation));
2439       DCHECK(
2440           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2441       return old_map;
2442     }
2443   }
2444
2445   // Check the state of the root map.
2446   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2447   if (!old_map->EquivalentToForTransition(*root_map)) {
2448     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2449                                             new_kind, new_attributes,
2450                                             "GenAll_NotEquivalent");
2451   }
2452
2453   ElementsKind from_kind = root_map->elements_kind();
2454   ElementsKind to_kind = old_map->elements_kind();
2455   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
2456   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
2457       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
2458       !(IsTransitionableFastElementsKind(from_kind) &&
2459         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2460     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2461                                             new_kind, new_attributes,
2462                                             "GenAll_InvalidElementsTransition");
2463   }
2464   int root_nof = root_map->NumberOfOwnDescriptors();
2465   if (modify_index >= 0 && modify_index < root_nof) {
2466     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2467     if (old_details.kind() != new_kind ||
2468         old_details.attributes() != new_attributes) {
2469       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2470                                               new_kind, new_attributes,
2471                                               "GenAll_RootModification1");
2472     }
2473     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2474         (old_details.type() == DATA &&
2475          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2476           !new_representation.fits_into(old_details.representation())))) {
2477       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2478                                               new_kind, new_attributes,
2479                                               "GenAll_RootModification2");
2480     }
2481   }
2482
2483   // From here on, use the map with correct elements kind as root map.
2484   if (from_kind != to_kind) {
2485     root_map = Map::AsElementsKind(root_map, to_kind);
2486   }
2487
2488   Handle<Map> target_map = root_map;
2489   for (int i = root_nof; i < old_nof; ++i) {
2490     PropertyDetails old_details = old_descriptors->GetDetails(i);
2491     PropertyKind next_kind;
2492     PropertyLocation next_location;
2493     PropertyAttributes next_attributes;
2494     Representation next_representation;
2495     bool property_kind_reconfiguration = false;
2496
2497     if (modify_index == i) {
2498       DCHECK_EQ(FORCE_FIELD, store_mode);
2499       property_kind_reconfiguration = old_details.kind() != new_kind;
2500
2501       next_kind = new_kind;
2502       next_location = kField;
2503       next_attributes = new_attributes;
2504       // If property kind is not reconfigured merge the result with
2505       // representation/field type from the old descriptor.
2506       next_representation = new_representation;
2507       if (!property_kind_reconfiguration) {
2508         next_representation =
2509             next_representation.generalize(old_details.representation());
2510       }
2511
2512     } else {
2513       next_kind = old_details.kind();
2514       next_location = old_details.location();
2515       next_attributes = old_details.attributes();
2516       next_representation = old_details.representation();
2517     }
2518     Map* transition = TransitionArray::SearchTransition(
2519         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2520     if (transition == NULL) break;
2521     Handle<Map> tmp_map(transition, isolate);
2522
2523     Handle<DescriptorArray> tmp_descriptors = handle(
2524         tmp_map->instance_descriptors(), isolate);
2525
2526     // Check if target map is incompatible.
2527     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2528     DCHECK_EQ(next_kind, tmp_details.kind());
2529     DCHECK_EQ(next_attributes, tmp_details.attributes());
2530     if (next_kind == kAccessor &&
2531         !EqualImmutableValues(old_descriptors->GetValue(i),
2532                               tmp_descriptors->GetValue(i))) {
2533       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2534                                               new_kind, new_attributes,
2535                                               "GenAll_Incompatible");
2536     }
2537     if (next_location == kField && tmp_details.location() == kDescriptor) break;
2538
2539     Representation tmp_representation = tmp_details.representation();
2540     if (!next_representation.fits_into(tmp_representation)) break;
2541
2542     PropertyLocation old_location = old_details.location();
2543     PropertyLocation tmp_location = tmp_details.location();
2544     if (tmp_location == kField) {
2545       if (next_kind == kData) {
2546         Handle<HeapType> next_field_type;
2547         if (modify_index == i) {
2548           next_field_type = new_field_type;
2549           if (!property_kind_reconfiguration) {
2550             Handle<HeapType> old_field_type =
2551                 GetFieldType(isolate, old_descriptors, i,
2552                              old_details.location(), tmp_representation);
2553             next_field_type =
2554                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2555           }
2556         } else {
2557           Handle<HeapType> old_field_type =
2558               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2559                            tmp_representation);
2560           next_field_type = old_field_type;
2561         }
2562         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
2563       }
2564     } else if (old_location == kField ||
2565                !EqualImmutableValues(old_descriptors->GetValue(i),
2566                                      tmp_descriptors->GetValue(i))) {
2567       break;
2568     }
2569     DCHECK(!tmp_map->is_deprecated());
2570     target_map = tmp_map;
2571   }
2572
2573   // Directly change the map if the target map is more general.
2574   Handle<DescriptorArray> target_descriptors(
2575       target_map->instance_descriptors(), isolate);
2576   int target_nof = target_map->NumberOfOwnDescriptors();
2577   if (target_nof == old_nof &&
2578       (store_mode != FORCE_FIELD ||
2579        (modify_index >= 0 &&
2580         target_descriptors->GetDetails(modify_index).location() == kField))) {
2581 #ifdef DEBUG
2582     if (modify_index >= 0) {
2583       PropertyDetails details = target_descriptors->GetDetails(modify_index);
2584       DCHECK_EQ(new_kind, details.kind());
2585       DCHECK_EQ(new_attributes, details.attributes());
2586       DCHECK(new_representation.fits_into(details.representation()));
2587       DCHECK(details.location() != kField ||
2588              new_field_type->NowIs(
2589                  target_descriptors->GetFieldType(modify_index)));
2590     }
2591 #endif
2592     if (*target_map != *old_map) {
2593       old_map->NotifyLeafMapLayoutChange();
2594     }
2595     return target_map;
2596   }
2597
2598   // Find the last compatible target map in the transition tree.
2599   for (int i = target_nof; i < old_nof; ++i) {
2600     PropertyDetails old_details = old_descriptors->GetDetails(i);
2601     PropertyKind next_kind;
2602     PropertyAttributes next_attributes;
2603     if (modify_index == i) {
2604       next_kind = new_kind;
2605       next_attributes = new_attributes;
2606     } else {
2607       next_kind = old_details.kind();
2608       next_attributes = old_details.attributes();
2609     }
2610     Map* transition = TransitionArray::SearchTransition(
2611         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2612     if (transition == NULL) break;
2613     Handle<Map> tmp_map(transition, isolate);
2614     Handle<DescriptorArray> tmp_descriptors(
2615         tmp_map->instance_descriptors(), isolate);
2616
2617     // Check if target map is compatible.
2618 #ifdef DEBUG
2619     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2620     DCHECK_EQ(next_kind, tmp_details.kind());
2621     DCHECK_EQ(next_attributes, tmp_details.attributes());
2622 #endif
2623     if (next_kind == kAccessor &&
2624         !EqualImmutableValues(old_descriptors->GetValue(i),
2625                               tmp_descriptors->GetValue(i))) {
2626       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2627                                               new_kind, new_attributes,
2628                                               "GenAll_Incompatible");
2629     }
2630     DCHECK(!tmp_map->is_deprecated());
2631     target_map = tmp_map;
2632   }
2633   target_nof = target_map->NumberOfOwnDescriptors();
2634   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2635
2636   // Allocate a new descriptor array large enough to hold the required
2637   // descriptors, with minimally the exact same size as the old descriptor
2638   // array.
2639   int new_slack = Max(
2640       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2641   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2642       isolate, old_nof, new_slack);
2643   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2644          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2645          new_descriptors->number_of_descriptors() ==
2646          old_descriptors->number_of_descriptors());
2647   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2648
2649   // 0 -> |root_nof|
2650   int current_offset = 0;
2651   for (int i = 0; i < root_nof; ++i) {
2652     PropertyDetails old_details = old_descriptors->GetDetails(i);
2653     if (old_details.location() == kField) {
2654       current_offset += old_details.field_width_in_words();
2655     }
2656     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2657                  handle(old_descriptors->GetValue(i), isolate),
2658                  old_details);
2659     new_descriptors->Set(i, &d);
2660   }
2661
2662   // |root_nof| -> |target_nof|
2663   for (int i = root_nof; i < target_nof; ++i) {
2664     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2665     PropertyDetails old_details = old_descriptors->GetDetails(i);
2666     PropertyDetails target_details = target_descriptors->GetDetails(i);
2667
2668     PropertyKind next_kind;
2669     PropertyAttributes next_attributes;
2670     PropertyLocation next_location;
2671     Representation next_representation;
2672     bool property_kind_reconfiguration = false;
2673
2674     if (modify_index == i) {
2675       DCHECK_EQ(FORCE_FIELD, store_mode);
2676       property_kind_reconfiguration = old_details.kind() != new_kind;
2677
2678       next_kind = new_kind;
2679       next_attributes = new_attributes;
2680       next_location = kField;
2681
2682       // Merge new representation/field type with ones from the target
2683       // descriptor. If property kind is not reconfigured merge the result with
2684       // representation/field type from the old descriptor.
2685       next_representation =
2686           new_representation.generalize(target_details.representation());
2687       if (!property_kind_reconfiguration) {
2688         next_representation =
2689             next_representation.generalize(old_details.representation());
2690       }
2691     } else {
2692       // Merge old_descriptor and target_descriptor entries.
2693       DCHECK_EQ(target_details.kind(), old_details.kind());
2694       next_kind = target_details.kind();
2695       next_attributes = target_details.attributes();
2696       next_location =
2697           old_details.location() == kField ||
2698                   target_details.location() == kField ||
2699                   !EqualImmutableValues(target_descriptors->GetValue(i),
2700                                         old_descriptors->GetValue(i))
2701               ? kField
2702               : kDescriptor;
2703
2704       next_representation = old_details.representation().generalize(
2705           target_details.representation());
2706     }
2707     DCHECK_EQ(next_kind, target_details.kind());
2708     DCHECK_EQ(next_attributes, target_details.attributes());
2709
2710     if (next_location == kField) {
2711       if (next_kind == kData) {
2712         Handle<HeapType> target_field_type =
2713             GetFieldType(isolate, target_descriptors, i,
2714                          target_details.location(), next_representation);
2715
2716         Handle<HeapType> next_field_type;
2717         if (modify_index == i) {
2718           next_field_type =
2719               GeneralizeFieldType(target_field_type, new_field_type, isolate);
2720           if (!property_kind_reconfiguration) {
2721             Handle<HeapType> old_field_type =
2722                 GetFieldType(isolate, old_descriptors, i,
2723                              old_details.location(), next_representation);
2724             next_field_type =
2725                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2726           }
2727         } else {
2728           Handle<HeapType> old_field_type =
2729               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2730                            next_representation);
2731           next_field_type =
2732               GeneralizeFieldType(target_field_type, old_field_type, isolate);
2733         }
2734         Handle<Object> wrapped_type(WrapType(next_field_type));
2735         DataDescriptor d(target_key, current_offset, wrapped_type,
2736                          next_attributes, next_representation);
2737         current_offset += d.GetDetails().field_width_in_words();
2738         new_descriptors->Set(i, &d);
2739       } else {
2740         UNIMPLEMENTED();  // TODO(ishell): implement.
2741       }
2742     } else {
2743       PropertyDetails details(next_attributes, next_kind, next_location,
2744                               next_representation);
2745       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
2746                    details);
2747       new_descriptors->Set(i, &d);
2748     }
2749   }
2750
2751   // |target_nof| -> |old_nof|
2752   for (int i = target_nof; i < old_nof; ++i) {
2753     PropertyDetails old_details = old_descriptors->GetDetails(i);
2754     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2755
2756     // Merge old_descriptor entry and modified details together.
2757     PropertyKind next_kind;
2758     PropertyAttributes next_attributes;
2759     PropertyLocation next_location;
2760     Representation next_representation;
2761     bool property_kind_reconfiguration = false;
2762
2763     if (modify_index == i) {
2764       DCHECK_EQ(FORCE_FIELD, store_mode);
2765       // In case of property kind reconfiguration it is not necessary to
2766       // take into account representation/field type of the old descriptor.
2767       property_kind_reconfiguration = old_details.kind() != new_kind;
2768
2769       next_kind = new_kind;
2770       next_attributes = new_attributes;
2771       next_location = kField;
2772       next_representation = new_representation;
2773       if (!property_kind_reconfiguration) {
2774         next_representation =
2775             next_representation.generalize(old_details.representation());
2776       }
2777     } else {
2778       next_kind = old_details.kind();
2779       next_attributes = old_details.attributes();
2780       next_location = old_details.location();
2781       next_representation = old_details.representation();
2782     }
2783
2784     if (next_location == kField) {
2785       if (next_kind == kData) {
2786         Handle<HeapType> next_field_type;
2787         if (modify_index == i) {
2788           next_field_type = new_field_type;
2789           if (!property_kind_reconfiguration) {
2790             Handle<HeapType> old_field_type =
2791                 GetFieldType(isolate, old_descriptors, i,
2792                              old_details.location(), next_representation);
2793             next_field_type =
2794                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2795           }
2796         } else {
2797           Handle<HeapType> old_field_type =
2798               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2799                            next_representation);
2800           next_field_type = old_field_type;
2801         }
2802
2803         Handle<Object> wrapped_type(WrapType(next_field_type));
2804
2805         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
2806                          next_representation);
2807         current_offset += d.GetDetails().field_width_in_words();
2808         new_descriptors->Set(i, &d);
2809       } else {
2810         UNIMPLEMENTED();  // TODO(ishell): implement.
2811       }
2812     } else {
2813       PropertyDetails details(next_attributes, next_kind, next_location,
2814                               next_representation);
2815       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
2816                    details);
2817       new_descriptors->Set(i, &d);
2818     }
2819   }
2820
2821   new_descriptors->Sort();
2822
2823   DCHECK(store_mode != FORCE_FIELD ||
2824          new_descriptors->GetDetails(modify_index).location() == kField);
2825
2826   Handle<Map> split_map(root_map->FindLastMatchMap(
2827           root_nof, old_nof, *new_descriptors), isolate);
2828   int split_nof = split_map->NumberOfOwnDescriptors();
2829   DCHECK_NE(old_nof, split_nof);
2830
2831   Handle<LayoutDescriptor> new_layout_descriptor =
2832       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
2833
2834   PropertyKind split_kind;
2835   PropertyAttributes split_attributes;
2836   if (modify_index == split_nof) {
2837     split_kind = new_kind;
2838     split_attributes = new_attributes;
2839   } else {
2840     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
2841     split_kind = split_prop_details.kind();
2842     split_attributes = split_prop_details.attributes();
2843   }
2844   bool transition_target_deprecated = split_map->DeprecateTarget(
2845       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2846       *new_descriptors, *new_layout_descriptor);
2847
2848   // If |transition_target_deprecated| is true then the transition array
2849   // already contains entry for given descriptor. This means that the transition
2850   // could be inserted regardless of whether transitions array is full or not.
2851   if (!transition_target_deprecated &&
2852       !TransitionArray::CanHaveMoreTransitions(split_map)) {
2853     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2854                                             new_kind, new_attributes,
2855                                             "GenAll_CantHaveMoreTransitions");
2856   }
2857
2858   old_map->NotifyLeafMapLayoutChange();
2859
2860   if (FLAG_trace_generalization && modify_index >= 0) {
2861     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2862     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2863     Handle<HeapType> old_field_type =
2864         (old_details.type() == DATA)
2865             ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2866             : HeapType::Constant(
2867                   handle(old_descriptors->GetValue(modify_index), isolate),
2868                   isolate);
2869     Handle<HeapType> new_field_type =
2870         (new_details.type() == DATA)
2871             ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2872             : HeapType::Constant(
2873                   handle(new_descriptors->GetValue(modify_index), isolate),
2874                   isolate);
2875     old_map->PrintGeneralization(
2876         stdout, "", modify_index, split_nof, old_nof,
2877         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2878         old_details.representation(), new_details.representation(),
2879         *old_field_type, *new_field_type);
2880   }
2881
2882   // Add missing transitions.
2883   Handle<Map> new_map = split_map;
2884   for (int i = split_nof; i < old_nof; ++i) {
2885     new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2886                                      new_layout_descriptor);
2887   }
2888   new_map->set_owns_descriptors(true);
2889   return new_map;
2890 }
2891
2892
2893 // Generalize the representation of all DATA descriptors.
2894 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2895     Handle<Map> map) {
2896   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2897   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2898     PropertyDetails details = descriptors->GetDetails(i);
2899     if (details.type() == DATA) {
2900       map = ReconfigureProperty(map, i, kData, details.attributes(),
2901                                 Representation::Tagged(),
2902                                 HeapType::Any(map->GetIsolate()), FORCE_FIELD);
2903     }
2904   }
2905   return map;
2906 }
2907
2908
2909 // static
2910 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
2911   DisallowHeapAllocation no_allocation;
2912   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2913
2914   if (!old_map->is_deprecated()) return old_map;
2915
2916   // Check the state of the root map.
2917   Map* root_map = old_map->FindRootMap();
2918   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2919
2920   ElementsKind from_kind = root_map->elements_kind();
2921   ElementsKind to_kind = old_map->elements_kind();
2922   if (from_kind != to_kind) {
2923     // Try to follow existing elements kind transitions.
2924     root_map = root_map->LookupElementsTransitionMap(to_kind);
2925     if (root_map == NULL) return MaybeHandle<Map>();
2926     // From here on, use the map with correct elements kind as root map.
2927   }
2928   int root_nof = root_map->NumberOfOwnDescriptors();
2929
2930   int old_nof = old_map->NumberOfOwnDescriptors();
2931   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2932
2933   Map* new_map = root_map;
2934   for (int i = root_nof; i < old_nof; ++i) {
2935     PropertyDetails old_details = old_descriptors->GetDetails(i);
2936     Map* transition = TransitionArray::SearchTransition(
2937         new_map, old_details.kind(), old_descriptors->GetKey(i),
2938         old_details.attributes());
2939     if (transition == NULL) return MaybeHandle<Map>();
2940     new_map = transition;
2941     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2942
2943     PropertyDetails new_details = new_descriptors->GetDetails(i);
2944     DCHECK_EQ(old_details.kind(), new_details.kind());
2945     DCHECK_EQ(old_details.attributes(), new_details.attributes());
2946     if (!old_details.representation().fits_into(new_details.representation())) {
2947       return MaybeHandle<Map>();
2948     }
2949     switch (new_details.type()) {
2950       case DATA: {
2951         HeapType* new_type = new_descriptors->GetFieldType(i);
2952         PropertyType old_property_type = old_details.type();
2953         if (old_property_type == DATA) {
2954           HeapType* old_type = old_descriptors->GetFieldType(i);
2955           if (!old_type->NowIs(new_type)) {
2956             return MaybeHandle<Map>();
2957           }
2958         } else {
2959           DCHECK(old_property_type == DATA_CONSTANT);
2960           Object* old_value = old_descriptors->GetValue(i);
2961           if (!new_type->NowContains(old_value)) {
2962             return MaybeHandle<Map>();
2963           }
2964         }
2965         break;
2966       }
2967       case ACCESSOR: {
2968 #ifdef DEBUG
2969         HeapType* new_type = new_descriptors->GetFieldType(i);
2970         DCHECK(HeapType::Any()->Is(new_type));
2971 #endif
2972         break;
2973       }
2974
2975       case DATA_CONSTANT:
2976       case ACCESSOR_CONSTANT: {
2977         Object* old_value = old_descriptors->GetValue(i);
2978         Object* new_value = new_descriptors->GetValue(i);
2979         if (old_details.location() == kField || old_value != new_value) {
2980           return MaybeHandle<Map>();
2981         }
2982         break;
2983       }
2984     }
2985   }
2986   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2987   return handle(new_map);
2988 }
2989
2990
2991 // static
2992 Handle<Map> Map::Update(Handle<Map> map) {
2993   if (!map->is_deprecated()) return map;
2994   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
2995                              HeapType::None(map->GetIsolate()),
2996                              ALLOW_IN_DESCRIPTOR);
2997 }
2998
2999
3000 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
3001                                                          Handle<Object> value) {
3002   Isolate* isolate = it->isolate();
3003   // Make sure that the top context does not change when doing callbacks or
3004   // interceptor calls.
3005   AssertNoContextChange ncc(isolate);
3006
3007   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
3008   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
3009   if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
3010
3011   Handle<JSObject> holder = it->GetHolder<JSObject>();
3012   v8::Local<v8::Value> result;
3013   PropertyCallbackArguments args(isolate, interceptor->data(),
3014                                  *it->GetReceiver(), *holder);
3015
3016   if (it->IsElement()) {
3017     uint32_t index = it->index();
3018     v8::IndexedPropertySetterCallback setter =
3019         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
3020     LOG(isolate,
3021         ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
3022     result = args.Call(setter, index, v8::Utils::ToLocal(value));
3023   } else {
3024     Handle<Name> name = it->name();
3025
3026     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
3027       return MaybeHandle<Object>();
3028     }
3029
3030     v8::GenericNamedPropertySetterCallback setter =
3031         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3032             interceptor->setter());
3033     LOG(it->isolate(),
3034         ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3035     result =
3036         args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3037   }
3038
3039   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3040   if (result.IsEmpty()) return MaybeHandle<Object>();
3041 #ifdef DEBUG
3042   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3043   result_internal->VerifyApiCallResultType();
3044 #endif
3045   return value;
3046 }
3047
3048
3049 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3050                                         Handle<Name> name, Handle<Object> value,
3051                                         LanguageMode language_mode,
3052                                         StoreFromKeyed store_mode) {
3053   LookupIterator it(object, name);
3054   return SetProperty(&it, value, language_mode, store_mode);
3055 }
3056
3057
3058 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
3059                                                 Handle<Object> value,
3060                                                 LanguageMode language_mode,
3061                                                 StoreFromKeyed store_mode,
3062                                                 bool* found) {
3063   // Make sure that the top context does not change when doing callbacks or
3064   // interceptor calls.
3065   AssertNoContextChange ncc(it->isolate());
3066
3067   *found = true;
3068
3069   bool done = false;
3070   for (; it->IsFound(); it->Next()) {
3071     switch (it->state()) {
3072       case LookupIterator::NOT_FOUND:
3073         UNREACHABLE();
3074
3075       case LookupIterator::ACCESS_CHECK:
3076         if (it->HasAccess()) break;
3077         // Check whether it makes sense to reuse the lookup iterator. Here it
3078         // might still call into setters up the prototype chain.
3079         return JSObject::SetPropertyWithFailedAccessCheck(it, value);
3080
3081       case LookupIterator::JSPROXY:
3082         if (it->HolderIsReceiverOrHiddenPrototype()) {
3083           return JSProxy::SetPropertyWithHandler(
3084               it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value,
3085               language_mode);
3086         } else {
3087           // TODO(verwaest): Use the MaybeHandle to indicate result.
3088           bool has_result = false;
3089           MaybeHandle<Object> maybe_result =
3090               JSProxy::SetPropertyViaPrototypesWithHandler(
3091                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(),
3092                   value, language_mode, &has_result);
3093           if (has_result) return maybe_result;
3094           done = true;
3095         }
3096         break;
3097
3098       case LookupIterator::INTERCEPTOR:
3099         if (it->HolderIsReceiverOrHiddenPrototype()) {
3100           MaybeHandle<Object> maybe_result =
3101               JSObject::SetPropertyWithInterceptor(it, value);
3102           if (!maybe_result.is_null()) return maybe_result;
3103           if (it->isolate()->has_pending_exception()) return maybe_result;
3104         } else {
3105           Maybe<PropertyAttributes> maybe_attributes =
3106               JSObject::GetPropertyAttributesWithInterceptor(it);
3107           if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3108           done = maybe_attributes.FromJust() != ABSENT;
3109           if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3110             return WriteToReadOnlyProperty(it, value, language_mode);
3111           }
3112         }
3113         break;
3114
3115       case LookupIterator::ACCESSOR: {
3116         if (it->IsReadOnly()) {
3117           return WriteToReadOnlyProperty(it, value, language_mode);
3118         }
3119         Handle<Object> accessors = it->GetAccessors();
3120         if (accessors->IsAccessorInfo() &&
3121             !it->HolderIsReceiverOrHiddenPrototype() &&
3122             AccessorInfo::cast(*accessors)->is_special_data_property()) {
3123           done = true;
3124           break;
3125         }
3126         return SetPropertyWithAccessor(it, value, language_mode);
3127       }
3128       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3129         // TODO(verwaest): We should throw an exception.
3130         return value;
3131
3132       case LookupIterator::DATA:
3133         if (it->IsReadOnly()) {
3134           return WriteToReadOnlyProperty(it, value, language_mode);
3135         }
3136         if (it->HolderIsReceiverOrHiddenPrototype()) {
3137           return SetDataProperty(it, value);
3138         }
3139         done = true;
3140         break;
3141
3142       case LookupIterator::TRANSITION:
3143         done = true;
3144         break;
3145     }
3146
3147     if (done) break;
3148   }
3149
3150   // If the receiver is the JSGlobalObject, the store was contextual. In case
3151   // the property did not exist yet on the global object itself, we have to
3152   // throw a reference error in strict mode.
3153   if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
3154     THROW_NEW_ERROR(it->isolate(),
3155                     NewReferenceError(MessageTemplate::kNotDefined, it->name()),
3156                     Object);
3157   }
3158
3159   *found = false;
3160   return MaybeHandle<Object>();
3161 }
3162
3163
3164 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3165                                         Handle<Object> value,
3166                                         LanguageMode language_mode,
3167                                         StoreFromKeyed store_mode) {
3168   bool found = false;
3169   MaybeHandle<Object> result =
3170       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3171   if (found) return result;
3172   return AddDataProperty(it, value, NONE, language_mode, store_mode);
3173 }
3174
3175
3176 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3177                                              Handle<Object> value,
3178                                              LanguageMode language_mode,
3179                                              StoreFromKeyed store_mode) {
3180   bool found = false;
3181   MaybeHandle<Object> result =
3182       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3183   if (found) return result;
3184
3185   if (!it->GetReceiver()->IsJSReceiver()) {
3186     return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3187                                    it->GetName(), value, language_mode);
3188   }
3189
3190   LookupIterator::Configuration c = LookupIterator::OWN;
3191   LookupIterator own_lookup =
3192       it->IsElement()
3193           ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
3194           : LookupIterator(it->GetReceiver(), it->name(), c);
3195
3196   for (; own_lookup.IsFound(); own_lookup.Next()) {
3197     switch (own_lookup.state()) {
3198       case LookupIterator::ACCESS_CHECK:
3199         if (!own_lookup.HasAccess()) {
3200           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value);
3201         }
3202         break;
3203
3204       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3205         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3206                                                value, language_mode);
3207
3208       case LookupIterator::DATA: {
3209         PropertyDetails details = own_lookup.property_details();
3210         if (details.IsConfigurable() || !details.IsReadOnly()) {
3211           return JSObject::DefineOwnPropertyIgnoreAttributes(
3212               &own_lookup, value, details.attributes());
3213         }
3214         return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3215       }
3216
3217       case LookupIterator::ACCESSOR: {
3218         PropertyDetails details = own_lookup.property_details();
3219         if (details.IsConfigurable()) {
3220           return JSObject::DefineOwnPropertyIgnoreAttributes(
3221               &own_lookup, value, details.attributes());
3222         }
3223
3224         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3225                                                value, language_mode);
3226       }
3227
3228       case LookupIterator::INTERCEPTOR:
3229       case LookupIterator::JSPROXY: {
3230         bool found = false;
3231         MaybeHandle<Object> result = SetPropertyInternal(
3232             &own_lookup, value, language_mode, store_mode, &found);
3233         if (found) return result;
3234         break;
3235       }
3236
3237       case LookupIterator::NOT_FOUND:
3238       case LookupIterator::TRANSITION:
3239         UNREACHABLE();
3240     }
3241   }
3242
3243   return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3244                                    store_mode);
3245 }
3246
3247
3248 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it,
3249                                                LanguageMode language_mode) {
3250   if (is_strong(language_mode)) {
3251     THROW_NEW_ERROR(it->isolate(),
3252                     NewTypeError(MessageTemplate::kStrongPropertyAccess,
3253                                  it->GetName(), it->GetReceiver()),
3254                     Object);
3255   }
3256   return it->isolate()->factory()->undefined_value();
3257 }
3258
3259 MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
3260                                                Handle<Object> receiver,
3261                                                Handle<Object> name,
3262                                                LanguageMode language_mode) {
3263   if (is_strong(language_mode)) {
3264     THROW_NEW_ERROR(
3265         isolate,
3266         NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver),
3267         Object);
3268   }
3269   return isolate->factory()->undefined_value();
3270 }
3271
3272
3273 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3274     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3275   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3276                                  it->GetName(), value, language_mode);
3277 }
3278
3279
3280 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3281     Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3282     Handle<Object> value, LanguageMode language_mode) {
3283   if (is_sloppy(language_mode)) return value;
3284   THROW_NEW_ERROR(
3285       isolate,
3286       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, receiver),
3287       Object);
3288 }
3289
3290
3291 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
3292     Isolate* isolate, Handle<Object> name, Handle<Object> value,
3293     LanguageMode language_mode) {
3294   if (is_sloppy(language_mode)) return value;
3295   THROW_NEW_ERROR(isolate,
3296                   NewTypeError(MessageTemplate::kRedefineDisallowed, name),
3297                   Object);
3298 }
3299
3300
3301 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3302                                             Handle<Object> value) {
3303   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3304   // have own properties.
3305   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3306
3307   // Store on the holder which may be hidden behind the receiver.
3308   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3309
3310   // Old value for the observation change record.
3311   // Fetch before transforming the object since the encoding may become
3312   // incompatible with what's cached in |it|.
3313   bool is_observed = receiver->map()->is_observed() &&
3314                      (it->IsElement() ||
3315                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
3316   MaybeHandle<Object> maybe_old;
3317   if (is_observed) maybe_old = it->GetDataValue();
3318
3319   Handle<Object> to_assign = value;
3320   // Convert the incoming value to a number for storing into typed arrays.
3321   if (it->IsElement() && (receiver->HasExternalArrayElements() ||
3322                           receiver->HasFixedTypedArrayElements())) {
3323     if (!value->IsNumber() && !value->IsUndefined()) {
3324       ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
3325                                  Execution::ToNumber(it->isolate(), value),
3326                                  Object);
3327       // ToNumber above might modify the receiver, causing the cached
3328       // holder_map to mismatch the actual holder->map() after this point.
3329       // Reload the map to be in consistent state. Other cached state cannot
3330       // have been invalidated since typed array elements cannot be reconfigured
3331       // in any way.
3332       it->ReloadHolderMap();
3333     }
3334   }
3335
3336   // Possibly migrate to the most up-to-date map that will be able to store
3337   // |value| under it->name().
3338   it->PrepareForDataProperty(to_assign);
3339
3340   // Write the property value.
3341   it->WriteDataValue(to_assign);
3342
3343   // Send the change record if there are observers.
3344   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3345     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3346                                            receiver, "update", it->GetName(),
3347                                            maybe_old.ToHandleChecked()),
3348                         Object);
3349   }
3350
3351   return value;
3352 }
3353
3354
3355 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
3356     Handle<JSArray> object) {
3357   Isolate* isolate = object->GetIsolate();
3358   HandleScope scope(isolate);
3359   Handle<Object> args[] = {object};
3360
3361   return Execution::Call(
3362       isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
3363       isolate->factory()->undefined_value(), arraysize(args), args);
3364 }
3365
3366
3367 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
3368     Handle<JSArray> object) {
3369   Isolate* isolate = object->GetIsolate();
3370   HandleScope scope(isolate);
3371   Handle<Object> args[] = {object};
3372
3373   return Execution::Call(
3374       isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
3375       isolate->factory()->undefined_value(), arraysize(args), args);
3376 }
3377
3378
3379 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
3380     Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
3381     uint32_t add_count) {
3382   Isolate* isolate = object->GetIsolate();
3383   HandleScope scope(isolate);
3384   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
3385   Handle<Object> add_count_object =
3386       isolate->factory()->NewNumberFromUint(add_count);
3387
3388   Handle<Object> args[] = {object, index_object, deleted, add_count_object};
3389
3390   return Execution::Call(
3391       isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
3392       isolate->factory()->undefined_value(), arraysize(args), args);
3393 }
3394
3395
3396 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3397                                             Handle<Object> value,
3398                                             PropertyAttributes attributes,
3399                                             LanguageMode language_mode,
3400                                             StoreFromKeyed store_mode) {
3401   DCHECK(!it->GetReceiver()->IsJSProxy());
3402   if (!it->GetReceiver()->IsJSObject()) {
3403     // TODO(verwaest): Throw a TypeError with a more specific message.
3404     return WriteToReadOnlyProperty(it, value, language_mode);
3405   }
3406
3407   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
3408
3409   Handle<JSObject> receiver = it->GetStoreTarget();
3410
3411   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3412   // instead. If the prototype is Null, the proxy is detached.
3413   if (receiver->IsJSGlobalProxy()) return value;
3414
3415   Isolate* isolate = it->isolate();
3416
3417   if (!receiver->map()->is_extensible() &&
3418       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
3419     if (is_sloppy(language_mode)) return value;
3420     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible,
3421                                           it->GetName()),
3422                     Object);
3423   }
3424
3425   if (it->IsElement()) {
3426     if (receiver->IsJSArray()) {
3427       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
3428       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
3429         if (is_sloppy(language_mode)) return value;
3430         return JSArray::ReadOnlyLengthError(array);
3431       }
3432
3433       if (FLAG_trace_external_array_abuse &&
3434           (array->HasExternalArrayElements() ||
3435            array->HasFixedTypedArrayElements())) {
3436         CheckArrayAbuse(array, "typed elements write", it->index(), true);
3437       }
3438
3439       if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
3440           !array->HasFixedTypedArrayElements()) {
3441         CheckArrayAbuse(array, "elements write", it->index(), false);
3442       }
3443     }
3444
3445     MaybeHandle<Object> result =
3446         JSObject::AddDataElement(receiver, it->index(), value, attributes);
3447     JSObject::ValidateElements(receiver);
3448     return result;
3449   } else {
3450     // Migrate to the most up-to-date map that will be able to store |value|
3451     // under it->name() with |attributes|.
3452     it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3453     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3454     it->ApplyTransitionToDataProperty();
3455
3456     // TODO(verwaest): Encapsulate dictionary handling better.
3457     if (receiver->map()->is_dictionary_map()) {
3458       // TODO(verwaest): Probably should ensure this is done beforehand.
3459       it->InternalizeName();
3460       // TODO(dcarney): just populate TransitionPropertyCell here?
3461       JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3462     } else {
3463       // Write the property value.
3464       it->WriteDataValue(value);
3465     }
3466
3467     // Send the change record if there are observers.
3468     if (receiver->map()->is_observed() &&
3469         !isolate->IsInternallyUsedPropertyName(it->name())) {
3470       RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
3471                                        receiver, "add", it->name(),
3472                                        it->factory()->the_hole_value()),
3473                           Object);
3474     }
3475   }
3476
3477   return value;
3478 }
3479
3480
3481 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3482   // Only supports adding slack to owned descriptors.
3483   DCHECK(map->owns_descriptors());
3484
3485   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3486   int old_size = map->NumberOfOwnDescriptors();
3487   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3488
3489   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3490       descriptors, old_size, slack);
3491
3492   DisallowHeapAllocation no_allocation;
3493   // The descriptors are still the same, so keep the layout descriptor.
3494   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
3495
3496   if (old_size == 0) {
3497     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3498     return;
3499   }
3500
3501   // If the source descriptors had an enum cache we copy it. This ensures
3502   // that the maps to which we push the new descriptor array back can rely
3503   // on a cache always being available once it is set. If the map has more
3504   // enumerated descriptors than available in the original cache, the cache
3505   // will be lazily replaced by the extended cache when needed.
3506   if (descriptors->HasEnumCache()) {
3507     new_descriptors->CopyEnumCacheFrom(*descriptors);
3508   }
3509
3510   // Replace descriptors by new_descriptors in all maps that share it.
3511   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3512
3513   Map* walk_map;
3514   for (Object* current = map->GetBackPointer();
3515        !current->IsUndefined();
3516        current = walk_map->GetBackPointer()) {
3517     walk_map = Map::cast(current);
3518     if (walk_map->instance_descriptors() != *descriptors) break;
3519     walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3520   }
3521
3522   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3523 }
3524
3525
3526 template<class T>
3527 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3528                                  Handle<typename T::Array> array,
3529                                  int valid_descriptors) {
3530   int nof_callbacks = callbacks->length();
3531
3532   Isolate* isolate = array->GetIsolate();
3533   // Ensure the keys are unique names before writing them into the
3534   // instance descriptor. Since it may cause a GC, it has to be done before we
3535   // temporarily put the heap in an invalid state while appending descriptors.
3536   for (int i = 0; i < nof_callbacks; ++i) {
3537     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3538     if (entry->name()->IsUniqueName()) continue;
3539     Handle<String> key =
3540         isolate->factory()->InternalizeString(
3541             Handle<String>(String::cast(entry->name())));
3542     entry->set_name(*key);
3543   }
3544
3545   // Fill in new callback descriptors.  Process the callbacks from
3546   // back to front so that the last callback with a given name takes
3547   // precedence over previously added callbacks with that name.
3548   for (int i = nof_callbacks - 1; i >= 0; i--) {
3549     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3550     Handle<Name> key(Name::cast(entry->name()));
3551     // Check if a descriptor with this name already exists before writing.
3552     if (!T::Contains(key, entry, valid_descriptors, array)) {
3553       T::Insert(key, entry, valid_descriptors, array);
3554       valid_descriptors++;
3555     }
3556   }
3557
3558   return valid_descriptors;
3559 }
3560
3561 struct DescriptorArrayAppender {
3562   typedef DescriptorArray Array;
3563   static bool Contains(Handle<Name> key,
3564                        Handle<AccessorInfo> entry,
3565                        int valid_descriptors,
3566                        Handle<DescriptorArray> array) {
3567     DisallowHeapAllocation no_gc;
3568     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3569   }
3570   static void Insert(Handle<Name> key,
3571                      Handle<AccessorInfo> entry,
3572                      int valid_descriptors,
3573                      Handle<DescriptorArray> array) {
3574     DisallowHeapAllocation no_gc;
3575     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
3576     array->Append(&desc);
3577   }
3578 };
3579
3580
3581 struct FixedArrayAppender {
3582   typedef FixedArray Array;
3583   static bool Contains(Handle<Name> key,
3584                        Handle<AccessorInfo> entry,
3585                        int valid_descriptors,
3586                        Handle<FixedArray> array) {
3587     for (int i = 0; i < valid_descriptors; i++) {
3588       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3589     }
3590     return false;
3591   }
3592   static void Insert(Handle<Name> key,
3593                      Handle<AccessorInfo> entry,
3594                      int valid_descriptors,
3595                      Handle<FixedArray> array) {
3596     DisallowHeapAllocation no_gc;
3597     array->set(valid_descriptors, *entry);
3598   }
3599 };
3600
3601
3602 void Map::AppendCallbackDescriptors(Handle<Map> map,
3603                                     Handle<Object> descriptors) {
3604   int nof = map->NumberOfOwnDescriptors();
3605   Handle<DescriptorArray> array(map->instance_descriptors());
3606   NeanderArray callbacks(descriptors);
3607   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3608   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3609   map->SetNumberOfOwnDescriptors(nof);
3610 }
3611
3612
3613 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3614                                Handle<FixedArray> array,
3615                                int valid_descriptors) {
3616   NeanderArray callbacks(descriptors);
3617   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3618   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3619                                                    array,
3620                                                    valid_descriptors);
3621 }
3622
3623
3624 static bool ContainsMap(MapHandleList* maps, Map* map) {
3625   DCHECK_NOT_NULL(map);
3626   for (int i = 0; i < maps->length(); ++i) {
3627     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
3628   }
3629   return false;
3630 }
3631
3632
3633 Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
3634                                      MapHandleList* candidates) {
3635   ElementsKind kind = map->elements_kind();
3636   bool packed = IsFastPackedElementsKind(kind);
3637
3638   Map* transition = nullptr;
3639   if (IsTransitionableFastElementsKind(kind)) {
3640     for (Map* current = map->ElementsTransitionMap();
3641          current != nullptr && current->has_fast_elements();
3642          current = current->ElementsTransitionMap()) {
3643       if (ContainsMap(candidates, current) &&
3644           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
3645         transition = current;
3646         packed = packed && IsFastPackedElementsKind(current->elements_kind());
3647       }
3648     }
3649   }
3650   return transition == nullptr ? Handle<Map>() : handle(transition);
3651 }
3652
3653
3654 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3655   Map* current_map = map;
3656
3657   ElementsKind kind = map->elements_kind();
3658   while (kind != to_kind) {
3659     Map* next_map = current_map->ElementsTransitionMap();
3660     if (next_map == nullptr) return current_map;
3661     kind = next_map->elements_kind();
3662     current_map = next_map;
3663   }
3664
3665   DCHECK_EQ(to_kind, current_map->elements_kind());
3666   return current_map;
3667 }
3668
3669
3670 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3671   Map* to_map = FindClosestElementsTransition(this, to_kind);
3672   if (to_map->elements_kind() == to_kind) return to_map;
3673   return nullptr;
3674 }
3675
3676
3677 bool Map::IsMapInArrayPrototypeChain() {
3678   Isolate* isolate = GetIsolate();
3679   if (isolate->initial_array_prototype()->map() == this) {
3680     return true;
3681   }
3682
3683   if (isolate->initial_object_prototype()->map() == this) {
3684     return true;
3685   }
3686
3687   return false;
3688 }
3689
3690
3691 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
3692   Isolate* isolate = map->GetIsolate();
3693   if (map->weak_cell_cache()->IsWeakCell()) {
3694     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
3695   }
3696   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
3697   map->set_weak_cell_cache(*weak_cell);
3698   return weak_cell;
3699 }
3700
3701
3702 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3703                                                  ElementsKind to_kind) {
3704   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3705
3706   Handle<Map> current_map = map;
3707
3708   ElementsKind kind = map->elements_kind();
3709   TransitionFlag flag;
3710   if (map->is_prototype_map()) {
3711     flag = OMIT_TRANSITION;
3712   } else {
3713     flag = INSERT_TRANSITION;
3714     if (IsFastElementsKind(kind)) {
3715       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3716         kind = GetNextTransitionElementsKind(kind);
3717         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
3718       }
3719     }
3720   }
3721
3722   // In case we are exiting the fast elements kind system, just add the map in
3723   // the end.
3724   if (kind != to_kind) {
3725     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
3726   }
3727
3728   DCHECK(current_map->elements_kind() == to_kind);
3729   return current_map;
3730 }
3731
3732
3733 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3734                                       ElementsKind to_kind) {
3735   ElementsKind from_kind = map->elements_kind();
3736   if (from_kind == to_kind) return map;
3737
3738   Isolate* isolate = map->GetIsolate();
3739   Context* native_context = isolate->context()->native_context();
3740   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
3741     if (*map == native_context->fast_aliased_arguments_map()) {
3742       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3743       return handle(native_context->slow_aliased_arguments_map());
3744     }
3745   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
3746     if (*map == native_context->slow_aliased_arguments_map()) {
3747       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3748       return handle(native_context->fast_aliased_arguments_map());
3749     }
3750   } else {
3751     Object* maybe_array_maps = map->is_strong()
3752                                    ? native_context->js_array_strong_maps()
3753                                    : native_context->js_array_maps();
3754     if (maybe_array_maps->IsFixedArray()) {
3755       DisallowHeapAllocation no_gc;
3756       FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3757       if (array_maps->get(from_kind) == *map) {
3758         Object* maybe_transitioned_map = array_maps->get(to_kind);
3759         if (maybe_transitioned_map->IsMap()) {
3760           return handle(Map::cast(maybe_transitioned_map));
3761         }
3762       }
3763     }
3764   }
3765
3766   DCHECK(!map->IsUndefined());
3767   bool allow_store_transition = IsTransitionElementsKind(from_kind);
3768   // Only store fast element maps in ascending generality.
3769   if (IsFastElementsKind(to_kind)) {
3770     allow_store_transition =
3771         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
3772         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3773   }
3774
3775   if (!allow_store_transition) {
3776     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3777   }
3778
3779   return Map::AsElementsKind(map, to_kind);
3780 }
3781
3782
3783 // static
3784 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3785   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3786
3787   if (closest_map->elements_kind() == kind) {
3788     return closest_map;
3789   }
3790
3791   return AddMissingElementsTransitions(closest_map, kind);
3792 }
3793
3794
3795 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3796                                                ElementsKind to_kind) {
3797   Handle<Map> map(object->map());
3798   return Map::TransitionElementsTo(map, to_kind);
3799 }
3800
3801
3802 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3803                                             Handle<Name> name) {
3804   Isolate* isolate = proxy->GetIsolate();
3805
3806   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3807   if (name->IsSymbol()) return Just(false);
3808
3809   Handle<Object> args[] = { name };
3810   Handle<Object> result;
3811   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3812       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3813                                 arraysize(args), args),
3814       Nothing<bool>());
3815
3816   return Just(result->BooleanValue());
3817 }
3818
3819
3820 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3821     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3822     Handle<Object> value, LanguageMode language_mode) {
3823   Isolate* isolate = proxy->GetIsolate();
3824
3825   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3826   if (name->IsSymbol()) return value;
3827
3828   Handle<Object> args[] = { receiver, name, value };
3829   RETURN_ON_EXCEPTION(
3830       isolate,
3831       CallTrap(proxy,
3832                "set",
3833                isolate->derived_set_trap(),
3834                arraysize(args),
3835                args),
3836       Object);
3837
3838   return value;
3839 }
3840
3841
3842 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3843     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3844     Handle<Object> value, LanguageMode language_mode, bool* done) {
3845   Isolate* isolate = proxy->GetIsolate();
3846   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3847
3848   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3849   if (name->IsSymbol()) {
3850     *done = false;
3851     return isolate->factory()->the_hole_value();
3852   }
3853
3854   *done = true;  // except where redefined...
3855   Handle<Object> args[] = { name };
3856   Handle<Object> result;
3857   ASSIGN_RETURN_ON_EXCEPTION(
3858       isolate, result,
3859       CallTrap(proxy,
3860                "getPropertyDescriptor",
3861                Handle<Object>(),
3862                arraysize(args),
3863                args),
3864       Object);
3865
3866   if (result->IsUndefined()) {
3867     *done = false;
3868     return isolate->factory()->the_hole_value();
3869   }
3870
3871   // Emulate [[GetProperty]] semantics for proxies.
3872   Handle<Object> argv[] = { result };
3873   Handle<Object> desc;
3874   ASSIGN_RETURN_ON_EXCEPTION(
3875       isolate, desc,
3876       Execution::Call(isolate,
3877                       isolate->to_complete_property_descriptor(),
3878                       result,
3879                       arraysize(argv),
3880                       argv),
3881       Object);
3882
3883   // [[GetProperty]] requires to check that all properties are configurable.
3884   Handle<String> configurable_name =
3885       isolate->factory()->InternalizeOneByteString(
3886           STATIC_CHAR_VECTOR("configurable_"));
3887   Handle<Object> configurable =
3888       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3889   DCHECK(configurable->IsBoolean());
3890   if (configurable->IsFalse()) {
3891     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3892         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3893     THROW_NEW_ERROR(isolate,
3894                     NewTypeError(MessageTemplate::kProxyPropNotConfigurable,
3895                                  handler, name, trap),
3896                     Object);
3897   }
3898   DCHECK(configurable->IsTrue());
3899
3900   // Check for DataDescriptor.
3901   Handle<String> hasWritable_name =
3902       isolate->factory()->InternalizeOneByteString(
3903           STATIC_CHAR_VECTOR("hasWritable_"));
3904   Handle<Object> hasWritable =
3905       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3906   DCHECK(hasWritable->IsBoolean());
3907   if (hasWritable->IsTrue()) {
3908     Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3909         STATIC_CHAR_VECTOR("writable_"));
3910     Handle<Object> writable =
3911         Object::GetProperty(desc, writable_name).ToHandleChecked();
3912     DCHECK(writable->IsBoolean());
3913     *done = writable->IsFalse();
3914     if (!*done) return isolate->factory()->the_hole_value();
3915     return WriteToReadOnlyProperty(isolate, receiver, name, value,
3916                                    language_mode);
3917   }
3918
3919   // We have an AccessorDescriptor.
3920   Handle<String> set_name =
3921       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3922   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3923   if (!setter->IsUndefined()) {
3924     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3925     return SetPropertyWithDefinedSetter(
3926         receiver, Handle<JSReceiver>::cast(setter), value);
3927   }
3928
3929   if (is_sloppy(language_mode)) return value;
3930   THROW_NEW_ERROR(
3931       isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy),
3932       Object);
3933 }
3934
3935
3936 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3937     Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) {
3938   Isolate* isolate = proxy->GetIsolate();
3939
3940   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3941   if (name->IsSymbol()) return isolate->factory()->false_value();
3942
3943   Handle<Object> args[] = { name };
3944   Handle<Object> result;
3945   ASSIGN_RETURN_ON_EXCEPTION(
3946       isolate, result,
3947       CallTrap(proxy,
3948                "delete",
3949                Handle<Object>(),
3950                arraysize(args),
3951                args),
3952       Object);
3953
3954   bool result_bool = result->BooleanValue();
3955   if (is_strict(language_mode) && !result_bool) {
3956     Handle<Object> handler(proxy->handler(), isolate);
3957     THROW_NEW_ERROR(
3958         isolate,
3959         NewTypeError(MessageTemplate::kProxyHandlerDeleteFailed, handler),
3960         Object);
3961   }
3962   return isolate->factory()->ToBoolean(result_bool);
3963 }
3964
3965
3966 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3967     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3968   Isolate* isolate = proxy->GetIsolate();
3969   HandleScope scope(isolate);
3970
3971   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3972   if (name->IsSymbol()) return Just(ABSENT);
3973
3974   Handle<Object> args[] = { name };
3975   Handle<Object> result;
3976   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3977       isolate, result, proxy->CallTrap(proxy, "getPropertyDescriptor",
3978                                        Handle<Object>(), arraysize(args), args),
3979       Nothing<PropertyAttributes>());
3980
3981   if (result->IsUndefined()) return Just(ABSENT);
3982
3983   Handle<Object> argv[] = { result };
3984   Handle<Object> desc;
3985   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3986       isolate, desc,
3987       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3988                       result, arraysize(argv), argv),
3989       Nothing<PropertyAttributes>());
3990
3991   // Convert result to PropertyAttributes.
3992   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3993       STATIC_CHAR_VECTOR("enumerable_"));
3994   Handle<Object> enumerable;
3995   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3996                                    Object::GetProperty(desc, enum_n),
3997                                    Nothing<PropertyAttributes>());
3998   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3999       STATIC_CHAR_VECTOR("configurable_"));
4000   Handle<Object> configurable;
4001   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
4002                                    Object::GetProperty(desc, conf_n),
4003                                    Nothing<PropertyAttributes>());
4004   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
4005       STATIC_CHAR_VECTOR("writable_"));
4006   Handle<Object> writable;
4007   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
4008                                    Object::GetProperty(desc, writ_n),
4009                                    Nothing<PropertyAttributes>());
4010   if (!writable->BooleanValue()) {
4011     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
4012         STATIC_CHAR_VECTOR("set_"));
4013     Handle<Object> setter;
4014     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
4015                                      Object::GetProperty(desc, set_n),
4016                                      Nothing<PropertyAttributes>());
4017     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
4018   }
4019
4020   if (configurable->IsFalse()) {
4021     Handle<Object> handler(proxy->handler(), isolate);
4022     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
4023         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
4024     Handle<Object> error = isolate->factory()->NewTypeError(
4025         MessageTemplate::kProxyPropNotConfigurable, handler, name, trap);
4026     isolate->Throw(*error);
4027     return Nothing<PropertyAttributes>();
4028   }
4029
4030   int attributes = NONE;
4031   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
4032   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
4033   if (!writable->BooleanValue()) attributes |= READ_ONLY;
4034   return Just(static_cast<PropertyAttributes>(attributes));
4035 }
4036
4037
4038 void JSProxy::Fix(Handle<JSProxy> proxy) {
4039   Isolate* isolate = proxy->GetIsolate();
4040
4041   // Save identity hash.
4042   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4043
4044   if (proxy->IsJSFunctionProxy()) {
4045     isolate->factory()->BecomeJSFunction(proxy);
4046     // Code will be set on the JavaScript side.
4047   } else {
4048     isolate->factory()->BecomeJSObject(proxy);
4049   }
4050   DCHECK(proxy->IsJSObject());
4051
4052   // Inherit identity, if it was present.
4053   if (hash->IsSmi()) {
4054     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
4055                               Handle<Smi>::cast(hash));
4056   }
4057 }
4058
4059
4060 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
4061                                       const char* name,
4062                                       Handle<Object> derived,
4063                                       int argc,
4064                                       Handle<Object> argv[]) {
4065   Isolate* isolate = proxy->GetIsolate();
4066   Handle<Object> handler(proxy->handler(), isolate);
4067
4068   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
4069   Handle<Object> trap;
4070   ASSIGN_RETURN_ON_EXCEPTION(
4071       isolate, trap,
4072       Object::GetPropertyOrElement(handler, trap_name),
4073       Object);
4074
4075   if (trap->IsUndefined()) {
4076     if (derived.is_null()) {
4077       THROW_NEW_ERROR(isolate,
4078                       NewTypeError(MessageTemplate::kProxyHandlerTrapMissing,
4079                                    handler, trap_name),
4080                       Object);
4081     }
4082     trap = Handle<Object>(derived);
4083   }
4084
4085   return Execution::Call(isolate, trap, handler, argc, argv);
4086 }
4087
4088
4089 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
4090   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
4091   ElementsKind obj_kind = object->map()->elements_kind();
4092   ElementsKind map_kind = map->elements_kind();
4093   if (map_kind != obj_kind) {
4094     ElementsKind to_kind = map_kind;
4095     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
4096         IsDictionaryElementsKind(obj_kind)) {
4097       to_kind = obj_kind;
4098     }
4099     if (IsDictionaryElementsKind(to_kind)) {
4100       NormalizeElements(object);
4101     } else {
4102       TransitionElementsKind(object, to_kind);
4103     }
4104     map = Map::AsElementsKind(map, to_kind);
4105   }
4106   JSObject::MigrateToMap(object, map);
4107 }
4108
4109
4110 void JSObject::MigrateInstance(Handle<JSObject> object) {
4111   Handle<Map> original_map(object->map());
4112   Handle<Map> map = Map::Update(original_map);
4113   map->set_migration_target(true);
4114   MigrateToMap(object, map);
4115   if (FLAG_trace_migration) {
4116     object->PrintInstanceMigration(stdout, *original_map, *map);
4117   }
4118 }
4119
4120
4121 // static
4122 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
4123   Isolate* isolate = object->GetIsolate();
4124   DisallowDeoptimization no_deoptimization(isolate);
4125   Handle<Map> original_map(object->map(), isolate);
4126   Handle<Map> new_map;
4127   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
4128     return false;
4129   }
4130   JSObject::MigrateToMap(object, new_map);
4131   if (FLAG_trace_migration) {
4132     object->PrintInstanceMigration(stdout, *original_map, object->map());
4133   }
4134   return true;
4135 }
4136
4137
4138 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4139                            Handle<Object> value,
4140                            PropertyAttributes attributes) {
4141   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4142   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
4143 #ifdef DEBUG
4144   uint32_t index;
4145   DCHECK(!object->IsJSProxy());
4146   DCHECK(!name->AsArrayIndex(&index));
4147   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4148   DCHECK(maybe.IsJust());
4149   DCHECK(!it.IsFound());
4150   DCHECK(object->map()->is_extensible() ||
4151          it.isolate()->IsInternallyUsedPropertyName(name));
4152 #endif
4153   AddDataProperty(&it, value, attributes, STRICT,
4154                   CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4155 }
4156
4157
4158 // static
4159 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
4160   Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr);
4161   info->set_setter(*object);
4162 }
4163
4164
4165 // Reconfigures a property to a data property with attributes, even if it is not
4166 // reconfigurable.
4167 // Requires a LookupIterator that does not look at the prototype chain beyond
4168 // hidden prototypes.
4169 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
4170     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
4171     ExecutableAccessorInfoHandling handling) {
4172   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
4173   bool is_observed = object->map()->is_observed() &&
4174                      (it->IsElement() ||
4175                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4176
4177   for (; it->IsFound(); it->Next()) {
4178     switch (it->state()) {
4179       case LookupIterator::JSPROXY:
4180       case LookupIterator::NOT_FOUND:
4181       case LookupIterator::TRANSITION:
4182         UNREACHABLE();
4183
4184       case LookupIterator::ACCESS_CHECK:
4185         if (!it->HasAccess()) {
4186           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
4187           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
4188           return value;
4189         }
4190         break;
4191
4192       // If there's an interceptor, try to store the property with the
4193       // interceptor.
4194       // In case of success, the attributes will have been reset to the default
4195       // attributes of the interceptor, rather than the incoming attributes.
4196       //
4197       // TODO(verwaest): JSProxy afterwards verify the attributes that the
4198       // JSProxy claims it has, and verifies that they are compatible. If not,
4199       // they throw. Here we should do the same.
4200       case LookupIterator::INTERCEPTOR:
4201         if (handling == DONT_FORCE_FIELD) {
4202           MaybeHandle<Object> maybe_result =
4203               JSObject::SetPropertyWithInterceptor(it, value);
4204           if (!maybe_result.is_null()) return maybe_result;
4205           if (it->isolate()->has_pending_exception()) return maybe_result;
4206         }
4207         break;
4208
4209       case LookupIterator::ACCESSOR: {
4210         Handle<Object> accessors = it->GetAccessors();
4211
4212         // Special handling for ExecutableAccessorInfo, which behaves like a
4213         // data property.
4214         if (accessors->IsExecutableAccessorInfo() &&
4215             handling == DONT_FORCE_FIELD) {
4216           PropertyDetails details = it->property_details();
4217           // Ensure the context isn't changed after calling into accessors.
4218           AssertNoContextChange ncc(it->isolate());
4219
4220           Handle<Object> result;
4221           ASSIGN_RETURN_ON_EXCEPTION(
4222               it->isolate(), result,
4223               JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4224           DCHECK(result->SameValue(*value));
4225
4226           if (details.attributes() == attributes) return value;
4227
4228           // Reconfigure the accessor if attributes mismatch.
4229           Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4230               it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4231           new_data->set_property_attributes(attributes);
4232           // By clearing the setter we don't have to introduce a lookup to
4233           // the setter, simply make it unavailable to reflect the
4234           // attributes.
4235           if (attributes & READ_ONLY) {
4236             ExecutableAccessorInfo::ClearSetter(new_data);
4237           }
4238
4239           it->TransitionToAccessorPair(new_data, attributes);
4240         } else {
4241           it->ReconfigureDataProperty(value, attributes);
4242           it->WriteDataValue(value);
4243         }
4244
4245         if (is_observed) {
4246           RETURN_ON_EXCEPTION(
4247               it->isolate(),
4248               EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4249                                   it->factory()->the_hole_value()),
4250               Object);
4251         }
4252
4253         return value;
4254       }
4255       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4256         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4257                                                value, STRICT);
4258
4259       case LookupIterator::DATA: {
4260         PropertyDetails details = it->property_details();
4261         Handle<Object> old_value = it->factory()->the_hole_value();
4262         // Regular property update if the attributes match.
4263         if (details.attributes() == attributes) {
4264           return SetDataProperty(it, value);
4265         }
4266
4267         // Special case: properties of typed arrays cannot be reconfigured to
4268         // non-writable nor to non-enumerable.
4269         if (it->IsElement() && (object->HasExternalArrayElements() ||
4270                                 object->HasFixedTypedArrayElements())) {
4271           return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4272                                                  value, STRICT);
4273         }
4274
4275         // Reconfigure the data property if the attributes mismatch.
4276         if (is_observed) old_value = it->GetDataValue();
4277
4278         it->ReconfigureDataProperty(value, attributes);
4279         it->WriteDataValue(value);
4280
4281         if (is_observed) {
4282           if (old_value->SameValue(*value)) {
4283             old_value = it->factory()->the_hole_value();
4284           }
4285           RETURN_ON_EXCEPTION(it->isolate(),
4286                               EnqueueChangeRecord(object, "reconfigure",
4287                                                   it->GetName(), old_value),
4288                               Object);
4289         }
4290         return value;
4291       }
4292     }
4293   }
4294
4295   return AddDataProperty(it, value, attributes, STRICT,
4296                          CERTAINLY_NOT_STORE_FROM_KEYED);
4297 }
4298
4299
4300 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4301     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4302     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4303   DCHECK(!value->IsTheHole());
4304   LookupIterator it(object, name, LookupIterator::OWN);
4305   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4306 }
4307
4308
4309 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
4310     Handle<JSObject> object, uint32_t index, Handle<Object> value,
4311     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4312   Isolate* isolate = object->GetIsolate();
4313   LookupIterator it(isolate, object, index, LookupIterator::OWN);
4314   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4315 }
4316
4317
4318 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
4319     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4320     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4321   Isolate* isolate = object->GetIsolate();
4322   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
4323                                                         LookupIterator::OWN);
4324   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4325 }
4326
4327
4328 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
4329                                          Handle<Object> value) {
4330   DCHECK(it->GetReceiver()->IsJSObject());
4331   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it);
4332   if (maybe.IsNothing()) return Nothing<bool>();
4333
4334   if (it->IsFound()) {
4335     if (!it->IsConfigurable()) return Just(false);
4336   } else {
4337     if (!JSObject::cast(*it->GetReceiver())->IsExtensible()) return Just(false);
4338   }
4339
4340   RETURN_ON_EXCEPTION_VALUE(
4341       it->isolate(),
4342       DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD),
4343       Nothing<bool>());
4344
4345   return Just(true);
4346 }
4347
4348
4349 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4350     LookupIterator* it) {
4351   Isolate* isolate = it->isolate();
4352   // Make sure that the top context does not change when doing
4353   // callbacks or interceptor calls.
4354   AssertNoContextChange ncc(isolate);
4355   HandleScope scope(isolate);
4356
4357   Handle<JSObject> holder = it->GetHolder<JSObject>();
4358   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
4359   if (!it->IsElement() && it->name()->IsSymbol() &&
4360       !interceptor->can_intercept_symbols()) {
4361     return Just(ABSENT);
4362   }
4363   PropertyCallbackArguments args(isolate, interceptor->data(),
4364                                  *it->GetReceiver(), *holder);
4365   if (!interceptor->query()->IsUndefined()) {
4366     v8::Local<v8::Integer> result;
4367     if (it->IsElement()) {
4368       uint32_t index = it->index();
4369       v8::IndexedPropertyQueryCallback query =
4370           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4371       LOG(isolate,
4372           ApiIndexedPropertyAccess("interceptor-indexed-has", *holder, index));
4373       result = args.Call(query, index);
4374     } else {
4375       Handle<Name> name = it->name();
4376       v8::GenericNamedPropertyQueryCallback query =
4377           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
4378               interceptor->query());
4379       LOG(isolate,
4380           ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4381       result = args.Call(query, v8::Utils::ToLocal(name));
4382     }
4383     if (!result.IsEmpty()) {
4384       DCHECK(result->IsInt32());
4385       return Just(static_cast<PropertyAttributes>(
4386           result->Int32Value(reinterpret_cast<v8::Isolate*>(isolate)
4387                                  ->GetCurrentContext()).FromJust()));
4388     }
4389   } else if (!interceptor->getter()->IsUndefined()) {
4390     // TODO(verwaest): Use GetPropertyWithInterceptor?
4391     v8::Local<v8::Value> result;
4392     if (it->IsElement()) {
4393       uint32_t index = it->index();
4394       v8::IndexedPropertyGetterCallback getter =
4395           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4396       LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-get-has",
4397                                             *holder, index));
4398       result = args.Call(getter, index);
4399     } else {
4400       Handle<Name> name = it->name();
4401
4402       v8::GenericNamedPropertyGetterCallback getter =
4403           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
4404               interceptor->getter());
4405       LOG(isolate,
4406           ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4407       result = args.Call(getter, v8::Utils::ToLocal(name));
4408     }
4409     if (!result.IsEmpty()) return Just(DONT_ENUM);
4410   }
4411
4412   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
4413   return Just(ABSENT);
4414 }
4415
4416
4417 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4418     LookupIterator* it) {
4419   for (; it->IsFound(); it->Next()) {
4420     switch (it->state()) {
4421       case LookupIterator::NOT_FOUND:
4422       case LookupIterator::TRANSITION:
4423         UNREACHABLE();
4424       case LookupIterator::JSPROXY:
4425         return JSProxy::GetPropertyAttributesWithHandler(
4426             it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
4427       case LookupIterator::INTERCEPTOR: {
4428         Maybe<PropertyAttributes> result =
4429             JSObject::GetPropertyAttributesWithInterceptor(it);
4430         if (!result.IsJust()) return result;
4431         if (result.FromJust() != ABSENT) return result;
4432         break;
4433       }
4434       case LookupIterator::ACCESS_CHECK:
4435         if (it->HasAccess()) break;
4436         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4437       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4438         return Just(ABSENT);
4439       case LookupIterator::ACCESSOR:
4440       case LookupIterator::DATA:
4441         return Just(it->property_details().attributes());
4442     }
4443   }
4444   return Just(ABSENT);
4445 }
4446
4447
4448 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4449   Handle<FixedArray> array(
4450       isolate->factory()->NewFixedArray(kEntries, TENURED));
4451   return Handle<NormalizedMapCache>::cast(array);
4452 }
4453
4454
4455 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4456                                          PropertyNormalizationMode mode) {
4457   DisallowHeapAllocation no_gc;
4458   Object* value = FixedArray::get(GetIndex(fast_map));
4459   if (!value->IsMap() ||
4460       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4461     return MaybeHandle<Map>();
4462   }
4463   return handle(Map::cast(value));
4464 }
4465
4466
4467 void NormalizedMapCache::Set(Handle<Map> fast_map,
4468                              Handle<Map> normalized_map) {
4469   DisallowHeapAllocation no_gc;
4470   DCHECK(normalized_map->is_dictionary_map());
4471   FixedArray::set(GetIndex(fast_map), *normalized_map);
4472 }
4473
4474
4475 void NormalizedMapCache::Clear() {
4476   int entries = length();
4477   for (int i = 0; i != entries; i++) {
4478     set_undefined(i);
4479   }
4480 }
4481
4482
4483 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4484                                     Handle<Name> name,
4485                                     Handle<Code> code) {
4486   Handle<Map> map(object->map());
4487   Map::UpdateCodeCache(map, name, code);
4488 }
4489
4490
4491 void JSObject::NormalizeProperties(Handle<JSObject> object,
4492                                    PropertyNormalizationMode mode,
4493                                    int expected_additional_properties,
4494                                    const char* reason) {
4495   if (!object->HasFastProperties()) return;
4496
4497   Handle<Map> map(object->map());
4498   Handle<Map> new_map = Map::Normalize(map, mode, reason);
4499
4500   MigrateToMap(object, new_map, expected_additional_properties);
4501 }
4502
4503
4504 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4505                                  Handle<Map> new_map,
4506                                  int expected_additional_properties) {
4507   // The global object is always normalized.
4508   DCHECK(!object->IsGlobalObject());
4509   // JSGlobalProxy must never be normalized
4510   DCHECK(!object->IsJSGlobalProxy());
4511
4512   Isolate* isolate = object->GetIsolate();
4513   HandleScope scope(isolate);
4514   Handle<Map> map(object->map());
4515
4516   // Allocate new content.
4517   int real_size = map->NumberOfOwnDescriptors();
4518   int property_count = real_size;
4519   if (expected_additional_properties > 0) {
4520     property_count += expected_additional_properties;
4521   } else {
4522     property_count += 2;  // Make space for two more properties.
4523   }
4524   Handle<NameDictionary> dictionary =
4525       NameDictionary::New(isolate, property_count);
4526
4527   Handle<DescriptorArray> descs(map->instance_descriptors());
4528   for (int i = 0; i < real_size; i++) {
4529     PropertyDetails details = descs->GetDetails(i);
4530     Handle<Name> key(descs->GetKey(i));
4531     switch (details.type()) {
4532       case DATA_CONSTANT: {
4533         Handle<Object> value(descs->GetConstant(i), isolate);
4534         PropertyDetails d(details.attributes(), DATA, i + 1,
4535                           PropertyCellType::kNoCell);
4536         dictionary = NameDictionary::Add(dictionary, key, value, d);
4537         break;
4538       }
4539       case DATA: {
4540         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4541         Handle<Object> value;
4542         if (object->IsUnboxedDoubleField(index)) {
4543           double old_value = object->RawFastDoublePropertyAt(index);
4544           value = isolate->factory()->NewHeapNumber(old_value);
4545         } else {
4546           value = handle(object->RawFastPropertyAt(index), isolate);
4547           if (details.representation().IsDouble()) {
4548             DCHECK(value->IsMutableHeapNumber());
4549             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4550             value = isolate->factory()->NewHeapNumber(old->value());
4551           }
4552         }
4553         PropertyDetails d(details.attributes(), DATA, i + 1,
4554                           PropertyCellType::kNoCell);
4555         dictionary = NameDictionary::Add(dictionary, key, value, d);
4556         break;
4557       }
4558       case ACCESSOR: {
4559         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4560         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
4561         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4562                           PropertyCellType::kNoCell);
4563         dictionary = NameDictionary::Add(dictionary, key, value, d);
4564         break;
4565       }
4566       case ACCESSOR_CONSTANT: {
4567         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4568         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4569                           PropertyCellType::kNoCell);
4570         dictionary = NameDictionary::Add(dictionary, key, value, d);
4571         break;
4572       }
4573     }
4574   }
4575
4576   // Copy the next enumeration index from instance descriptor.
4577   dictionary->SetNextEnumerationIndex(real_size + 1);
4578
4579   // From here on we cannot fail and we shouldn't GC anymore.
4580   DisallowHeapAllocation no_allocation;
4581
4582   // Resize the object in the heap if necessary.
4583   int new_instance_size = new_map->instance_size();
4584   int instance_size_delta = map->instance_size() - new_instance_size;
4585   DCHECK(instance_size_delta >= 0);
4586
4587   if (instance_size_delta > 0) {
4588     Heap* heap = isolate->heap();
4589     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4590                                instance_size_delta);
4591     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4592                           Heap::CONCURRENT_TO_SWEEPER);
4593   }
4594
4595   // We are storing the new map using release store after creating a filler for
4596   // the left-over space to avoid races with the sweeper thread.
4597   object->synchronized_set_map(*new_map);
4598
4599   object->set_properties(*dictionary);
4600
4601   // Ensure that in-object space of slow-mode object does not contain random
4602   // garbage.
4603   int inobject_properties = new_map->inobject_properties();
4604   for (int i = 0; i < inobject_properties; i++) {
4605     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4606     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
4607   }
4608
4609   isolate->counters()->props_to_dictionary()->Increment();
4610
4611 #ifdef DEBUG
4612   if (FLAG_trace_normalization) {
4613     OFStream os(stdout);
4614     os << "Object properties have been normalized:\n";
4615     object->Print(os);
4616   }
4617 #endif
4618 }
4619
4620
4621 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4622                                  int unused_property_fields,
4623                                  const char* reason) {
4624   if (object->HasFastProperties()) return;
4625   DCHECK(!object->IsGlobalObject());
4626   Isolate* isolate = object->GetIsolate();
4627   Factory* factory = isolate->factory();
4628   Handle<NameDictionary> dictionary(object->property_dictionary());
4629
4630   // Make sure we preserve dictionary representation if there are too many
4631   // descriptors.
4632   int number_of_elements = dictionary->NumberOfElements();
4633   if (number_of_elements > kMaxNumberOfDescriptors) return;
4634
4635   Handle<FixedArray> iteration_order;
4636   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4637     iteration_order =
4638         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4639   } else {
4640     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
4641   }
4642
4643   int instance_descriptor_length = iteration_order->length();
4644   int number_of_fields = 0;
4645
4646   // Compute the length of the instance descriptor.
4647   for (int i = 0; i < instance_descriptor_length; i++) {
4648     int index = Smi::cast(iteration_order->get(i))->value();
4649     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
4650
4651     Object* value = dictionary->ValueAt(index);
4652     PropertyType type = dictionary->DetailsAt(index).type();
4653     if (type == DATA && !value->IsJSFunction()) {
4654       number_of_fields += 1;
4655     }
4656   }
4657
4658   int inobject_props = object->map()->inobject_properties();
4659
4660   // Allocate new map.
4661   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4662   new_map->set_dictionary_map(false);
4663
4664   if (object->map()->is_prototype_map()) {
4665     DCHECK(new_map->is_prototype_map());
4666     new_map->set_prototype_info(object->map()->prototype_info());
4667     object->map()->set_prototype_info(Smi::FromInt(0));
4668     if (FLAG_trace_prototype_users) {
4669       PrintF("Moving prototype_info %p from map %p to map %p.\n",
4670              reinterpret_cast<void*>(new_map->prototype_info()),
4671              reinterpret_cast<void*>(object->map()),
4672              reinterpret_cast<void*>(*new_map));
4673     }
4674   }
4675
4676 #if TRACE_MAPS
4677   if (FLAG_trace_maps) {
4678     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
4679            reinterpret_cast<void*>(object->map()),
4680            reinterpret_cast<void*>(*new_map), reason);
4681   }
4682 #endif
4683
4684   if (instance_descriptor_length == 0) {
4685     DisallowHeapAllocation no_gc;
4686     DCHECK_LE(unused_property_fields, inobject_props);
4687     // Transform the object.
4688     new_map->set_unused_property_fields(inobject_props);
4689     object->synchronized_set_map(*new_map);
4690     object->set_properties(isolate->heap()->empty_fixed_array());
4691     // Check that it really works.
4692     DCHECK(object->HasFastProperties());
4693     return;
4694   }
4695
4696   // Allocate the instance descriptor.
4697   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4698       isolate, instance_descriptor_length);
4699
4700   int number_of_allocated_fields =
4701       number_of_fields + unused_property_fields - inobject_props;
4702   if (number_of_allocated_fields < 0) {
4703     // There is enough inobject space for all fields (including unused).
4704     number_of_allocated_fields = 0;
4705     unused_property_fields = inobject_props - number_of_fields;
4706   }
4707
4708   // Allocate the fixed array for the fields.
4709   Handle<FixedArray> fields = factory->NewFixedArray(
4710       number_of_allocated_fields);
4711
4712   // Fill in the instance descriptor and the fields.
4713   int current_offset = 0;
4714   for (int i = 0; i < instance_descriptor_length; i++) {
4715     int index = Smi::cast(iteration_order->get(i))->value();
4716     Object* k = dictionary->KeyAt(index);
4717     DCHECK(dictionary->IsKey(k));
4718
4719     Object* value = dictionary->ValueAt(index);
4720     Handle<Name> key;
4721     if (k->IsSymbol()) {
4722       key = handle(Symbol::cast(k));
4723     } else {
4724       // Ensure the key is a unique name before writing into the
4725       // instance descriptor.
4726       key = factory->InternalizeString(handle(String::cast(k)));
4727     }
4728
4729     PropertyDetails details = dictionary->DetailsAt(index);
4730     int enumeration_index = details.dictionary_index();
4731     PropertyType type = details.type();
4732
4733     if (value->IsJSFunction()) {
4734       DataConstantDescriptor d(key, handle(value, isolate),
4735                                details.attributes());
4736       descriptors->Set(enumeration_index - 1, &d);
4737     } else if (type == DATA) {
4738       if (current_offset < inobject_props) {
4739         object->InObjectPropertyAtPut(current_offset, value,
4740                                       UPDATE_WRITE_BARRIER);
4741       } else {
4742         int offset = current_offset - inobject_props;
4743         fields->set(offset, value);
4744       }
4745       DataDescriptor d(key, current_offset, details.attributes(),
4746                        // TODO(verwaest): value->OptimalRepresentation();
4747                        Representation::Tagged());
4748       current_offset += d.GetDetails().field_width_in_words();
4749       descriptors->Set(enumeration_index - 1, &d);
4750     } else if (type == ACCESSOR_CONSTANT) {
4751       AccessorConstantDescriptor d(key, handle(value, isolate),
4752                                    details.attributes());
4753       descriptors->Set(enumeration_index - 1, &d);
4754     } else {
4755       UNREACHABLE();
4756     }
4757   }
4758   DCHECK(current_offset == number_of_fields);
4759
4760   descriptors->Sort();
4761
4762   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
4763       new_map, descriptors, descriptors->number_of_descriptors());
4764
4765   DisallowHeapAllocation no_gc;
4766   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
4767   new_map->set_unused_property_fields(unused_property_fields);
4768
4769   // Transform the object.
4770   object->synchronized_set_map(*new_map);
4771
4772   object->set_properties(*fields);
4773   DCHECK(object->IsJSObject());
4774
4775   // Check that it really works.
4776   DCHECK(object->HasFastProperties());
4777 }
4778
4779
4780 void JSObject::ResetElements(Handle<JSObject> object) {
4781   Isolate* isolate = object->GetIsolate();
4782   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4783   if (object->map()->has_dictionary_elements()) {
4784     Handle<SeededNumberDictionary> new_elements =
4785         SeededNumberDictionary::New(isolate, 0);
4786     object->set_elements(*new_elements);
4787   } else {
4788     object->set_elements(object->map()->GetInitialElements());
4789   }
4790 }
4791
4792
4793 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4794     Handle<FixedArrayBase> array,
4795     int length,
4796     Handle<SeededNumberDictionary> dictionary) {
4797   Isolate* isolate = array->GetIsolate();
4798   Factory* factory = isolate->factory();
4799   bool has_double_elements = array->IsFixedDoubleArray();
4800   for (int i = 0; i < length; i++) {
4801     Handle<Object> value;
4802     if (has_double_elements) {
4803       Handle<FixedDoubleArray> double_array =
4804           Handle<FixedDoubleArray>::cast(array);
4805       if (double_array->is_the_hole(i)) {
4806         value = factory->the_hole_value();
4807       } else {
4808         value = factory->NewHeapNumber(double_array->get_scalar(i));
4809       }
4810     } else {
4811       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4812     }
4813     if (!value->IsTheHole()) {
4814       PropertyDetails details = PropertyDetails::Empty();
4815       dictionary =
4816           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4817     }
4818   }
4819   return dictionary;
4820 }
4821
4822
4823 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
4824   if (dictionary->requires_slow_elements()) return;
4825   dictionary->set_requires_slow_elements();
4826   // TODO(verwaest): Remove this hack.
4827   if (map()->is_prototype_map()) {
4828     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
4829   }
4830 }
4831
4832
4833 Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
4834     Handle<JSObject> object, Handle<FixedArrayBase> elements) {
4835   DCHECK(!object->HasDictionaryElements());
4836   DCHECK(!object->HasSlowArgumentsElements());
4837   Isolate* isolate = object->GetIsolate();
4838   // Ensure that notifications fire if the array or object prototypes are
4839   // normalizing.
4840   isolate->UpdateArrayProtectorOnNormalizeElements(object);
4841   int length = object->IsJSArray()
4842                    ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4843                    : elements->length();
4844   int used = object->GetFastElementsUsage();
4845   Handle<SeededNumberDictionary> dictionary =
4846       SeededNumberDictionary::New(isolate, used);
4847   return CopyFastElementsToDictionary(elements, length, dictionary);
4848 }
4849
4850
4851 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4852     Handle<JSObject> object) {
4853   DCHECK(!object->HasExternalArrayElements() &&
4854          !object->HasFixedTypedArrayElements());
4855   Isolate* isolate = object->GetIsolate();
4856
4857   // Find the backing store.
4858   Handle<FixedArrayBase> elements(object->elements(), isolate);
4859   bool is_arguments = object->HasSloppyArgumentsElements();
4860   if (is_arguments) {
4861     FixedArray* parameter_map = FixedArray::cast(*elements);
4862     elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
4863   }
4864
4865   if (elements->IsDictionary()) {
4866     return Handle<SeededNumberDictionary>::cast(elements);
4867   }
4868
4869   DCHECK(object->HasFastSmiOrObjectElements() ||
4870          object->HasFastDoubleElements() ||
4871          object->HasFastArgumentsElements());
4872
4873   Handle<SeededNumberDictionary> dictionary =
4874       GetNormalizedElementDictionary(object, elements);
4875
4876   // Switch to using the dictionary as the backing storage for elements.
4877   ElementsKind target_kind =
4878       is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
4879   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
4880   // Set the new map first to satify the elements type assert in set_elements().
4881   JSObject::MigrateToMap(object, new_map);
4882
4883   if (is_arguments) {
4884     FixedArray::cast(object->elements())->set(1, *dictionary);
4885   } else {
4886     object->set_elements(*dictionary);
4887   }
4888
4889   isolate->counters()->elements_to_dictionary()->Increment();
4890
4891 #ifdef DEBUG
4892   if (FLAG_trace_normalization) {
4893     OFStream os(stdout);
4894     os << "Object elements have been normalized:\n";
4895     object->Print(os);
4896   }
4897 #endif
4898
4899   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
4900   return dictionary;
4901 }
4902
4903
4904 static Smi* GenerateIdentityHash(Isolate* isolate) {
4905   int hash_value;
4906   int attempts = 0;
4907   do {
4908     // Generate a random 32-bit hash value but limit range to fit
4909     // within a smi.
4910     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4911     attempts++;
4912   } while (hash_value == 0 && attempts < 30);
4913   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4914
4915   return Smi::FromInt(hash_value);
4916 }
4917
4918
4919 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4920   DCHECK(!object->IsJSGlobalProxy());
4921   Isolate* isolate = object->GetIsolate();
4922   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4923   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4924 }
4925
4926
4927 template<typename ProxyType>
4928 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4929   Isolate* isolate = proxy->GetIsolate();
4930
4931   Handle<Object> maybe_hash(proxy->hash(), isolate);
4932   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4933
4934   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4935   proxy->set_hash(*hash);
4936   return hash;
4937 }
4938
4939
4940 Object* JSObject::GetIdentityHash() {
4941   DisallowHeapAllocation no_gc;
4942   Isolate* isolate = GetIsolate();
4943   if (IsJSGlobalProxy()) {
4944     return JSGlobalProxy::cast(this)->hash();
4945   }
4946   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4947   Handle<Object> stored_value =
4948       Object::GetPropertyOrElement(Handle<Object>(this, isolate),
4949                                    hash_code_symbol).ToHandleChecked();
4950   return stored_value->IsSmi() ? *stored_value
4951                                : isolate->heap()->undefined_value();
4952 }
4953
4954
4955 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4956   if (object->IsJSGlobalProxy()) {
4957     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4958   }
4959
4960   Isolate* isolate = object->GetIsolate();
4961
4962   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4963   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4964
4965   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4966   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4967   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4968   return hash;
4969 }
4970
4971
4972 Object* JSProxy::GetIdentityHash() {
4973   return this->hash();
4974 }
4975
4976
4977 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4978   return GetOrCreateIdentityHashHelper(proxy);
4979 }
4980
4981
4982 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4983   DisallowHeapAllocation no_gc;
4984   DCHECK(key->IsUniqueName());
4985   if (IsJSGlobalProxy()) {
4986     // For a proxy, use the prototype as target object.
4987     PrototypeIterator iter(GetIsolate(), this);
4988     // If the proxy is detached, return undefined.
4989     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4990     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4991     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4992   }
4993   DCHECK(!IsJSGlobalProxy());
4994   Object* inline_value = GetHiddenPropertiesHashTable();
4995
4996   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4997
4998   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4999   Object* entry = hashtable->Lookup(key);
5000   return entry;
5001 }
5002
5003
5004 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5005                                            Handle<Name> key,
5006                                            Handle<Object> value) {
5007   Isolate* isolate = object->GetIsolate();
5008
5009   DCHECK(key->IsUniqueName());
5010   if (object->IsJSGlobalProxy()) {
5011     // For a proxy, use the prototype as target object.
5012     PrototypeIterator iter(isolate, object);
5013     // If the proxy is detached, return undefined.
5014     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
5015     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5016     return SetHiddenProperty(
5017         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
5018         value);
5019   }
5020   DCHECK(!object->IsJSGlobalProxy());
5021
5022   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5023
5024   Handle<ObjectHashTable> hashtable =
5025       GetOrCreateHiddenPropertiesHashtable(object);
5026
5027   // If it was found, check if the key is already in the dictionary.
5028   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5029                                                            value);
5030   if (*new_table != *hashtable) {
5031     // If adding the key expanded the dictionary (i.e., Add returned a new
5032     // dictionary), store it back to the object.
5033     SetHiddenPropertiesHashTable(object, new_table);
5034   }
5035
5036   // Return this to mark success.
5037   return object;
5038 }
5039
5040
5041 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5042   Isolate* isolate = object->GetIsolate();
5043   DCHECK(key->IsUniqueName());
5044
5045   if (object->IsJSGlobalProxy()) {
5046     PrototypeIterator iter(isolate, object);
5047     if (iter.IsAtEnd()) return;
5048     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5049     return DeleteHiddenProperty(
5050         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5051   }
5052
5053   Object* inline_value = object->GetHiddenPropertiesHashTable();
5054
5055   if (inline_value->IsUndefined()) return;
5056
5057   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5058   bool was_present = false;
5059   ObjectHashTable::Remove(hashtable, key, &was_present);
5060 }
5061
5062
5063 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5064   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5065   LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
5066   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5067   // Cannot get an exception since the hidden_string isn't accessible to JS.
5068   DCHECK(maybe.IsJust());
5069   return maybe.FromJust() != ABSENT;
5070 }
5071
5072
5073 Object* JSObject::GetHiddenPropertiesHashTable() {
5074   DCHECK(!IsJSGlobalProxy());
5075   if (HasFastProperties()) {
5076     // If the object has fast properties, check whether the first slot
5077     // in the descriptor array matches the hidden string. Since the
5078     // hidden strings hash code is zero (and no other name has hash
5079     // code zero) it will always occupy the first entry if present.
5080     DescriptorArray* descriptors = this->map()->instance_descriptors();
5081     if (descriptors->number_of_descriptors() > 0) {
5082       int sorted_index = descriptors->GetSortedKeyIndex(0);
5083       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5084           sorted_index < map()->NumberOfOwnDescriptors()) {
5085         DCHECK(descriptors->GetType(sorted_index) == DATA);
5086         DCHECK(descriptors->GetDetails(sorted_index).representation().
5087                IsCompatibleForLoad(Representation::Tagged()));
5088         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5089                                                      sorted_index);
5090         return this->RawFastPropertyAt(index);
5091       } else {
5092         return GetHeap()->undefined_value();
5093       }
5094     } else {
5095       return GetHeap()->undefined_value();
5096     }
5097   } else {
5098     Isolate* isolate = GetIsolate();
5099     LookupIterator it(handle(this), isolate->factory()->hidden_string(),
5100                       LookupIterator::OWN_SKIP_INTERCEPTOR);
5101     // Access check is always skipped for the hidden string anyways.
5102     return *GetDataProperty(&it);
5103   }
5104 }
5105
5106 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5107     Handle<JSObject> object) {
5108   Isolate* isolate = object->GetIsolate();
5109
5110   static const int kInitialCapacity = 4;
5111   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5112   if (inline_value->IsHashTable()) {
5113     return Handle<ObjectHashTable>::cast(inline_value);
5114   }
5115
5116   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5117       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5118
5119   DCHECK(inline_value->IsUndefined());
5120   SetHiddenPropertiesHashTable(object, hashtable);
5121   return hashtable;
5122 }
5123
5124
5125 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5126                                                       Handle<Object> value) {
5127   DCHECK(!object->IsJSGlobalProxy());
5128   Isolate* isolate = object->GetIsolate();
5129   Handle<Name> name = isolate->factory()->hidden_string();
5130   SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
5131   return object;
5132 }
5133
5134
5135 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5136     LookupIterator* it) {
5137   Isolate* isolate = it->isolate();
5138   // Make sure that the top context does not change when doing callbacks or
5139   // interceptor calls.
5140   AssertNoContextChange ncc(isolate);
5141
5142   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
5143   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
5144   if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
5145
5146   Handle<JSObject> holder = it->GetHolder<JSObject>();
5147
5148   PropertyCallbackArguments args(isolate, interceptor->data(),
5149                                  *it->GetReceiver(), *holder);
5150   v8::Local<v8::Boolean> result;
5151   if (it->IsElement()) {
5152     uint32_t index = it->index();
5153     v8::IndexedPropertyDeleterCallback deleter =
5154         v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5155     LOG(isolate,
5156         ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index));
5157     result = args.Call(deleter, index);
5158   } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
5159     return MaybeHandle<Object>();
5160   } else {
5161     Handle<Name> name = it->name();
5162     v8::GenericNamedPropertyDeleterCallback deleter =
5163         v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
5164             interceptor->deleter());
5165     LOG(isolate,
5166         ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
5167     result = args.Call(deleter, v8::Utils::ToLocal(name));
5168   }
5169
5170   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5171   if (result.IsEmpty()) return MaybeHandle<Object>();
5172
5173   DCHECK(result->IsBoolean());
5174   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5175   result_internal->VerifyApiCallResultType();
5176   // Rebox CustomArguments::kReturnValueOffset before returning.
5177   return handle(*result_internal, isolate);
5178 }
5179
5180
5181 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
5182                                         Handle<Name> name, int entry) {
5183   DCHECK(!object->HasFastProperties());
5184   Isolate* isolate = object->GetIsolate();
5185
5186   if (object->IsGlobalObject()) {
5187     // If we have a global object, invalidate the cell and swap in a new one.
5188     Handle<GlobalDictionary> dictionary(object->global_dictionary());
5189     DCHECK_NE(GlobalDictionary::kNotFound, entry);
5190
5191     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
5192     cell->set_value(isolate->heap()->the_hole_value());
5193     // TODO(ishell): InvalidateForDelete
5194     cell->set_property_details(
5195         cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
5196   } else {
5197     Handle<NameDictionary> dictionary(object->property_dictionary());
5198     DCHECK_NE(NameDictionary::kNotFound, entry);
5199
5200     NameDictionary::DeleteProperty(dictionary, entry);
5201     Handle<NameDictionary> new_properties =
5202         NameDictionary::Shrink(dictionary, name);
5203     object->set_properties(*new_properties);
5204   }
5205 }
5206
5207
5208 // ECMA-262, 3rd, 8.6.2.5
5209 MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it,
5210                                                LanguageMode language_mode) {
5211   Isolate* isolate = it->isolate();
5212   if (it->state() == LookupIterator::JSPROXY) {
5213     return JSProxy::DeletePropertyWithHandler(it->GetHolder<JSProxy>(),
5214                                               it->GetName(), language_mode);
5215   }
5216
5217   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
5218
5219   bool is_observed =
5220       receiver->map()->is_observed() &&
5221       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()));
5222
5223   Handle<Object> old_value = it->factory()->the_hole_value();
5224
5225   for (; it->IsFound(); it->Next()) {
5226     switch (it->state()) {
5227       case LookupIterator::JSPROXY:
5228       case LookupIterator::NOT_FOUND:
5229       case LookupIterator::TRANSITION:
5230         UNREACHABLE();
5231       case LookupIterator::ACCESS_CHECK:
5232         if (it->HasAccess()) break;
5233         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
5234         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5235         return it->factory()->false_value();
5236       case LookupIterator::INTERCEPTOR: {
5237         MaybeHandle<Object> maybe_result =
5238             JSObject::DeletePropertyWithInterceptor(it);
5239         // Delete with interceptor succeeded. Return result.
5240         if (!maybe_result.is_null()) return maybe_result;
5241         // An exception was thrown in the interceptor. Propagate.
5242         if (isolate->has_pending_exception()) return maybe_result;
5243         break;
5244       }
5245       case LookupIterator::INTEGER_INDEXED_EXOTIC:
5246         return it->factory()->true_value();
5247       case LookupIterator::DATA:
5248         if (is_observed) {
5249           old_value = it->GetDataValue();
5250         }
5251       // Fall through.
5252       case LookupIterator::ACCESSOR: {
5253         if (!it->IsConfigurable() || receiver->map()->is_strong()) {
5254           // Fail if the property is not configurable, or on a strong object.
5255           if (is_strict(language_mode)) {
5256             MessageTemplate::Template templ =
5257                 receiver->map()->is_strong()
5258                     ? MessageTemplate::kStrongDeleteProperty
5259                     : MessageTemplate::kStrictDeleteProperty;
5260             THROW_NEW_ERROR(
5261                 isolate, NewTypeError(templ, it->GetName(), receiver), Object);
5262           }
5263           return it->factory()->false_value();
5264         }
5265
5266         it->Delete();
5267
5268         if (is_observed) {
5269           RETURN_ON_EXCEPTION(isolate,
5270                               JSObject::EnqueueChangeRecord(
5271                                   receiver, "delete", it->GetName(), old_value),
5272                               Object);
5273         }
5274
5275         return it->factory()->true_value();
5276       }
5277     }
5278   }
5279
5280   return it->factory()->true_value();
5281 }
5282
5283
5284 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5285                                               uint32_t index,
5286                                               LanguageMode language_mode) {
5287   LookupIterator it(object->GetIsolate(), object, index,
5288                     LookupIterator::HIDDEN);
5289   return DeleteProperty(&it, language_mode);
5290 }
5291
5292
5293 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5294                                                Handle<Name> name,
5295                                                LanguageMode language_mode) {
5296   LookupIterator it(object, name, LookupIterator::HIDDEN);
5297   return JSObject::DeleteProperty(&it, language_mode);
5298 }
5299
5300
5301 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement(
5302     Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) {
5303   LookupIterator it = LookupIterator::PropertyOrElement(
5304       name->GetIsolate(), object, name, LookupIterator::HIDDEN);
5305   return JSObject::DeleteProperty(&it, language_mode);
5306 }
5307
5308
5309 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5310                                             ElementsKind kind,
5311                                             Object* object) {
5312   DCHECK(IsFastObjectElementsKind(kind) ||
5313          kind == DICTIONARY_ELEMENTS);
5314   if (IsFastObjectElementsKind(kind)) {
5315     int length = IsJSArray()
5316         ? Smi::cast(JSArray::cast(this)->length())->value()
5317         : elements->length();
5318     for (int i = 0; i < length; ++i) {
5319       Object* element = elements->get(i);
5320       if (!element->IsTheHole() && element == object) return true;
5321     }
5322   } else {
5323     Object* key =
5324         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5325     if (!key->IsUndefined()) return true;
5326   }
5327   return false;
5328 }
5329
5330
5331 // Check whether this object references another object.
5332 bool JSObject::ReferencesObject(Object* obj) {
5333   Map* map_of_this = map();
5334   Heap* heap = GetHeap();
5335   DisallowHeapAllocation no_allocation;
5336
5337   // Is the object the constructor for this object?
5338   if (map_of_this->GetConstructor() == obj) {
5339     return true;
5340   }
5341
5342   // Is the object the prototype for this object?
5343   if (map_of_this->prototype() == obj) {
5344     return true;
5345   }
5346
5347   // Check if the object is among the named properties.
5348   Object* key = SlowReverseLookup(obj);
5349   if (!key->IsUndefined()) {
5350     return true;
5351   }
5352
5353   // Check if the object is among the indexed properties.
5354   ElementsKind kind = GetElementsKind();
5355   switch (kind) {
5356     // Raw pixels and external arrays do not reference other
5357     // objects.
5358 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5359     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5360     case TYPE##_ELEMENTS:                                                      \
5361       break;
5362
5363     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5364 #undef TYPED_ARRAY_CASE
5365
5366     case FAST_DOUBLE_ELEMENTS:
5367     case FAST_HOLEY_DOUBLE_ELEMENTS:
5368       break;
5369     case FAST_SMI_ELEMENTS:
5370     case FAST_HOLEY_SMI_ELEMENTS:
5371       break;
5372     case FAST_ELEMENTS:
5373     case FAST_HOLEY_ELEMENTS:
5374     case DICTIONARY_ELEMENTS: {
5375       FixedArray* elements = FixedArray::cast(this->elements());
5376       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5377       break;
5378     }
5379     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5380     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
5381       FixedArray* parameter_map = FixedArray::cast(elements());
5382       // Check the mapped parameters.
5383       int length = parameter_map->length();
5384       for (int i = 2; i < length; ++i) {
5385         Object* value = parameter_map->get(i);
5386         if (!value->IsTheHole() && value == obj) return true;
5387       }
5388       // Check the arguments.
5389       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5390       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5391           FAST_HOLEY_ELEMENTS;
5392       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5393       break;
5394     }
5395   }
5396
5397   // For functions check the context.
5398   if (IsJSFunction()) {
5399     // Get the constructor function for arguments array.
5400     Map* arguments_map =
5401         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5402     JSFunction* arguments_function =
5403         JSFunction::cast(arguments_map->GetConstructor());
5404
5405     // Get the context and don't check if it is the native context.
5406     JSFunction* f = JSFunction::cast(this);
5407     Context* context = f->context();
5408     if (context->IsNativeContext()) {
5409       return false;
5410     }
5411
5412     // Check the non-special context slots.
5413     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5414       // Only check JS objects.
5415       if (context->get(i)->IsJSObject()) {
5416         JSObject* ctxobj = JSObject::cast(context->get(i));
5417         // If it is an arguments array check the content.
5418         if (ctxobj->map()->GetConstructor() == arguments_function) {
5419           if (ctxobj->ReferencesObject(obj)) {
5420             return true;
5421           }
5422         } else if (ctxobj == obj) {
5423           return true;
5424         }
5425       }
5426     }
5427
5428     // Check the context extension (if any) if it can have references.
5429     if (context->has_extension() && !context->IsCatchContext()) {
5430       // With harmony scoping, a JSFunction may have a global context.
5431       // TODO(mvstanton): walk into the ScopeInfo.
5432       if (context->IsScriptContext()) {
5433         return false;
5434       }
5435
5436       return JSObject::cast(context->extension())->ReferencesObject(obj);
5437     }
5438   }
5439
5440   // No references to object.
5441   return false;
5442 }
5443
5444
5445 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5446   if (!object->map()->is_extensible()) return object;
5447
5448   if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
5449     return PreventExtensionsWithTransition<NONE>(object);
5450   }
5451
5452   Isolate* isolate = object->GetIsolate();
5453
5454   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5455     isolate->ReportFailedAccessCheck(object);
5456     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5457     return isolate->factory()->false_value();
5458   }
5459
5460   if (object->IsJSGlobalProxy()) {
5461     PrototypeIterator iter(isolate, object);
5462     if (iter.IsAtEnd()) return object;
5463     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5464     return PreventExtensions(
5465         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5466   }
5467
5468   // It's not possible to seal objects with external array elements
5469   if (object->HasExternalArrayElements() ||
5470       object->HasFixedTypedArrayElements()) {
5471     THROW_NEW_ERROR(
5472         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5473         Object);
5474   }
5475
5476   // If there are fast elements we normalize.
5477   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5478   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
5479
5480   // Make sure that we never go back to fast case.
5481   object->RequireSlowElements(*dictionary);
5482
5483   // Do a map transition, other objects with this map may still
5484   // be extensible.
5485   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5486   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
5487
5488   new_map->set_is_extensible(false);
5489   JSObject::MigrateToMap(object, new_map);
5490   DCHECK(!object->map()->is_extensible());
5491
5492   if (object->map()->is_observed()) {
5493     RETURN_ON_EXCEPTION(
5494         isolate,
5495         EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5496                             isolate->factory()->the_hole_value()),
5497         Object);
5498   }
5499   return object;
5500 }
5501
5502
5503 bool JSObject::IsExtensible() {
5504   if (IsJSGlobalProxy()) {
5505     PrototypeIterator iter(GetIsolate(), this);
5506     if (iter.IsAtEnd()) return false;
5507     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
5508     return JSObject::cast(iter.GetCurrent())->map()->is_extensible();
5509   }
5510   return map()->is_extensible();
5511 }
5512
5513
5514 template <typename Dictionary>
5515 static void ApplyAttributesToDictionary(Dictionary* dictionary,
5516                                         const PropertyAttributes attributes) {
5517   int capacity = dictionary->Capacity();
5518   for (int i = 0; i < capacity; i++) {
5519     Object* k = dictionary->KeyAt(i);
5520     if (dictionary->IsKey(k) &&
5521         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5522       PropertyDetails details = dictionary->DetailsAt(i);
5523       int attrs = attributes;
5524       // READ_ONLY is an invalid attribute for JS setters/getters.
5525       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
5526         Object* v = dictionary->ValueAt(i);
5527         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5528         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
5529       }
5530       details = details.CopyAddAttributes(
5531           static_cast<PropertyAttributes>(attrs));
5532       dictionary->DetailsAtPut(i, details);
5533     }
5534   }
5535 }
5536
5537
5538 template <PropertyAttributes attrs>
5539 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
5540     Handle<JSObject> object) {
5541   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
5542
5543   // Sealing/freezing sloppy arguments should be handled elsewhere.
5544   DCHECK(!object->HasSloppyArgumentsElements());
5545   DCHECK(!object->map()->is_observed());
5546
5547   Isolate* isolate = object->GetIsolate();
5548   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5549     isolate->ReportFailedAccessCheck(object);
5550     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5551     return isolate->factory()->false_value();
5552   }
5553
5554   if (object->IsJSGlobalProxy()) {
5555     PrototypeIterator iter(isolate, object);
5556     if (iter.IsAtEnd()) return object;
5557     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5558     return PreventExtensionsWithTransition<attrs>(
5559         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5560   }
5561
5562   // It's not possible to seal or freeze objects with external array elements
5563   if (object->HasExternalArrayElements() ||
5564       object->HasFixedTypedArrayElements()) {
5565     THROW_NEW_ERROR(
5566         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5567         Object);
5568   }
5569
5570   Handle<SeededNumberDictionary> new_element_dictionary;
5571   if (!object->HasDictionaryElements()) {
5572     int length =
5573         object->IsJSArray()
5574             ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5575             : object->elements()->length();
5576     new_element_dictionary =
5577         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
5578                     : GetNormalizedElementDictionary(
5579                           object, handle(object->elements()));
5580   }
5581
5582   Handle<Symbol> transition_marker;
5583   if (attrs == NONE) {
5584     transition_marker = isolate->factory()->nonextensible_symbol();
5585   } else if (attrs == SEALED) {
5586     transition_marker = isolate->factory()->sealed_symbol();
5587   } else {
5588     DCHECK(attrs == FROZEN);
5589     transition_marker = isolate->factory()->frozen_symbol();
5590   }
5591
5592   Handle<Map> old_map(object->map(), isolate);
5593   Map* transition =
5594       TransitionArray::SearchSpecial(*old_map, *transition_marker);
5595   if (transition != NULL) {
5596     Handle<Map> transition_map(transition, isolate);
5597     DCHECK(transition_map->has_dictionary_elements());
5598     DCHECK(!transition_map->is_extensible());
5599     JSObject::MigrateToMap(object, transition_map);
5600   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5601     // Create a new descriptor array with the appropriate property attributes
5602     Handle<Map> new_map = Map::CopyForPreventExtensions(
5603         old_map, attrs, transition_marker, "CopyForPreventExtensions");
5604     JSObject::MigrateToMap(object, new_map);
5605   } else {
5606     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5607     // Slow path: need to normalize properties for safety
5608     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5609                         "SlowPreventExtensions");
5610
5611     // Create a new map, since other objects with this map may be extensible.
5612     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5613     Handle<Map> new_map =
5614         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5615     new_map->set_is_extensible(false);
5616     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5617     JSObject::MigrateToMap(object, new_map);
5618
5619     if (attrs != NONE) {
5620       if (object->IsGlobalObject()) {
5621         ApplyAttributesToDictionary(object->global_dictionary(), attrs);
5622       } else {
5623         ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5624       }
5625     }
5626   }
5627
5628   DCHECK(object->map()->has_dictionary_elements());
5629   if (!new_element_dictionary.is_null()) {
5630     object->set_elements(*new_element_dictionary);
5631   }
5632
5633   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5634     SeededNumberDictionary* dictionary = object->element_dictionary();
5635     // Make sure we never go back to the fast case
5636     object->RequireSlowElements(dictionary);
5637     if (attrs != NONE) {
5638       ApplyAttributesToDictionary(dictionary, attrs);
5639     }
5640   }
5641
5642   return object;
5643 }
5644
5645
5646 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5647   return PreventExtensionsWithTransition<FROZEN>(object);
5648 }
5649
5650
5651 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
5652   return PreventExtensionsWithTransition<SEALED>(object);
5653 }
5654
5655
5656 void JSObject::SetObserved(Handle<JSObject> object) {
5657   DCHECK(!object->IsJSGlobalProxy());
5658   DCHECK(!object->IsJSGlobalObject());
5659   Isolate* isolate = object->GetIsolate();
5660   Handle<Map> new_map;
5661   Handle<Map> old_map(object->map(), isolate);
5662   DCHECK(!old_map->is_observed());
5663   Map* transition = TransitionArray::SearchSpecial(
5664       *old_map, isolate->heap()->observed_symbol());
5665   if (transition != NULL) {
5666     new_map = handle(transition, isolate);
5667     DCHECK(new_map->is_observed());
5668   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5669     new_map = Map::CopyForObserved(old_map);
5670   } else {
5671     new_map = Map::Copy(old_map, "SlowObserved");
5672     new_map->set_is_observed();
5673   }
5674   JSObject::MigrateToMap(object, new_map);
5675 }
5676
5677
5678 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5679                                         Representation representation,
5680                                         FieldIndex index) {
5681   Isolate* isolate = object->GetIsolate();
5682   if (object->IsUnboxedDoubleField(index)) {
5683     double value = object->RawFastDoublePropertyAt(index);
5684     return isolate->factory()->NewHeapNumber(value);
5685   }
5686   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5687   return Object::WrapForRead(isolate, raw_value, representation);
5688 }
5689
5690
5691 template<class ContextObject>
5692 class JSObjectWalkVisitor {
5693  public:
5694   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5695                       JSObject::DeepCopyHints hints)
5696     : site_context_(site_context),
5697       copying_(copying),
5698       hints_(hints) {}
5699
5700   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5701
5702  protected:
5703   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5704       Handle<JSObject> object,
5705       Handle<JSObject> value) {
5706     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5707     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5708     site_context()->ExitScope(current_site, value);
5709     return copy_of_value;
5710   }
5711
5712   inline ContextObject* site_context() { return site_context_; }
5713   inline Isolate* isolate() { return site_context()->isolate(); }
5714
5715   inline bool copying() const { return copying_; }
5716
5717  private:
5718   ContextObject* site_context_;
5719   const bool copying_;
5720   const JSObject::DeepCopyHints hints_;
5721 };
5722
5723
5724 template <class ContextObject>
5725 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5726     Handle<JSObject> object) {
5727   Isolate* isolate = this->isolate();
5728   bool copying = this->copying();
5729   bool shallow = hints_ == JSObject::kObjectIsShallow;
5730
5731   if (!shallow) {
5732     StackLimitCheck check(isolate);
5733
5734     if (check.HasOverflowed()) {
5735       isolate->StackOverflow();
5736       return MaybeHandle<JSObject>();
5737     }
5738   }
5739
5740   if (object->map()->is_deprecated()) {
5741     JSObject::MigrateInstance(object);
5742   }
5743
5744   Handle<JSObject> copy;
5745   if (copying) {
5746     Handle<AllocationSite> site_to_pass;
5747     if (site_context()->ShouldCreateMemento(object)) {
5748       site_to_pass = site_context()->current();
5749     }
5750     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5751         object, site_to_pass);
5752   } else {
5753     copy = object;
5754   }
5755
5756   DCHECK(copying || copy.is_identical_to(object));
5757
5758   ElementsKind kind = copy->GetElementsKind();
5759   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5760       FixedArray::cast(copy->elements())->map() ==
5761         isolate->heap()->fixed_cow_array_map()) {
5762     isolate->counters()->cow_arrays_created_runtime()->Increment();
5763   }
5764
5765   if (!shallow) {
5766     HandleScope scope(isolate);
5767
5768     // Deep copy own properties.
5769     if (copy->HasFastProperties()) {
5770       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5771       int limit = copy->map()->NumberOfOwnDescriptors();
5772       for (int i = 0; i < limit; i++) {
5773         PropertyDetails details = descriptors->GetDetails(i);
5774         if (details.type() != DATA) continue;
5775         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5776         if (object->IsUnboxedDoubleField(index)) {
5777           if (copying) {
5778             double value = object->RawFastDoublePropertyAt(index);
5779             copy->RawFastDoublePropertyAtPut(index, value);
5780           }
5781         } else {
5782           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5783           if (value->IsJSObject()) {
5784             ASSIGN_RETURN_ON_EXCEPTION(
5785                 isolate, value,
5786                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5787                 JSObject);
5788             if (copying) {
5789               copy->FastPropertyAtPut(index, *value);
5790             }
5791           } else {
5792             if (copying) {
5793               Representation representation = details.representation();
5794               value = Object::NewStorageFor(isolate, value, representation);
5795               copy->FastPropertyAtPut(index, *value);
5796             }
5797           }
5798         }
5799       }
5800     } else {
5801       Handle<FixedArray> names =
5802           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5803       copy->GetOwnPropertyNames(*names, 0);
5804       for (int i = 0; i < names->length(); i++) {
5805         DCHECK(names->get(i)->IsString());
5806         Handle<String> key_string(String::cast(names->get(i)));
5807         Maybe<PropertyAttributes> maybe =
5808             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5809         DCHECK(maybe.IsJust());
5810         PropertyAttributes attributes = maybe.FromJust();
5811         // Only deep copy fields from the object literal expression.
5812         // In particular, don't try to copy the length attribute of
5813         // an array.
5814         if (attributes != NONE) continue;
5815         Handle<Object> value =
5816             Object::GetProperty(copy, key_string).ToHandleChecked();
5817         if (value->IsJSObject()) {
5818           Handle<JSObject> result;
5819           ASSIGN_RETURN_ON_EXCEPTION(
5820               isolate, result,
5821               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5822               JSObject);
5823           if (copying) {
5824             // Creating object copy for literals. No strict mode needed.
5825             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5826           }
5827         }
5828       }
5829     }
5830
5831     // Deep copy own elements.
5832     // Pixel elements cannot be created using an object literal.
5833     DCHECK(!copy->HasExternalArrayElements());
5834     switch (kind) {
5835       case FAST_SMI_ELEMENTS:
5836       case FAST_ELEMENTS:
5837       case FAST_HOLEY_SMI_ELEMENTS:
5838       case FAST_HOLEY_ELEMENTS: {
5839         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5840         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5841 #ifdef DEBUG
5842           for (int i = 0; i < elements->length(); i++) {
5843             DCHECK(!elements->get(i)->IsJSObject());
5844           }
5845 #endif
5846         } else {
5847           for (int i = 0; i < elements->length(); i++) {
5848             Handle<Object> value(elements->get(i), isolate);
5849             DCHECK(value->IsSmi() ||
5850                    value->IsTheHole() ||
5851                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5852             if (value->IsJSObject()) {
5853               Handle<JSObject> result;
5854               ASSIGN_RETURN_ON_EXCEPTION(
5855                   isolate, result,
5856                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5857                   JSObject);
5858               if (copying) {
5859                 elements->set(i, *result);
5860               }
5861             }
5862           }
5863         }
5864         break;
5865       }
5866       case DICTIONARY_ELEMENTS: {
5867         Handle<SeededNumberDictionary> element_dictionary(
5868             copy->element_dictionary());
5869         int capacity = element_dictionary->Capacity();
5870         for (int i = 0; i < capacity; i++) {
5871           Object* k = element_dictionary->KeyAt(i);
5872           if (element_dictionary->IsKey(k)) {
5873             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5874             if (value->IsJSObject()) {
5875               Handle<JSObject> result;
5876               ASSIGN_RETURN_ON_EXCEPTION(
5877                   isolate, result,
5878                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5879                   JSObject);
5880               if (copying) {
5881                 element_dictionary->ValueAtPut(i, *result);
5882               }
5883             }
5884           }
5885         }
5886         break;
5887       }
5888       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5889       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
5890         UNIMPLEMENTED();
5891         break;
5892
5893
5894 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5895       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
5896       case TYPE##_ELEMENTS:                                                    \
5897
5898       TYPED_ARRAYS(TYPED_ARRAY_CASE)
5899 #undef TYPED_ARRAY_CASE
5900
5901       case FAST_DOUBLE_ELEMENTS:
5902       case FAST_HOLEY_DOUBLE_ELEMENTS:
5903         // No contained objects, nothing to do.
5904         break;
5905     }
5906   }
5907
5908   return copy;
5909 }
5910
5911
5912 MaybeHandle<JSObject> JSObject::DeepWalk(
5913     Handle<JSObject> object,
5914     AllocationSiteCreationContext* site_context) {
5915   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
5916                                                        kNoHints);
5917   MaybeHandle<JSObject> result = v.StructureWalk(object);
5918   Handle<JSObject> for_assert;
5919   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
5920   return result;
5921 }
5922
5923
5924 MaybeHandle<JSObject> JSObject::DeepCopy(
5925     Handle<JSObject> object,
5926     AllocationSiteUsageContext* site_context,
5927     DeepCopyHints hints) {
5928   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5929   MaybeHandle<JSObject> copy = v.StructureWalk(object);
5930   Handle<JSObject> for_assert;
5931   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
5932   return copy;
5933 }
5934
5935
5936 // Tests for the fast common case for property enumeration:
5937 // - This object and all prototypes has an enum cache (which means that
5938 //   it is no proxy, has no interceptors and needs no access checks).
5939 // - This object has no elements.
5940 // - No prototype has enumerable properties/elements.
5941 bool JSReceiver::IsSimpleEnum() {
5942   for (PrototypeIterator iter(GetIsolate(), this,
5943                               PrototypeIterator::START_AT_RECEIVER);
5944        !iter.IsAtEnd(); iter.Advance()) {
5945     if (!iter.GetCurrent()->IsJSObject()) return false;
5946     JSObject* curr = JSObject::cast(iter.GetCurrent());
5947     int enum_length = curr->map()->EnumLength();
5948     if (enum_length == kInvalidEnumCacheSentinel) return false;
5949     if (curr->IsAccessCheckNeeded()) return false;
5950     DCHECK(!curr->HasNamedInterceptor());
5951     DCHECK(!curr->HasIndexedInterceptor());
5952     if (curr->NumberOfEnumElements() > 0) return false;
5953     if (curr != this && enum_length != 0) return false;
5954   }
5955   return true;
5956 }
5957
5958
5959 static bool FilterKey(Object* key, PropertyAttributes filter) {
5960   if ((filter & SYMBOLIC) && key->IsSymbol()) {
5961     return true;
5962   }
5963
5964   if ((filter & PRIVATE_SYMBOL) &&
5965       key->IsSymbol() && Symbol::cast(key)->is_private()) {
5966     return true;
5967   }
5968
5969   if ((filter & STRING) && !key->IsSymbol()) {
5970     return true;
5971   }
5972
5973   return false;
5974 }
5975
5976
5977 int Map::NumberOfDescribedProperties(DescriptorFlag which,
5978                                      PropertyAttributes filter) {
5979   int result = 0;
5980   DescriptorArray* descs = instance_descriptors();
5981   int limit = which == ALL_DESCRIPTORS
5982       ? descs->number_of_descriptors()
5983       : NumberOfOwnDescriptors();
5984   for (int i = 0; i < limit; i++) {
5985     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
5986         !FilterKey(descs->GetKey(i), filter)) {
5987       result++;
5988     }
5989   }
5990   return result;
5991 }
5992
5993
5994 int Map::NextFreePropertyIndex() {
5995   int free_index = 0;
5996   int number_of_own_descriptors = NumberOfOwnDescriptors();
5997   DescriptorArray* descs = instance_descriptors();
5998   for (int i = 0; i < number_of_own_descriptors; i++) {
5999     PropertyDetails details = descs->GetDetails(i);
6000     if (details.location() == kField) {
6001       int candidate = details.field_index() + details.field_width_in_words();
6002       if (candidate > free_index) free_index = candidate;
6003     }
6004   }
6005   return free_index;
6006 }
6007
6008
6009 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6010   int len = array->length();
6011   for (int i = 0; i < len; i++) {
6012     Object* e = array->get(i);
6013     if (!(e->IsName() || e->IsNumber())) return false;
6014   }
6015   return true;
6016 }
6017
6018
6019 static Handle<FixedArray> ReduceFixedArrayTo(
6020     Handle<FixedArray> array, int length) {
6021   DCHECK(array->length() >= length);
6022   if (array->length() == length) return array;
6023
6024   Handle<FixedArray> new_array =
6025       array->GetIsolate()->factory()->NewFixedArray(length);
6026   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6027   return new_array;
6028 }
6029
6030
6031 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
6032                                                  bool cache_result) {
6033   Isolate* isolate = object->GetIsolate();
6034   if (object->HasFastProperties()) {
6035     int own_property_count = object->map()->EnumLength();
6036     // If the enum length of the given map is set to kInvalidEnumCache, this
6037     // means that the map itself has never used the present enum cache. The
6038     // first step to using the cache is to set the enum length of the map by
6039     // counting the number of own descriptors that are not DONT_ENUM or
6040     // SYMBOLIC.
6041     if (own_property_count == kInvalidEnumCacheSentinel) {
6042       own_property_count = object->map()->NumberOfDescribedProperties(
6043           OWN_DESCRIPTORS, DONT_SHOW);
6044     } else {
6045       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6046           OWN_DESCRIPTORS, DONT_SHOW));
6047     }
6048
6049     if (object->map()->instance_descriptors()->HasEnumCache()) {
6050       DescriptorArray* desc = object->map()->instance_descriptors();
6051       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6052
6053       // In case the number of properties required in the enum are actually
6054       // present, we can reuse the enum cache. Otherwise, this means that the
6055       // enum cache was generated for a previous (smaller) version of the
6056       // Descriptor Array. In that case we regenerate the enum cache.
6057       if (own_property_count <= keys->length()) {
6058         if (cache_result) object->map()->SetEnumLength(own_property_count);
6059         isolate->counters()->enum_cache_hits()->Increment();
6060         return ReduceFixedArrayTo(keys, own_property_count);
6061       }
6062     }
6063
6064     Handle<Map> map(object->map());
6065
6066     if (map->instance_descriptors()->IsEmpty()) {
6067       isolate->counters()->enum_cache_hits()->Increment();
6068       if (cache_result) map->SetEnumLength(0);
6069       return isolate->factory()->empty_fixed_array();
6070     }
6071
6072     isolate->counters()->enum_cache_misses()->Increment();
6073
6074     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6075         own_property_count);
6076     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6077         own_property_count);
6078
6079     Handle<DescriptorArray> descs =
6080         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6081
6082     int size = map->NumberOfOwnDescriptors();
6083     int index = 0;
6084
6085     for (int i = 0; i < size; i++) {
6086       PropertyDetails details = descs->GetDetails(i);
6087       Object* key = descs->GetKey(i);
6088       if (!(details.IsDontEnum() || key->IsSymbol())) {
6089         storage->set(index, key);
6090         if (!indices.is_null()) {
6091           if (details.type() != DATA) {
6092             indices = Handle<FixedArray>();
6093           } else {
6094             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6095             int load_by_field_index = field_index.GetLoadByFieldIndex();
6096             indices->set(index, Smi::FromInt(load_by_field_index));
6097           }
6098         }
6099         index++;
6100       }
6101     }
6102     DCHECK(index == storage->length());
6103
6104     Handle<FixedArray> bridge_storage =
6105         isolate->factory()->NewFixedArray(
6106             DescriptorArray::kEnumCacheBridgeLength);
6107     DescriptorArray* desc = object->map()->instance_descriptors();
6108     desc->SetEnumCache(*bridge_storage,
6109                        *storage,
6110                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6111                                          : Object::cast(*indices));
6112     if (cache_result) {
6113       object->map()->SetEnumLength(own_property_count);
6114     }
6115     return storage;
6116   } else if (object->IsGlobalObject()) {
6117     Handle<GlobalDictionary> dictionary(object->global_dictionary());
6118     int length = dictionary->NumberOfEnumElements();
6119     if (length == 0) {
6120       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6121     }
6122     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6123     dictionary->CopyEnumKeysTo(*storage);
6124     return storage;
6125   } else {
6126     Handle<NameDictionary> dictionary(object->property_dictionary());
6127     int length = dictionary->NumberOfEnumElements();
6128     if (length == 0) {
6129       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6130     }
6131     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6132     dictionary->CopyEnumKeysTo(*storage);
6133     return storage;
6134   }
6135 }
6136
6137
6138 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6139                                             KeyCollectionType type) {
6140   USE(ContainsOnlyValidKeys);
6141   Isolate* isolate = object->GetIsolate();
6142   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6143   Handle<JSFunction> arguments_function(
6144       JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6145
6146   PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6147                                           ? PrototypeIterator::END_AT_NON_HIDDEN
6148                                           : PrototypeIterator::END_AT_NULL;
6149   // Only collect keys if access is permitted.
6150   for (PrototypeIterator iter(isolate, object,
6151                               PrototypeIterator::START_AT_RECEIVER);
6152        !iter.IsAtEnd(end); iter.Advance()) {
6153     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6154       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6155                             isolate);
6156       Handle<Object> args[] = { proxy };
6157       Handle<Object> names;
6158       ASSIGN_RETURN_ON_EXCEPTION(
6159           isolate, names,
6160           Execution::Call(isolate,
6161                           isolate->proxy_enumerate(),
6162                           object,
6163                           arraysize(args),
6164                           args),
6165           FixedArray);
6166       ASSIGN_RETURN_ON_EXCEPTION(
6167           isolate, content,
6168           FixedArray::AddKeysFromArrayLike(
6169               content, Handle<JSObject>::cast(names)),
6170           FixedArray);
6171       break;
6172     }
6173
6174     Handle<JSObject> current =
6175         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6176
6177     // Check access rights if required.
6178     if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6179       if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6180         isolate->ReportFailedAccessCheck(current);
6181         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6182       }
6183       break;
6184     }
6185
6186     // Compute the element keys.
6187     Handle<FixedArray> element_keys =
6188         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6189     current->GetEnumElementKeys(*element_keys);
6190     ASSIGN_RETURN_ON_EXCEPTION(
6191         isolate, content,
6192         FixedArray::UnionOfKeys(content, element_keys),
6193         FixedArray);
6194     DCHECK(ContainsOnlyValidKeys(content));
6195
6196     // Add the element keys from the interceptor.
6197     if (current->HasIndexedInterceptor()) {
6198       Handle<JSObject> result;
6199       if (JSObject::GetKeysForIndexedInterceptor(
6200               current, object).ToHandle(&result)) {
6201         ASSIGN_RETURN_ON_EXCEPTION(
6202             isolate, content,
6203             FixedArray::AddKeysFromArrayLike(content, result),
6204             FixedArray);
6205       }
6206       DCHECK(ContainsOnlyValidKeys(content));
6207     }
6208
6209     // We can cache the computed property keys if access checks are
6210     // not needed and no interceptors are involved.
6211     //
6212     // We do not use the cache if the object has elements and
6213     // therefore it does not make sense to cache the property names
6214     // for arguments objects.  Arguments objects will always have
6215     // elements.
6216     // Wrapped strings have elements, but don't have an elements
6217     // array or dictionary.  So the fast inline test for whether to
6218     // use the cache says yes, so we should not create a cache.
6219     bool cache_enum_keys =
6220         ((current->map()->GetConstructor() != *arguments_function) &&
6221          !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6222          !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6223     // Compute the property keys and cache them if possible.
6224     ASSIGN_RETURN_ON_EXCEPTION(
6225         isolate, content,
6226         FixedArray::UnionOfKeys(
6227             content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)),
6228         FixedArray);
6229     DCHECK(ContainsOnlyValidKeys(content));
6230
6231     // Add the non-symbol property keys from the interceptor.
6232     if (current->HasNamedInterceptor()) {
6233       Handle<JSObject> result;
6234       if (JSObject::GetKeysForNamedInterceptor(
6235               current, object).ToHandle(&result)) {
6236         ASSIGN_RETURN_ON_EXCEPTION(
6237             isolate, content, FixedArray::AddKeysFromArrayLike(
6238                                   content, result, FixedArray::NON_SYMBOL_KEYS),
6239             FixedArray);
6240       }
6241       DCHECK(ContainsOnlyValidKeys(content));
6242     }
6243   }
6244   return content;
6245 }
6246
6247
6248 bool Map::DictionaryElementsInPrototypeChainOnly() {
6249   if (IsDictionaryElementsKind(elements_kind())) {
6250     return false;
6251   }
6252
6253   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6254     // Be conservative, don't walk into proxies.
6255     if (iter.GetCurrent()->IsJSProxy()) return true;
6256     // String wrappers have non-configurable, non-writable elements.
6257     if (iter.GetCurrent()->IsStringWrapper()) return true;
6258     JSObject* current = JSObject::cast(iter.GetCurrent());
6259
6260     if (current->HasDictionaryElements() &&
6261         current->element_dictionary()->requires_slow_elements()) {
6262       return true;
6263     }
6264
6265     if (current->HasSlowArgumentsElements()) {
6266       FixedArray* parameter_map = FixedArray::cast(current->elements());
6267       Object* arguments = parameter_map->get(1);
6268       if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
6269         return true;
6270       }
6271     }
6272   }
6273
6274   return false;
6275 }
6276
6277
6278 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6279                                              Handle<Name> name,
6280                                              Handle<Object> getter,
6281                                              Handle<Object> setter,
6282                                              PropertyAttributes attributes) {
6283   Isolate* isolate = object->GetIsolate();
6284
6285   LookupIterator it = LookupIterator::PropertyOrElement(
6286       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6287
6288   if (it.state() == LookupIterator::ACCESS_CHECK) {
6289     if (!it.HasAccess()) {
6290       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6291       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6292       return isolate->factory()->undefined_value();
6293     }
6294     it.Next();
6295   }
6296
6297   // Ignore accessors on typed arrays.
6298   if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
6299                          object->HasExternalArrayElements())) {
6300     return it.factory()->undefined_value();
6301   }
6302
6303   Handle<Object> old_value = isolate->factory()->the_hole_value();
6304   bool is_observed = object->map()->is_observed() &&
6305                      !isolate->IsInternallyUsedPropertyName(name);
6306   bool preexists = false;
6307   if (is_observed) {
6308     CHECK(GetPropertyAttributes(&it).IsJust());
6309     preexists = it.IsFound();
6310     if (preexists && (it.state() == LookupIterator::DATA ||
6311                       it.GetAccessors()->IsAccessorInfo())) {
6312       old_value = GetProperty(&it).ToHandleChecked();
6313     }
6314   }
6315
6316   DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || getter->IsNull());
6317   DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || setter->IsNull());
6318   // At least one of the accessors needs to be a new value.
6319   DCHECK(!getter->IsNull() || !setter->IsNull());
6320   if (!getter->IsNull()) {
6321     it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6322   }
6323   if (!setter->IsNull()) {
6324     it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6325   }
6326
6327   if (is_observed) {
6328     // Make sure the top context isn't changed.
6329     AssertNoContextChange ncc(isolate);
6330     const char* type = preexists ? "reconfigure" : "add";
6331     RETURN_ON_EXCEPTION(
6332         isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
6333   }
6334
6335   return isolate->factory()->undefined_value();
6336 }
6337
6338
6339 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6340                                           Handle<AccessorInfo> info) {
6341   Isolate* isolate = object->GetIsolate();
6342   Handle<Name> name(Name::cast(info->name()), isolate);
6343
6344   LookupIterator it = LookupIterator::PropertyOrElement(
6345       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6346
6347   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
6348   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
6349   //
6350   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
6351   // remove reliance on default return values.
6352   if (it.state() == LookupIterator::ACCESS_CHECK) {
6353     if (!it.HasAccess()) {
6354       isolate->ReportFailedAccessCheck(object);
6355       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6356       return it.factory()->undefined_value();
6357     }
6358     it.Next();
6359   }
6360
6361   // Ignore accessors on typed arrays.
6362   if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
6363                          object->HasExternalArrayElements())) {
6364     return it.factory()->undefined_value();
6365   }
6366
6367   CHECK(GetPropertyAttributes(&it).IsJust());
6368
6369   // ES5 forbids turning a property into an accessor if it's not
6370   // configurable. See 8.6.1 (Table 5).
6371   if (it.IsFound() && !it.IsConfigurable()) {
6372     return it.factory()->undefined_value();
6373   }
6374
6375   it.TransitionToAccessorPair(info, info->property_attributes());
6376
6377   return object;
6378 }
6379
6380
6381 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6382                                           Handle<Name> name,
6383                                           AccessorComponent component) {
6384   Isolate* isolate = object->GetIsolate();
6385
6386   // Make sure that the top context does not change when doing callbacks or
6387   // interceptor calls.
6388   AssertNoContextChange ncc(isolate);
6389
6390   LookupIterator it = LookupIterator::PropertyOrElement(
6391       isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6392
6393   for (; it.IsFound(); it.Next()) {
6394     switch (it.state()) {
6395       case LookupIterator::INTERCEPTOR:
6396       case LookupIterator::NOT_FOUND:
6397       case LookupIterator::TRANSITION:
6398         UNREACHABLE();
6399
6400       case LookupIterator::ACCESS_CHECK:
6401         if (it.HasAccess()) continue;
6402         isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6403         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6404         return isolate->factory()->undefined_value();
6405
6406       case LookupIterator::JSPROXY:
6407         return isolate->factory()->undefined_value();
6408
6409       case LookupIterator::INTEGER_INDEXED_EXOTIC:
6410         return isolate->factory()->undefined_value();
6411       case LookupIterator::DATA:
6412         continue;
6413       case LookupIterator::ACCESSOR: {
6414         Handle<Object> maybe_pair = it.GetAccessors();
6415         if (maybe_pair->IsAccessorPair()) {
6416           return handle(
6417               AccessorPair::cast(*maybe_pair)->GetComponent(component),
6418               isolate);
6419         }
6420       }
6421     }
6422   }
6423
6424   return isolate->factory()->undefined_value();
6425 }
6426
6427
6428 Object* JSObject::SlowReverseLookup(Object* value) {
6429   if (HasFastProperties()) {
6430     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6431     DescriptorArray* descs = map()->instance_descriptors();
6432     bool value_is_number = value->IsNumber();
6433     for (int i = 0; i < number_of_own_descriptors; i++) {
6434       if (descs->GetType(i) == DATA) {
6435         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
6436         if (IsUnboxedDoubleField(field_index)) {
6437           if (value_is_number) {
6438             double property = RawFastDoublePropertyAt(field_index);
6439             if (property == value->Number()) {
6440               return descs->GetKey(i);
6441             }
6442           }
6443         } else {
6444           Object* property = RawFastPropertyAt(field_index);
6445           if (field_index.is_double()) {
6446             DCHECK(property->IsMutableHeapNumber());
6447             if (value_is_number && property->Number() == value->Number()) {
6448               return descs->GetKey(i);
6449             }
6450           } else if (property == value) {
6451             return descs->GetKey(i);
6452           }
6453         }
6454       } else if (descs->GetType(i) == DATA_CONSTANT) {
6455         if (descs->GetConstant(i) == value) {
6456           return descs->GetKey(i);
6457         }
6458       }
6459     }
6460     return GetHeap()->undefined_value();
6461   } else if (IsGlobalObject()) {
6462     return global_dictionary()->SlowReverseLookup(value);
6463   } else {
6464     return property_dictionary()->SlowReverseLookup(value);
6465   }
6466 }
6467
6468
6469 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6470   Isolate* isolate = map->GetIsolate();
6471   Handle<Map> result =
6472       isolate->factory()->NewMap(map->instance_type(), instance_size);
6473   Handle<Object> prototype(map->prototype(), isolate);
6474   Map::SetPrototype(result, prototype);
6475   result->set_constructor_or_backpointer(map->GetConstructor());
6476   result->set_bit_field(map->bit_field());
6477   result->set_bit_field2(map->bit_field2());
6478   int new_bit_field3 = map->bit_field3();
6479   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6480   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6481   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6482                                           kInvalidEnumCacheSentinel);
6483   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6484   if (!map->is_dictionary_map()) {
6485     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6486   }
6487   new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
6488   result->set_bit_field3(new_bit_field3);
6489   return result;
6490 }
6491
6492
6493 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
6494                            const char* reason) {
6495   DCHECK(!fast_map->is_dictionary_map());
6496
6497   Isolate* isolate = fast_map->GetIsolate();
6498   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6499                              isolate);
6500   bool use_cache = !fast_map->is_prototype_map() && !maybe_cache->IsUndefined();
6501   Handle<NormalizedMapCache> cache;
6502   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6503
6504   Handle<Map> new_map;
6505   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6506 #ifdef VERIFY_HEAP
6507     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6508 #endif
6509 #ifdef ENABLE_SLOW_DCHECKS
6510     if (FLAG_enable_slow_asserts) {
6511       // The cached map should match newly created normalized map bit-by-bit,
6512       // except for the code cache, which can contain some ics which can be
6513       // applied to the shared map, dependent code and weak cell cache.
6514       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6515
6516       if (new_map->is_prototype_map()) {
6517         // For prototype maps, the PrototypeInfo is not copied.
6518         DCHECK(memcmp(fresh->address(), new_map->address(),
6519                       kTransitionsOrPrototypeInfoOffset) == 0);
6520         DCHECK(fresh->raw_transitions() == Smi::FromInt(0));
6521         STATIC_ASSERT(kDescriptorsOffset ==
6522                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
6523         DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
6524                       HeapObject::RawField(*new_map, kDescriptorsOffset),
6525                       kCodeCacheOffset - kDescriptorsOffset) == 0);
6526       } else {
6527         DCHECK(memcmp(fresh->address(), new_map->address(),
6528                       Map::kCodeCacheOffset) == 0);
6529       }
6530       STATIC_ASSERT(Map::kDependentCodeOffset ==
6531                     Map::kCodeCacheOffset + kPointerSize);
6532       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
6533                     Map::kDependentCodeOffset + kPointerSize);
6534       int offset = Map::kWeakCellCacheOffset + kPointerSize;
6535       DCHECK(memcmp(fresh->address() + offset,
6536                     new_map->address() + offset,
6537                     Map::kSize - offset) == 0);
6538     }
6539 #endif
6540   } else {
6541     new_map = Map::CopyNormalized(fast_map, mode);
6542     if (use_cache) {
6543       cache->Set(fast_map, new_map);
6544       isolate->counters()->normalized_maps()->Increment();
6545     }
6546 #if TRACE_MAPS
6547     if (FLAG_trace_maps) {
6548       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
6549              reinterpret_cast<void*>(*fast_map),
6550              reinterpret_cast<void*>(*new_map), reason);
6551     }
6552 #endif
6553   }
6554   fast_map->NotifyLeafMapLayoutChange();
6555   return new_map;
6556 }
6557
6558
6559 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6560                                 PropertyNormalizationMode mode) {
6561   int new_instance_size = map->instance_size();
6562   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6563     new_instance_size -= map->inobject_properties() * kPointerSize;
6564   }
6565
6566   Handle<Map> result = RawCopy(map, new_instance_size);
6567
6568   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6569     result->set_inobject_properties(map->inobject_properties());
6570   }
6571
6572   result->set_dictionary_map(true);
6573   result->set_migration_target(false);
6574
6575 #ifdef VERIFY_HEAP
6576   if (FLAG_verify_heap) result->DictionaryMapVerify();
6577 #endif
6578
6579   return result;
6580 }
6581
6582
6583 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6584   Handle<Map> result = RawCopy(map, map->instance_size());
6585
6586   // Please note instance_type and instance_size are set when allocated.
6587   result->set_inobject_properties(map->inobject_properties());
6588   result->set_unused_property_fields(map->unused_property_fields());
6589
6590   result->ClearCodeCache(map->GetHeap());
6591   map->NotifyLeafMapLayoutChange();
6592   return result;
6593 }
6594
6595
6596 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6597                                  Handle<DescriptorArray> descriptors,
6598                                  Descriptor* descriptor) {
6599   // Sanity check. This path is only to be taken if the map owns its descriptor
6600   // array, implying that its NumberOfOwnDescriptors equals the number of
6601   // descriptors in the descriptor array.
6602   DCHECK(map->NumberOfOwnDescriptors() ==
6603          map->instance_descriptors()->number_of_descriptors());
6604
6605   Handle<Map> result = CopyDropDescriptors(map);
6606   Handle<Name> name = descriptor->GetKey();
6607
6608   // Ensure there's space for the new descriptor in the shared descriptor array.
6609   if (descriptors->NumberOfSlackDescriptors() == 0) {
6610     int old_size = descriptors->number_of_descriptors();
6611     if (old_size == 0) {
6612       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6613     } else {
6614       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
6615       EnsureDescriptorSlack(map, slack);
6616       descriptors = handle(map->instance_descriptors());
6617     }
6618   }
6619
6620   Handle<LayoutDescriptor> layout_descriptor =
6621       FLAG_unbox_double_fields
6622           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
6623           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
6624
6625   {
6626     DisallowHeapAllocation no_gc;
6627     descriptors->Append(descriptor);
6628     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6629   }
6630
6631   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6632   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6633
6634   return result;
6635 }
6636
6637
6638 #if TRACE_MAPS
6639
6640 // static
6641 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
6642   if (FLAG_trace_maps) {
6643     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
6644            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
6645     name->NameShortPrint();
6646     PrintF(" ]\n");
6647   }
6648 }
6649
6650
6651 // static
6652 void Map::TraceAllTransitions(Map* map) {
6653   Object* transitions = map->raw_transitions();
6654   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
6655   for (int i = -0; i < num_transitions; ++i) {
6656     Map* target = TransitionArray::GetTarget(transitions, i);
6657     Name* key = TransitionArray::GetKey(transitions, i);
6658     Map::TraceTransition("Transition", map, target, key);
6659     Map::TraceAllTransitions(target);
6660   }
6661 }
6662
6663 #endif  // TRACE_MAPS
6664
6665
6666 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
6667                             Handle<Name> name, SimpleTransitionFlag flag) {
6668   parent->set_owns_descriptors(false);
6669   if (parent->is_prototype_map()) {
6670     DCHECK(child->is_prototype_map());
6671 #if TRACE_MAPS
6672     Map::TraceTransition("NoTransition", *parent, *child, *name);
6673 #endif
6674   } else {
6675     TransitionArray::Insert(parent, name, child, flag);
6676 #if TRACE_MAPS
6677     Map::TraceTransition("Transition", *parent, *child, *name);
6678 #endif
6679   }
6680 }
6681
6682
6683 Handle<Map> Map::CopyReplaceDescriptors(
6684     Handle<Map> map, Handle<DescriptorArray> descriptors,
6685     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
6686     MaybeHandle<Name> maybe_name, const char* reason,
6687     SimpleTransitionFlag simple_flag) {
6688   DCHECK(descriptors->IsSortedNoDuplicates());
6689
6690   Handle<Map> result = CopyDropDescriptors(map);
6691
6692   if (!map->is_prototype_map()) {
6693     if (flag == INSERT_TRANSITION &&
6694         TransitionArray::CanHaveMoreTransitions(map)) {
6695       result->InitializeDescriptors(*descriptors, *layout_descriptor);
6696
6697       Handle<Name> name;
6698       CHECK(maybe_name.ToHandle(&name));
6699       ConnectTransition(map, result, name, simple_flag);
6700     } else {
6701       int length = descriptors->number_of_descriptors();
6702       for (int i = 0; i < length; i++) {
6703         descriptors->SetRepresentation(i, Representation::Tagged());
6704         if (descriptors->GetDetails(i).type() == DATA) {
6705           descriptors->SetValue(i, HeapType::Any());
6706         }
6707       }
6708       result->InitializeDescriptors(*descriptors,
6709                                     LayoutDescriptor::FastPointerLayout());
6710     }
6711   } else {
6712     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6713   }
6714 #if TRACE_MAPS
6715   if (FLAG_trace_maps &&
6716       // Mirror conditions above that did not call ConnectTransition().
6717       (map->is_prototype_map() ||
6718        !(flag == INSERT_TRANSITION &&
6719          TransitionArray::CanHaveMoreTransitions(map)))) {
6720     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
6721            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
6722            reason);
6723   }
6724 #endif
6725
6726   return result;
6727 }
6728
6729
6730 // Since this method is used to rewrite an existing transition tree, it can
6731 // always insert transitions without checking.
6732 Handle<Map> Map::CopyInstallDescriptors(
6733     Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
6734     Handle<LayoutDescriptor> full_layout_descriptor) {
6735   DCHECK(descriptors->IsSortedNoDuplicates());
6736
6737   Handle<Map> result = CopyDropDescriptors(map);
6738
6739   result->set_instance_descriptors(*descriptors);
6740   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6741
6742   int unused_property_fields = map->unused_property_fields();
6743   PropertyDetails details = descriptors->GetDetails(new_descriptor);
6744   if (details.location() == kField) {
6745     unused_property_fields = map->unused_property_fields() - 1;
6746     if (unused_property_fields < 0) {
6747       unused_property_fields += JSObject::kFieldsAdded;
6748     }
6749   }
6750   result->set_unused_property_fields(unused_property_fields);
6751
6752   if (FLAG_unbox_double_fields) {
6753     Handle<LayoutDescriptor> layout_descriptor =
6754         LayoutDescriptor::AppendIfFastOrUseFull(map, details,
6755                                                 full_layout_descriptor);
6756     result->set_layout_descriptor(*layout_descriptor);
6757 #ifdef VERIFY_HEAP
6758     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
6759     if (FLAG_verify_heap) {
6760       CHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6761     }
6762 #else
6763     SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6764 #endif
6765     result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
6766   }
6767
6768   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6769   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6770
6771   return result;
6772 }
6773
6774
6775 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
6776                                     TransitionFlag flag) {
6777   Map* maybe_elements_transition_map = NULL;
6778   if (flag == INSERT_TRANSITION) {
6779     maybe_elements_transition_map = map->ElementsTransitionMap();
6780     DCHECK(
6781         maybe_elements_transition_map == NULL ||
6782         ((maybe_elements_transition_map->elements_kind() ==
6783               DICTIONARY_ELEMENTS ||
6784           IsExternalArrayElementsKind(
6785               maybe_elements_transition_map->elements_kind())) &&
6786          (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind))));
6787     DCHECK(!IsFastElementsKind(kind) ||
6788            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
6789     DCHECK(kind != map->elements_kind());
6790   }
6791
6792   bool insert_transition = flag == INSERT_TRANSITION &&
6793                            TransitionArray::CanHaveMoreTransitions(map) &&
6794                            maybe_elements_transition_map == NULL;
6795
6796   if (insert_transition) {
6797     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
6798     new_map->set_elements_kind(kind);
6799
6800     Isolate* isolate = map->GetIsolate();
6801     Handle<Name> name = isolate->factory()->elements_transition_symbol();
6802     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6803     return new_map;
6804   }
6805
6806   // Create a new free-floating map only if we are not allowed to store it.
6807   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
6808   new_map->set_elements_kind(kind);
6809   return new_map;
6810 }
6811
6812
6813 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
6814   DCHECK(!map->is_observed());
6815
6816   Isolate* isolate = map->GetIsolate();
6817
6818   bool insert_transition =
6819       TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
6820
6821   if (insert_transition) {
6822     Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
6823     new_map->set_is_observed();
6824
6825     Handle<Name> name = isolate->factory()->observed_symbol();
6826     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6827     return new_map;
6828   }
6829
6830   // Create a new free-floating map only if we are not allowed to store it.
6831   Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
6832   new_map->set_is_observed();
6833   return new_map;
6834 }
6835
6836
6837 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
6838   DCHECK(!map->is_prototype_map());
6839   Handle<Map> new_map = CopyDropDescriptors(map);
6840
6841   if (map->owns_descriptors()) {
6842     // In case the map owned its own descriptors, share the descriptors and
6843     // transfer ownership to the new map.
6844     // The properties did not change, so reuse descriptors.
6845     new_map->InitializeDescriptors(map->instance_descriptors(),
6846                                    map->GetLayoutDescriptor());
6847   } else {
6848     // In case the map did not own its own descriptors, a split is forced by
6849     // copying the map; creating a new descriptor array cell.
6850     Handle<DescriptorArray> descriptors(map->instance_descriptors());
6851     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6852     Handle<DescriptorArray> new_descriptors =
6853         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6854     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6855                                                    map->GetIsolate());
6856     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
6857   }
6858
6859 #if TRACE_MAPS
6860   if (FLAG_trace_maps) {
6861     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
6862            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
6863            reason);
6864   }
6865 #endif
6866
6867   return new_map;
6868 }
6869
6870
6871 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
6872   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6873   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6874   Handle<DescriptorArray> new_descriptors =
6875       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6876   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6877                                                  map->GetIsolate());
6878   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
6879                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
6880                                 SPECIAL_TRANSITION);
6881 }
6882
6883
6884 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
6885   Handle<Map> copy =
6886       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
6887
6888   // Check that we do not overflow the instance size when adding the extra
6889   // inobject properties. If the instance size overflows, we allocate as many
6890   // properties as we can as inobject properties.
6891   int max_extra_properties =
6892       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
6893
6894   if (inobject_properties > max_extra_properties) {
6895     inobject_properties = max_extra_properties;
6896   }
6897
6898   int new_instance_size =
6899       JSObject::kHeaderSize + kPointerSize * inobject_properties;
6900
6901   // Adjust the map with the extra inobject properties.
6902   copy->set_inobject_properties(inobject_properties);
6903   copy->set_unused_property_fields(inobject_properties);
6904   copy->set_instance_size(new_instance_size);
6905   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
6906   return copy;
6907 }
6908
6909
6910 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
6911                                           PropertyAttributes attrs_to_add,
6912                                           Handle<Symbol> transition_marker,
6913                                           const char* reason) {
6914   int num_descriptors = map->NumberOfOwnDescriptors();
6915   Isolate* isolate = map->GetIsolate();
6916   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
6917       handle(map->instance_descriptors(), isolate), num_descriptors,
6918       attrs_to_add);
6919   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6920                                                  isolate);
6921   Handle<Map> new_map = CopyReplaceDescriptors(
6922       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
6923       transition_marker, reason, SPECIAL_TRANSITION);
6924   new_map->set_is_extensible(false);
6925   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6926   return new_map;
6927 }
6928
6929
6930 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) {
6931   DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
6932   DCHECK(map->IsJSProxyMap());
6933
6934   Isolate* isolate = map->GetIsolate();
6935
6936   // Allocate fresh map.
6937   // TODO(rossberg): Once we optimize proxies, cache these maps.
6938   Handle<Map> new_map = isolate->factory()->NewMap(type, size);
6939
6940   Handle<Object> prototype(map->prototype(), isolate);
6941   Map::SetPrototype(new_map, prototype);
6942
6943   map->NotifyLeafMapLayoutChange();
6944
6945   return new_map;
6946 }
6947
6948
6949 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
6950   PropertyDetails details = GetDetails(descriptor);
6951   switch (details.type()) {
6952     case DATA:
6953       return value->FitsRepresentation(details.representation()) &&
6954              GetFieldType(descriptor)->NowContains(value);
6955
6956     case DATA_CONSTANT:
6957       DCHECK(GetConstant(descriptor) != value ||
6958              value->FitsRepresentation(details.representation()));
6959       return GetConstant(descriptor) == value;
6960
6961     case ACCESSOR:
6962     case ACCESSOR_CONSTANT:
6963       return false;
6964   }
6965
6966   UNREACHABLE();
6967   return false;
6968 }
6969
6970
6971 // static
6972 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
6973                                         Handle<Object> value) {
6974   // Dictionaries can store any property value.
6975   if (map->is_dictionary_map()) return map;
6976
6977   // Migrate to the newest map before storing the property.
6978   map = Update(map);
6979
6980   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6981
6982   if (descriptors->CanHoldValue(descriptor, *value)) return map;
6983
6984   Isolate* isolate = map->GetIsolate();
6985   PropertyAttributes attributes =
6986       descriptors->GetDetails(descriptor).attributes();
6987   Representation representation = value->OptimalRepresentation();
6988   Handle<HeapType> type = value->OptimalType(isolate, representation);
6989
6990   return ReconfigureProperty(map, descriptor, kData, attributes, representation,
6991                              type, FORCE_FIELD);
6992 }
6993
6994
6995 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
6996                                           Handle<Object> value,
6997                                           PropertyAttributes attributes,
6998                                           StoreFromKeyed store_mode) {
6999   // Dictionary maps can always have additional data properties.
7000   if (map->is_dictionary_map()) return map;
7001
7002   // Migrate to the newest map before storing the property.
7003   map = Update(map);
7004
7005   Map* maybe_transition =
7006       TransitionArray::SearchTransition(*map, kData, *name, attributes);
7007   if (maybe_transition != NULL) {
7008     Handle<Map> transition(maybe_transition);
7009     int descriptor = transition->LastAdded();
7010
7011     DCHECK_EQ(attributes, transition->instance_descriptors()
7012                               ->GetDetails(descriptor)
7013                               .attributes());
7014
7015     return Map::PrepareForDataProperty(transition, descriptor, value);
7016   }
7017
7018   TransitionFlag flag = INSERT_TRANSITION;
7019   MaybeHandle<Map> maybe_map;
7020   if (value->IsJSFunction()) {
7021     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7022   } else if (!map->TooManyFastProperties(store_mode)) {
7023     Isolate* isolate = name->GetIsolate();
7024     Representation representation = value->OptimalRepresentation();
7025     Handle<HeapType> type = value->OptimalType(isolate, representation);
7026     maybe_map =
7027         Map::CopyWithField(map, name, type, attributes, representation, flag);
7028   }
7029
7030   Handle<Map> result;
7031   if (!maybe_map.ToHandle(&result)) {
7032 #if TRACE_MAPS
7033     if (FLAG_trace_maps) {
7034       Vector<char> name_buffer = Vector<char>::New(100);
7035       name->NameShortPrint(name_buffer);
7036       Vector<char> buffer = Vector<char>::New(128);
7037       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
7038       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
7039     }
7040 #endif
7041     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
7042                           "TooManyFastProperties");
7043   }
7044
7045   return result;
7046 }
7047
7048
7049 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
7050                                              PropertyKind kind,
7051                                              PropertyAttributes attributes) {
7052   // Dictionaries have to be reconfigured in-place.
7053   DCHECK(!map->is_dictionary_map());
7054
7055   if (!map->GetBackPointer()->IsMap()) {
7056     // There is no benefit from reconstructing transition tree for maps without
7057     // back pointers.
7058     return CopyGeneralizeAllRepresentations(
7059         map, descriptor, FORCE_FIELD, kind, attributes,
7060         "GenAll_AttributesMismatchProtoMap");
7061   }
7062
7063   if (FLAG_trace_generalization) {
7064     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
7065   }
7066
7067   Isolate* isolate = map->GetIsolate();
7068   Handle<Map> new_map = ReconfigureProperty(
7069       map, descriptor, kind, attributes, Representation::None(),
7070       HeapType::None(isolate), FORCE_FIELD);
7071   return new_map;
7072 }
7073
7074
7075 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
7076                                               Handle<Name> name,
7077                                               AccessorComponent component,
7078                                               Handle<Object> accessor,
7079                                               PropertyAttributes attributes) {
7080   Isolate* isolate = name->GetIsolate();
7081
7082   // Dictionary maps can always have additional data properties.
7083   if (map->is_dictionary_map()) return map;
7084
7085   // Migrate to the newest map before transitioning to the new property.
7086   map = Update(map);
7087
7088   PropertyNormalizationMode mode = map->is_prototype_map()
7089                                        ? KEEP_INOBJECT_PROPERTIES
7090                                        : CLEAR_INOBJECT_PROPERTIES;
7091
7092   Map* maybe_transition =
7093       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
7094   if (maybe_transition != NULL) {
7095     Handle<Map> transition(maybe_transition, isolate);
7096     DescriptorArray* descriptors = transition->instance_descriptors();
7097     int descriptor = transition->LastAdded();
7098     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7099
7100     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7101     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7102
7103     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7104     if (!maybe_pair->IsAccessorPair()) {
7105       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
7106     }
7107
7108     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
7109     if (pair->get(component) != *accessor) {
7110       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
7111     }
7112
7113     return transition;
7114   }
7115
7116   Handle<AccessorPair> pair;
7117   DescriptorArray* old_descriptors = map->instance_descriptors();
7118   int descriptor = old_descriptors->SearchWithCache(*name, *map);
7119   if (descriptor != DescriptorArray::kNotFound) {
7120     if (descriptor != map->LastAdded()) {
7121       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
7122     }
7123     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
7124     if (old_details.type() != ACCESSOR_CONSTANT) {
7125       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
7126     }
7127
7128     if (old_details.attributes() != attributes) {
7129       return Map::Normalize(map, mode, "AccessorsWithAttributes");
7130     }
7131
7132     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
7133     if (!maybe_pair->IsAccessorPair()) {
7134       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
7135     }
7136
7137     Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
7138     if (current == *accessor) return map;
7139
7140     if (!current->IsTheHole()) {
7141       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
7142     }
7143
7144     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
7145   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
7146              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
7147     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
7148   } else {
7149     pair = isolate->factory()->NewAccessorPair();
7150   }
7151
7152   pair->set(component, *accessor);
7153   TransitionFlag flag = INSERT_TRANSITION;
7154   AccessorConstantDescriptor new_desc(name, pair, attributes);
7155   return Map::CopyInsertDescriptor(map, &new_desc, flag);
7156 }
7157
7158
7159 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7160                                    Descriptor* descriptor,
7161                                    TransitionFlag flag) {
7162   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7163
7164   // Ensure the key is unique.
7165   descriptor->KeyToUniqueName();
7166
7167   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
7168       TransitionArray::CanHaveMoreTransitions(map)) {
7169     return ShareDescriptor(map, descriptors, descriptor);
7170   }
7171
7172   int nof = map->NumberOfOwnDescriptors();
7173   Handle<DescriptorArray> new_descriptors =
7174       DescriptorArray::CopyUpTo(descriptors, nof, 1);
7175   new_descriptors->Append(descriptor);
7176
7177   Handle<LayoutDescriptor> new_layout_descriptor =
7178       FLAG_unbox_double_fields
7179           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
7180           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
7181
7182   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7183                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
7184                                 SIMPLE_PROPERTY_TRANSITION);
7185 }
7186
7187
7188 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7189                                       Descriptor* descriptor,
7190                                       TransitionFlag flag) {
7191   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7192
7193   // Ensure the key is unique.
7194   descriptor->KeyToUniqueName();
7195
7196   // We replace the key if it is already present.
7197   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7198   if (index != DescriptorArray::kNotFound) {
7199     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7200   }
7201   return CopyAddDescriptor(map, descriptor, flag);
7202 }
7203
7204
7205 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7206     Handle<DescriptorArray> desc,
7207     int enumeration_index,
7208     int slack) {
7209   return DescriptorArray::CopyUpToAddAttributes(
7210       desc, enumeration_index, NONE, slack);
7211 }
7212
7213
7214 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7215     Handle<DescriptorArray> desc,
7216     int enumeration_index,
7217     PropertyAttributes attributes,
7218     int slack) {
7219   if (enumeration_index + slack == 0) {
7220     return desc->GetIsolate()->factory()->empty_descriptor_array();
7221   }
7222
7223   int size = enumeration_index;
7224
7225   Handle<DescriptorArray> descriptors =
7226       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7227   DescriptorArray::WhitenessWitness witness(*descriptors);
7228
7229   if (attributes != NONE) {
7230     for (int i = 0; i < size; ++i) {
7231       Object* value = desc->GetValue(i);
7232       Name* key = desc->GetKey(i);
7233       PropertyDetails details = desc->GetDetails(i);
7234       // Bulk attribute changes never affect private properties.
7235       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7236         int mask = DONT_DELETE | DONT_ENUM;
7237         // READ_ONLY is an invalid attribute for JS setters/getters.
7238         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
7239           mask |= READ_ONLY;
7240         }
7241         details = details.CopyAddAttributes(
7242             static_cast<PropertyAttributes>(attributes & mask));
7243       }
7244       Descriptor inner_desc(
7245           handle(key), handle(value, desc->GetIsolate()), details);
7246       descriptors->Set(i, &inner_desc, witness);
7247     }
7248   } else {
7249     for (int i = 0; i < size; ++i) {
7250       descriptors->CopyFrom(i, *desc, witness);
7251     }
7252   }
7253
7254   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7255
7256   return descriptors;
7257 }
7258
7259
7260 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7261                                        Handle<DescriptorArray> descriptors,
7262                                        Descriptor* descriptor,
7263                                        int insertion_index,
7264                                        TransitionFlag flag) {
7265   // Ensure the key is unique.
7266   descriptor->KeyToUniqueName();
7267
7268   Handle<Name> key = descriptor->GetKey();
7269   DCHECK(*key == descriptors->GetKey(insertion_index));
7270
7271   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7272       descriptors, map->NumberOfOwnDescriptors());
7273
7274   new_descriptors->Replace(insertion_index, descriptor);
7275   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
7276       map, new_descriptors, new_descriptors->number_of_descriptors());
7277
7278   SimpleTransitionFlag simple_flag =
7279       (insertion_index == descriptors->number_of_descriptors() - 1)
7280           ? SIMPLE_PROPERTY_TRANSITION
7281           : PROPERTY_TRANSITION;
7282   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7283                                 flag, key, "CopyReplaceDescriptor",
7284                                 simple_flag);
7285 }
7286
7287
7288 void Map::UpdateCodeCache(Handle<Map> map,
7289                           Handle<Name> name,
7290                           Handle<Code> code) {
7291   Isolate* isolate = map->GetIsolate();
7292   HandleScope scope(isolate);
7293   // Allocate the code cache if not present.
7294   if (map->code_cache()->IsFixedArray()) {
7295     Handle<Object> result = isolate->factory()->NewCodeCache();
7296     map->set_code_cache(*result);
7297   }
7298
7299   // Update the code cache.
7300   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7301   CodeCache::Update(code_cache, name, code);
7302 }
7303
7304
7305 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7306   // Do a lookup if a code cache exists.
7307   if (!code_cache()->IsFixedArray()) {
7308     return CodeCache::cast(code_cache())->Lookup(name, flags);
7309   } else {
7310     return GetHeap()->undefined_value();
7311   }
7312 }
7313
7314
7315 int Map::IndexInCodeCache(Object* name, Code* code) {
7316   // Get the internal index if a code cache exists.
7317   if (!code_cache()->IsFixedArray()) {
7318     return CodeCache::cast(code_cache())->GetIndex(name, code);
7319   }
7320   return -1;
7321 }
7322
7323
7324 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7325   // No GC is supposed to happen between a call to IndexInCodeCache and
7326   // RemoveFromCodeCache so the code cache must be there.
7327   DCHECK(!code_cache()->IsFixedArray());
7328   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7329 }
7330
7331
7332 void CodeCache::Update(
7333     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7334   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7335   // a large number and therefore they need to go into a hash table. They are
7336   // used to load global properties from cells.
7337   if (code->type() == Code::NORMAL) {
7338     // Make sure that a hash table is allocated for the normal load code cache.
7339     if (code_cache->normal_type_cache()->IsUndefined()) {
7340       Handle<Object> result =
7341           CodeCacheHashTable::New(code_cache->GetIsolate(),
7342                                   CodeCacheHashTable::kInitialSize);
7343       code_cache->set_normal_type_cache(*result);
7344     }
7345     UpdateNormalTypeCache(code_cache, name, code);
7346   } else {
7347     DCHECK(code_cache->default_cache()->IsFixedArray());
7348     UpdateDefaultCache(code_cache, name, code);
7349   }
7350 }
7351
7352
7353 void CodeCache::UpdateDefaultCache(
7354     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7355   // When updating the default code cache we disregard the type encoded in the
7356   // flags. This allows call constant stubs to overwrite call field
7357   // stubs, etc.
7358   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7359
7360   // First check whether we can update existing code cache without
7361   // extending it.
7362   Handle<FixedArray> cache = handle(code_cache->default_cache());
7363   int length = cache->length();
7364   {
7365     DisallowHeapAllocation no_alloc;
7366     int deleted_index = -1;
7367     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7368       Object* key = cache->get(i);
7369       if (key->IsNull()) {
7370         if (deleted_index < 0) deleted_index = i;
7371         continue;
7372       }
7373       if (key->IsUndefined()) {
7374         if (deleted_index >= 0) i = deleted_index;
7375         cache->set(i + kCodeCacheEntryNameOffset, *name);
7376         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7377         return;
7378       }
7379       if (name->Equals(Name::cast(key))) {
7380         Code::Flags found =
7381             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7382         if (Code::RemoveTypeFromFlags(found) == flags) {
7383           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7384           return;
7385         }
7386       }
7387     }
7388
7389     // Reached the end of the code cache.  If there were deleted
7390     // elements, reuse the space for the first of them.
7391     if (deleted_index >= 0) {
7392       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7393       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7394       return;
7395     }
7396   }
7397
7398   // Extend the code cache with some new entries (at least one). Must be a
7399   // multiple of the entry size.
7400   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7401   new_length = new_length - new_length % kCodeCacheEntrySize;
7402   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7403   cache = FixedArray::CopySize(cache, new_length);
7404
7405   // Add the (name, code) pair to the new cache.
7406   cache->set(length + kCodeCacheEntryNameOffset, *name);
7407   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7408   code_cache->set_default_cache(*cache);
7409 }
7410
7411
7412 void CodeCache::UpdateNormalTypeCache(
7413     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7414   // Adding a new entry can cause a new cache to be allocated.
7415   Handle<CodeCacheHashTable> cache(
7416       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7417   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7418   code_cache->set_normal_type_cache(*new_cache);
7419 }
7420
7421
7422 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7423   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7424   if (result->IsCode()) {
7425     if (Code::cast(result)->flags() == flags) return result;
7426     return GetHeap()->undefined_value();
7427   }
7428   return LookupNormalTypeCache(name, flags);
7429 }
7430
7431
7432 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7433   FixedArray* cache = default_cache();
7434   int length = cache->length();
7435   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7436     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7437     // Skip deleted elements.
7438     if (key->IsNull()) continue;
7439     if (key->IsUndefined()) return key;
7440     if (name->Equals(Name::cast(key))) {
7441       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7442       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7443         return code;
7444       }
7445     }
7446   }
7447   return GetHeap()->undefined_value();
7448 }
7449
7450
7451 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7452   if (!normal_type_cache()->IsUndefined()) {
7453     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7454     return cache->Lookup(name, flags);
7455   } else {
7456     return GetHeap()->undefined_value();
7457   }
7458 }
7459
7460
7461 int CodeCache::GetIndex(Object* name, Code* code) {
7462   if (code->type() == Code::NORMAL) {
7463     if (normal_type_cache()->IsUndefined()) return -1;
7464     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7465     return cache->GetIndex(Name::cast(name), code->flags());
7466   }
7467
7468   FixedArray* array = default_cache();
7469   int len = array->length();
7470   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7471     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7472   }
7473   return -1;
7474 }
7475
7476
7477 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7478   if (code->type() == Code::NORMAL) {
7479     DCHECK(!normal_type_cache()->IsUndefined());
7480     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7481     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7482     cache->RemoveByIndex(index);
7483   } else {
7484     FixedArray* array = default_cache();
7485     DCHECK(array->length() >= index && array->get(index)->IsCode());
7486     // Use null instead of undefined for deleted elements to distinguish
7487     // deleted elements from unused elements.  This distinction is used
7488     // when looking up in the cache and when updating the cache.
7489     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7490     array->set_null(index - 1);  // Name.
7491     array->set_null(index);  // Code.
7492   }
7493 }
7494
7495
7496 // The key in the code cache hash table consists of the property name and the
7497 // code object. The actual match is on the name and the code flags. If a key
7498 // is created using the flags and not a code object it can only be used for
7499 // lookup not to create a new entry.
7500 class CodeCacheHashTableKey : public HashTableKey {
7501  public:
7502   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7503       : name_(name), flags_(flags), code_() { }
7504
7505   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7506       : name_(name), flags_(code->flags()), code_(code) { }
7507
7508   bool IsMatch(Object* other) override {
7509     if (!other->IsFixedArray()) return false;
7510     FixedArray* pair = FixedArray::cast(other);
7511     Name* name = Name::cast(pair->get(0));
7512     Code::Flags flags = Code::cast(pair->get(1))->flags();
7513     if (flags != flags_) {
7514       return false;
7515     }
7516     return name_->Equals(name);
7517   }
7518
7519   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7520     return name->Hash() ^ flags;
7521   }
7522
7523   uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
7524
7525   uint32_t HashForObject(Object* obj) override {
7526     FixedArray* pair = FixedArray::cast(obj);
7527     Name* name = Name::cast(pair->get(0));
7528     Code* code = Code::cast(pair->get(1));
7529     return NameFlagsHashHelper(name, code->flags());
7530   }
7531
7532   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7533     Handle<Code> code = code_.ToHandleChecked();
7534     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7535     pair->set(0, *name_);
7536     pair->set(1, *code);
7537     return pair;
7538   }
7539
7540  private:
7541   Handle<Name> name_;
7542   Code::Flags flags_;
7543   // TODO(jkummerow): We should be able to get by without this.
7544   MaybeHandle<Code> code_;
7545 };
7546
7547
7548 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7549   DisallowHeapAllocation no_alloc;
7550   CodeCacheHashTableKey key(handle(name), flags);
7551   int entry = FindEntry(&key);
7552   if (entry == kNotFound) return GetHeap()->undefined_value();
7553   return get(EntryToIndex(entry) + 1);
7554 }
7555
7556
7557 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
7558     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
7559   CodeCacheHashTableKey key(name, code);
7560
7561   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7562
7563   int entry = new_cache->FindInsertionEntry(key.Hash());
7564   Handle<Object> k = key.AsHandle(cache->GetIsolate());
7565
7566   new_cache->set(EntryToIndex(entry), *k);
7567   new_cache->set(EntryToIndex(entry) + 1, *code);
7568   new_cache->ElementAdded();
7569   return new_cache;
7570 }
7571
7572
7573 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7574   DisallowHeapAllocation no_alloc;
7575   CodeCacheHashTableKey key(handle(name), flags);
7576   int entry = FindEntry(&key);
7577   return (entry == kNotFound) ? -1 : entry;
7578 }
7579
7580
7581 void CodeCacheHashTable::RemoveByIndex(int index) {
7582   DCHECK(index >= 0);
7583   Heap* heap = GetHeap();
7584   set(EntryToIndex(index), heap->the_hole_value());
7585   set(EntryToIndex(index) + 1, heap->the_hole_value());
7586   ElementRemoved();
7587 }
7588
7589
7590 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
7591                                   MapHandleList* maps,
7592                                   Code::Flags flags,
7593                                   Handle<Code> code) {
7594   Isolate* isolate = code_cache->GetIsolate();
7595   if (code_cache->cache()->IsUndefined()) {
7596     Handle<PolymorphicCodeCacheHashTable> result =
7597         PolymorphicCodeCacheHashTable::New(
7598             isolate,
7599             PolymorphicCodeCacheHashTable::kInitialSize);
7600     code_cache->set_cache(*result);
7601   } else {
7602     // This entry shouldn't be contained in the cache yet.
7603     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7604                ->Lookup(maps, flags)->IsUndefined());
7605   }
7606   Handle<PolymorphicCodeCacheHashTable> hash_table =
7607       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7608   Handle<PolymorphicCodeCacheHashTable> new_cache =
7609       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7610   code_cache->set_cache(*new_cache);
7611 }
7612
7613
7614 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7615                                             Code::Flags flags) {
7616   if (!cache()->IsUndefined()) {
7617     PolymorphicCodeCacheHashTable* hash_table =
7618         PolymorphicCodeCacheHashTable::cast(cache());
7619     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7620   } else {
7621     return GetIsolate()->factory()->undefined_value();
7622   }
7623 }
7624
7625
7626 // Despite their name, object of this class are not stored in the actual
7627 // hash table; instead they're temporarily used for lookups. It is therefore
7628 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7629 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7630  public:
7631   // Callers must ensure that |maps| outlives the newly constructed object.
7632   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7633       : maps_(maps),
7634         code_flags_(code_flags) {}
7635
7636   bool IsMatch(Object* other) override {
7637     MapHandleList other_maps(kDefaultListAllocationSize);
7638     int other_flags;
7639     FromObject(other, &other_flags, &other_maps);
7640     if (code_flags_ != other_flags) return false;
7641     if (maps_->length() != other_maps.length()) return false;
7642     // Compare just the hashes first because it's faster.
7643     int this_hash = MapsHashHelper(maps_, code_flags_);
7644     int other_hash = MapsHashHelper(&other_maps, other_flags);
7645     if (this_hash != other_hash) return false;
7646
7647     // Full comparison: for each map in maps_, look for an equivalent map in
7648     // other_maps. This implementation is slow, but probably good enough for
7649     // now because the lists are short (<= 4 elements currently).
7650     for (int i = 0; i < maps_->length(); ++i) {
7651       bool match_found = false;
7652       for (int j = 0; j < other_maps.length(); ++j) {
7653         if (*(maps_->at(i)) == *(other_maps.at(j))) {
7654           match_found = true;
7655           break;
7656         }
7657       }
7658       if (!match_found) return false;
7659     }
7660     return true;
7661   }
7662
7663   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7664     uint32_t hash = code_flags;
7665     for (int i = 0; i < maps->length(); ++i) {
7666       hash ^= maps->at(i)->Hash();
7667     }
7668     return hash;
7669   }
7670
7671   uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
7672
7673   uint32_t HashForObject(Object* obj) override {
7674     MapHandleList other_maps(kDefaultListAllocationSize);
7675     int other_flags;
7676     FromObject(obj, &other_flags, &other_maps);
7677     return MapsHashHelper(&other_maps, other_flags);
7678   }
7679
7680   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7681     // The maps in |maps_| must be copied to a newly allocated FixedArray,
7682     // both because the referenced MapList is short-lived, and because C++
7683     // objects can't be stored in the heap anyway.
7684     Handle<FixedArray> list =
7685         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
7686     list->set(0, Smi::FromInt(code_flags_));
7687     for (int i = 0; i < maps_->length(); ++i) {
7688       list->set(i + 1, *maps_->at(i));
7689     }
7690     return list;
7691   }
7692
7693  private:
7694   static MapHandleList* FromObject(Object* obj,
7695                                    int* code_flags,
7696                                    MapHandleList* maps) {
7697     FixedArray* list = FixedArray::cast(obj);
7698     maps->Rewind(0);
7699     *code_flags = Smi::cast(list->get(0))->value();
7700     for (int i = 1; i < list->length(); ++i) {
7701       maps->Add(Handle<Map>(Map::cast(list->get(i))));
7702     }
7703     return maps;
7704   }
7705
7706   MapHandleList* maps_;  // weak.
7707   int code_flags_;
7708   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7709 };
7710
7711
7712 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
7713                                               int code_kind) {
7714   DisallowHeapAllocation no_alloc;
7715   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7716   int entry = FindEntry(&key);
7717   if (entry == kNotFound) return GetHeap()->undefined_value();
7718   return get(EntryToIndex(entry) + 1);
7719 }
7720
7721
7722 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
7723       Handle<PolymorphicCodeCacheHashTable> hash_table,
7724       MapHandleList* maps,
7725       int code_kind,
7726       Handle<Code> code) {
7727   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7728   Handle<PolymorphicCodeCacheHashTable> cache =
7729       EnsureCapacity(hash_table, 1, &key);
7730   int entry = cache->FindInsertionEntry(key.Hash());
7731
7732   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
7733   cache->set(EntryToIndex(entry), *obj);
7734   cache->set(EntryToIndex(entry) + 1, *code);
7735   cache->ElementAdded();
7736   return cache;
7737 }
7738
7739
7740 void FixedArray::Shrink(int new_length) {
7741   DCHECK(0 <= new_length && new_length <= length());
7742   if (new_length < length()) {
7743     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
7744         this, length() - new_length);
7745   }
7746 }
7747
7748
7749 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
7750     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
7751   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
7752   ElementsAccessor* accessor = array->GetElementsAccessor();
7753   Handle<FixedArray> result =
7754       accessor->AddElementsToFixedArray(array, content, filter);
7755
7756 #ifdef ENABLE_SLOW_DCHECKS
7757   if (FLAG_enable_slow_asserts) {
7758     DisallowHeapAllocation no_allocation;
7759     for (int i = 0; i < result->length(); i++) {
7760       Object* current = result->get(i);
7761       DCHECK(current->IsNumber() || current->IsName());
7762     }
7763   }
7764 #endif
7765   return result;
7766 }
7767
7768
7769 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
7770                                                 Handle<FixedArray> second) {
7771   if (second->length() == 0) return first;
7772   if (first->length() == 0) return second;
7773   Isolate* isolate = first->GetIsolate();
7774   Handle<FixedArray> result =
7775       isolate->factory()->NewFixedArray(first->length() + second->length());
7776   for (int i = 0; i < first->length(); i++) {
7777     result->set(i, first->get(i));
7778   }
7779   int pos = first->length();
7780   for (int j = 0; j < second->length(); j++) {
7781     Object* current = second->get(j);
7782     int i;
7783     for (i = 0; i < first->length(); i++) {
7784       if (current->KeyEquals(first->get(i))) break;
7785     }
7786     if (i == first->length()) {
7787       result->set(pos++, current);
7788     }
7789   }
7790
7791   result->Shrink(pos);
7792   return result;
7793 }
7794
7795
7796 Handle<FixedArray> FixedArray::CopySize(
7797     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
7798   Isolate* isolate = array->GetIsolate();
7799   if (new_length == 0) return isolate->factory()->empty_fixed_array();
7800   Handle<FixedArray> result =
7801       isolate->factory()->NewFixedArray(new_length, pretenure);
7802   // Copy the content
7803   DisallowHeapAllocation no_gc;
7804   int len = array->length();
7805   if (new_length < len) len = new_length;
7806   // We are taking the map from the old fixed array so the map is sure to
7807   // be an immortal immutable object.
7808   result->set_map_no_write_barrier(array->map());
7809   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7810   for (int i = 0; i < len; i++) {
7811     result->set(i, array->get(i), mode);
7812   }
7813   return result;
7814 }
7815
7816
7817 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7818   DisallowHeapAllocation no_gc;
7819   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7820   for (int index = 0; index < len; index++) {
7821     dest->set(dest_pos+index, get(pos+index), mode);
7822   }
7823 }
7824
7825
7826 #ifdef DEBUG
7827 bool FixedArray::IsEqualTo(FixedArray* other) {
7828   if (length() != other->length()) return false;
7829   for (int i = 0 ; i < length(); ++i) {
7830     if (get(i) != other->get(i)) return false;
7831   }
7832   return true;
7833 }
7834 #endif
7835
7836
7837 // static
7838 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
7839                          Handle<HeapObject> value) {
7840   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
7841   Handle<WeakCell> cell =
7842       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
7843                      : array->GetIsolate()->factory()->NewWeakCell(value);
7844   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
7845   if (FLAG_trace_weak_arrays) {
7846     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
7847   }
7848   array->set_last_used_index(index);
7849 }
7850
7851
7852 // static
7853 Handle<WeakFixedArray> WeakFixedArray::Add(
7854     Handle<Object> maybe_array, Handle<HeapObject> value,
7855     SearchForDuplicates search_for_duplicates, bool* was_present) {
7856   Handle<WeakFixedArray> array =
7857       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
7858           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
7859           : Handle<WeakFixedArray>::cast(maybe_array);
7860   if (was_present != NULL) *was_present = false;
7861   if (search_for_duplicates == kAddIfNotFound) {
7862     for (int i = 0; i < array->Length(); ++i) {
7863       if (array->Get(i) == *value) {
7864         if (was_present != NULL) *was_present = true;
7865         return array;
7866       }
7867     }
7868 #if 0  // Enable this if you want to check your search_for_duplicates flags.
7869   } else {
7870     for (int i = 0; i < array->Length(); ++i) {
7871       DCHECK_NE(*value, array->Get(i));
7872     }
7873 #endif
7874   }
7875
7876   // Try to store the new entry if there's room. Optimize for consecutive
7877   // accesses.
7878   int first_index = array->last_used_index();
7879   if (array->Length() > 0) {
7880     for (int i = first_index;;) {
7881       if (array->IsEmptySlot((i))) {
7882         WeakFixedArray::Set(array, i, value);
7883         return array;
7884       }
7885       if (FLAG_trace_weak_arrays) {
7886         PrintF("[WeakFixedArray: searching for free slot]\n");
7887       }
7888       i = (i + 1) % array->Length();
7889       if (i == first_index) break;
7890     }
7891   }
7892
7893   // No usable slot found, grow the array.
7894   int new_length =
7895       array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4;
7896   Handle<WeakFixedArray> new_array =
7897       Allocate(array->GetIsolate(), new_length, array);
7898   if (FLAG_trace_weak_arrays) {
7899     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
7900   }
7901   WeakFixedArray::Set(new_array, array->Length(), value);
7902   return new_array;
7903 }
7904
7905
7906 void WeakFixedArray::Compact() {
7907   FixedArray* array = FixedArray::cast(this);
7908   int new_length = kFirstIndex;
7909   for (int i = kFirstIndex; i < array->length(); i++) {
7910     Object* element = array->get(i);
7911     if (element->IsSmi()) continue;
7912     if (WeakCell::cast(element)->cleared()) continue;
7913     array->set(new_length++, element);
7914   }
7915   array->Shrink(new_length);
7916   set_last_used_index(0);
7917 }
7918
7919
7920 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
7921   if (Length() == 0) return false;
7922   // Optimize for the most recently added element to be removed again.
7923   int first_index = last_used_index();
7924   for (int i = first_index;;) {
7925     if (Get(i) == *value) {
7926       Clear(i);
7927       // Users of WeakFixedArray should make sure that there are no duplicates,
7928       // they can use Add(..., kAddIfNotFound) if necessary.
7929       return true;
7930     }
7931     i = (i + 1) % Length();
7932     if (i == first_index) return false;
7933   }
7934   UNREACHABLE();
7935 }
7936
7937
7938 // static
7939 Handle<WeakFixedArray> WeakFixedArray::Allocate(
7940     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
7941   DCHECK(0 <= size);
7942   Handle<FixedArray> result =
7943       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
7944   Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
7945   if (initialize_from.is_null()) {
7946     for (int i = 0; i < result->length(); ++i) {
7947       result->set(i, Smi::FromInt(0));
7948     }
7949   } else {
7950     DCHECK(initialize_from->Length() <= size);
7951     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
7952     int target_index = kFirstIndex;
7953     for (int source_index = kFirstIndex; source_index < raw_source->length();
7954          ++source_index) {
7955       // The act of allocating might have caused entries in the source array
7956       // to be cleared. Copy only what's needed.
7957       if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
7958       result->set(target_index++, raw_source->get(source_index));
7959     }
7960     casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
7961     for (; target_index < result->length(); ++target_index) {
7962       result->set(target_index, Smi::FromInt(0));
7963     }
7964   }
7965   return casted_result;
7966 }
7967
7968
7969 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
7970                                  AddMode mode) {
7971   int length = array->Length();
7972   array = EnsureSpace(array, length + 1);
7973   if (mode == kReloadLengthAfterAllocation) {
7974     DCHECK(array->Length() <= length);
7975     length = array->Length();
7976   }
7977   array->Set(length, *obj);
7978   array->SetLength(length + 1);
7979   return array;
7980 }
7981
7982
7983 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
7984                                  Handle<Object> obj2, AddMode mode) {
7985   int length = array->Length();
7986   array = EnsureSpace(array, length + 2);
7987   if (mode == kReloadLengthAfterAllocation) {
7988     length = array->Length();
7989   }
7990   array->Set(length, *obj1);
7991   array->Set(length + 1, *obj2);
7992   array->SetLength(length + 2);
7993   return array;
7994 }
7995
7996
7997 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
7998   int capacity = array->length();
7999   bool empty = (capacity == 0);
8000   if (capacity < kFirstIndex + length) {
8001     capacity = kFirstIndex + length;
8002     capacity = capacity + Max(capacity / 2, 2);
8003     array = Handle<ArrayList>::cast(FixedArray::CopySize(array, capacity));
8004     if (empty) array->SetLength(0);
8005   }
8006   return array;
8007 }
8008
8009
8010 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8011                                                   int number_of_descriptors,
8012                                                   int slack) {
8013   DCHECK(0 <= number_of_descriptors);
8014   Factory* factory = isolate->factory();
8015   // Do not use DescriptorArray::cast on incomplete object.
8016   int size = number_of_descriptors + slack;
8017   if (size == 0) return factory->empty_descriptor_array();
8018   // Allocate the array of keys.
8019   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8020
8021   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8022   result->set(kEnumCacheIndex, Smi::FromInt(0));
8023   return Handle<DescriptorArray>::cast(result);
8024 }
8025
8026
8027 void DescriptorArray::ClearEnumCache() {
8028   set(kEnumCacheIndex, Smi::FromInt(0));
8029 }
8030
8031
8032 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8033   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8034   Set(index, descriptor);
8035 }
8036
8037
8038 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8039                                    FixedArray* new_cache,
8040                                    Object* new_index_cache) {
8041   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8042   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8043   DCHECK(!IsEmpty());
8044   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8045   FixedArray::cast(bridge_storage)->
8046     set(kEnumCacheBridgeCacheIndex, new_cache);
8047   FixedArray::cast(bridge_storage)->
8048     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8049   set(kEnumCacheIndex, bridge_storage);
8050 }
8051
8052
8053 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8054                                const WhitenessWitness& witness) {
8055   Object* value = src->GetValue(index);
8056   PropertyDetails details = src->GetDetails(index);
8057   Descriptor desc(handle(src->GetKey(index)),
8058                   handle(value, src->GetIsolate()),
8059                   details);
8060   Set(index, &desc, witness);
8061 }
8062
8063
8064 // We need the whiteness witness since sort will reshuffle the entries in the
8065 // descriptor array. If the descriptor array were to be black, the shuffling
8066 // would move a slot that was already recorded as pointing into an evacuation
8067 // candidate. This would result in missing updates upon evacuation.
8068 void DescriptorArray::Sort() {
8069   // In-place heap sort.
8070   int len = number_of_descriptors();
8071   // Reset sorting since the descriptor array might contain invalid pointers.
8072   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8073   // Bottom-up max-heap construction.
8074   // Index of the last node with children
8075   const int max_parent_index = (len / 2) - 1;
8076   for (int i = max_parent_index; i >= 0; --i) {
8077     int parent_index = i;
8078     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8079     while (parent_index <= max_parent_index) {
8080       int child_index = 2 * parent_index + 1;
8081       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8082       if (child_index + 1 < len) {
8083         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8084         if (right_child_hash > child_hash) {
8085           child_index++;
8086           child_hash = right_child_hash;
8087         }
8088       }
8089       if (child_hash <= parent_hash) break;
8090       SwapSortedKeys(parent_index, child_index);
8091       // Now element at child_index could be < its children.
8092       parent_index = child_index;  // parent_hash remains correct.
8093     }
8094   }
8095
8096   // Extract elements and create sorted array.
8097   for (int i = len - 1; i > 0; --i) {
8098     // Put max element at the back of the array.
8099     SwapSortedKeys(0, i);
8100     // Shift down the new top element.
8101     int parent_index = 0;
8102     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8103     const int max_parent_index = (i / 2) - 1;
8104     while (parent_index <= max_parent_index) {
8105       int child_index = parent_index * 2 + 1;
8106       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8107       if (child_index + 1 < i) {
8108         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8109         if (right_child_hash > child_hash) {
8110           child_index++;
8111           child_hash = right_child_hash;
8112         }
8113       }
8114       if (child_hash <= parent_hash) break;
8115       SwapSortedKeys(parent_index, child_index);
8116       parent_index = child_index;
8117     }
8118   }
8119   DCHECK(IsSortedNoDuplicates());
8120 }
8121
8122
8123 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8124   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8125   copy->set_getter(pair->getter());
8126   copy->set_setter(pair->setter());
8127   return copy;
8128 }
8129
8130
8131 Object* AccessorPair::GetComponent(AccessorComponent component) {
8132   Object* accessor = get(component);
8133   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8134 }
8135
8136
8137 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8138     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
8139   return Handle<DeoptimizationInputData>::cast(
8140       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
8141                                         pretenure));
8142 }
8143
8144
8145 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8146     Isolate* isolate,
8147     int number_of_deopt_points,
8148     PretenureFlag pretenure) {
8149   Handle<FixedArray> result;
8150   if (number_of_deopt_points == 0) {
8151     result = isolate->factory()->empty_fixed_array();
8152   } else {
8153     result = isolate->factory()->NewFixedArray(
8154         LengthOfFixedArray(number_of_deopt_points), pretenure);
8155   }
8156   return Handle<DeoptimizationOutputData>::cast(result);
8157 }
8158
8159
8160 int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out,
8161                               CatchPrediction* prediction_out) {
8162   int innermost_handler = -1, innermost_start = -1;
8163   for (int i = 0; i < length(); i += kRangeEntrySize) {
8164     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
8165     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
8166     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
8167     int handler_offset = HandlerOffsetField::decode(handler_field);
8168     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
8169     int stack_depth = Smi::cast(get(i + kRangeDepthIndex))->value();
8170     if (pc_offset > start_offset && pc_offset <= end_offset) {
8171       DCHECK_NE(start_offset, innermost_start);
8172       if (start_offset < innermost_start) continue;
8173       innermost_handler = handler_offset;
8174       innermost_start = start_offset;
8175       *stack_depth_out = stack_depth;
8176       if (prediction_out) *prediction_out = prediction;
8177     }
8178   }
8179   return innermost_handler;
8180 }
8181
8182
8183 // TODO(turbofan): Make sure table is sorted and use binary search.
8184 int HandlerTable::LookupReturn(int pc_offset, CatchPrediction* prediction_out) {
8185   for (int i = 0; i < length(); i += kReturnEntrySize) {
8186     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
8187     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
8188     if (pc_offset == return_offset) {
8189       if (prediction_out) {
8190         *prediction_out = HandlerPredictionField::decode(handler_field);
8191       }
8192       return HandlerOffsetField::decode(handler_field);
8193     }
8194   }
8195   return -1;
8196 }
8197
8198
8199 #ifdef DEBUG
8200 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8201   if (IsEmpty()) return other->IsEmpty();
8202   if (other->IsEmpty()) return false;
8203   if (length() != other->length()) return false;
8204   for (int i = 0; i < length(); ++i) {
8205     if (get(i) != other->get(i)) return false;
8206   }
8207   return true;
8208 }
8209 #endif
8210
8211
8212 bool String::LooksValid() {
8213   if (!GetIsolate()->heap()->Contains(this)) return false;
8214   return true;
8215 }
8216
8217
8218 String::FlatContent String::GetFlatContent() {
8219   DCHECK(!AllowHeapAllocation::IsAllowed());
8220   int length = this->length();
8221   StringShape shape(this);
8222   String* string = this;
8223   int offset = 0;
8224   if (shape.representation_tag() == kConsStringTag) {
8225     ConsString* cons = ConsString::cast(string);
8226     if (cons->second()->length() != 0) {
8227       return FlatContent();
8228     }
8229     string = cons->first();
8230     shape = StringShape(string);
8231   }
8232   if (shape.representation_tag() == kSlicedStringTag) {
8233     SlicedString* slice = SlicedString::cast(string);
8234     offset = slice->offset();
8235     string = slice->parent();
8236     shape = StringShape(string);
8237     DCHECK(shape.representation_tag() != kConsStringTag &&
8238            shape.representation_tag() != kSlicedStringTag);
8239   }
8240   if (shape.encoding_tag() == kOneByteStringTag) {
8241     const uint8_t* start;
8242     if (shape.representation_tag() == kSeqStringTag) {
8243       start = SeqOneByteString::cast(string)->GetChars();
8244     } else {
8245       start = ExternalOneByteString::cast(string)->GetChars();
8246     }
8247     return FlatContent(start + offset, length);
8248   } else {
8249     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8250     const uc16* start;
8251     if (shape.representation_tag() == kSeqStringTag) {
8252       start = SeqTwoByteString::cast(string)->GetChars();
8253     } else {
8254       start = ExternalTwoByteString::cast(string)->GetChars();
8255     }
8256     return FlatContent(start + offset, length);
8257   }
8258 }
8259
8260
8261 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8262                                                 RobustnessFlag robust_flag,
8263                                                 int offset, int length,
8264                                                 int* length_return) {
8265   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8266     return base::SmartArrayPointer<char>(NULL);
8267   }
8268   // Negative length means the to the end of the string.
8269   if (length < 0) length = kMaxInt - offset;
8270
8271   // Compute the size of the UTF-8 string. Start at the specified offset.
8272   StringCharacterStream stream(this, offset);
8273   int character_position = offset;
8274   int utf8_bytes = 0;
8275   int last = unibrow::Utf16::kNoPreviousCharacter;
8276   while (stream.HasMore() && character_position++ < offset + length) {
8277     uint16_t character = stream.GetNext();
8278     utf8_bytes += unibrow::Utf8::Length(character, last);
8279     last = character;
8280   }
8281
8282   if (length_return) {
8283     *length_return = utf8_bytes;
8284   }
8285
8286   char* result = NewArray<char>(utf8_bytes + 1);
8287
8288   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8289   stream.Reset(this, offset);
8290   character_position = offset;
8291   int utf8_byte_position = 0;
8292   last = unibrow::Utf16::kNoPreviousCharacter;
8293   while (stream.HasMore() && character_position++ < offset + length) {
8294     uint16_t character = stream.GetNext();
8295     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8296       character = ' ';
8297     }
8298     utf8_byte_position +=
8299         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8300     last = character;
8301   }
8302   result[utf8_byte_position] = 0;
8303   return base::SmartArrayPointer<char>(result);
8304 }
8305
8306
8307 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8308                                                 RobustnessFlag robust_flag,
8309                                                 int* length_return) {
8310   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8311 }
8312
8313
8314 const uc16* String::GetTwoByteData(unsigned start) {
8315   DCHECK(!IsOneByteRepresentationUnderneath());
8316   switch (StringShape(this).representation_tag()) {
8317     case kSeqStringTag:
8318       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8319     case kExternalStringTag:
8320       return ExternalTwoByteString::cast(this)->
8321         ExternalTwoByteStringGetData(start);
8322     case kSlicedStringTag: {
8323       SlicedString* slice = SlicedString::cast(this);
8324       return slice->parent()->GetTwoByteData(start + slice->offset());
8325     }
8326     case kConsStringTag:
8327       UNREACHABLE();
8328       return NULL;
8329   }
8330   UNREACHABLE();
8331   return NULL;
8332 }
8333
8334
8335 base::SmartArrayPointer<uc16> String::ToWideCString(
8336     RobustnessFlag robust_flag) {
8337   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8338     return base::SmartArrayPointer<uc16>();
8339   }
8340   StringCharacterStream stream(this);
8341
8342   uc16* result = NewArray<uc16>(length() + 1);
8343
8344   int i = 0;
8345   while (stream.HasMore()) {
8346     uint16_t character = stream.GetNext();
8347     result[i++] = character;
8348   }
8349   result[i] = 0;
8350   return base::SmartArrayPointer<uc16>(result);
8351 }
8352
8353
8354 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8355   return reinterpret_cast<uc16*>(
8356       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8357 }
8358
8359
8360 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8361   Relocatable* current = isolate->relocatable_top();
8362   while (current != NULL) {
8363     current->PostGarbageCollection();
8364     current = current->prev_;
8365   }
8366 }
8367
8368
8369 // Reserve space for statics needing saving and restoring.
8370 int Relocatable::ArchiveSpacePerThread() {
8371   return sizeof(Relocatable*);  // NOLINT
8372 }
8373
8374
8375 // Archive statics that are thread-local.
8376 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8377   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8378   isolate->set_relocatable_top(NULL);
8379   return to + ArchiveSpacePerThread();
8380 }
8381
8382
8383 // Restore statics that are thread-local.
8384 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8385   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8386   return from + ArchiveSpacePerThread();
8387 }
8388
8389
8390 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8391   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8392   Iterate(v, top);
8393   return thread_storage + ArchiveSpacePerThread();
8394 }
8395
8396
8397 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8398   Iterate(v, isolate->relocatable_top());
8399 }
8400
8401
8402 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8403   Relocatable* current = top;
8404   while (current != NULL) {
8405     current->IterateInstance(v);
8406     current = current->prev_;
8407   }
8408 }
8409
8410
8411 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8412     : Relocatable(isolate),
8413       str_(str.location()),
8414       length_(str->length()) {
8415   PostGarbageCollection();
8416 }
8417
8418
8419 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8420     : Relocatable(isolate),
8421       str_(0),
8422       is_one_byte_(true),
8423       length_(input.length()),
8424       start_(input.start()) {}
8425
8426
8427 void FlatStringReader::PostGarbageCollection() {
8428   if (str_ == NULL) return;
8429   Handle<String> str(str_);
8430   DCHECK(str->IsFlat());
8431   DisallowHeapAllocation no_gc;
8432   // This does not actually prevent the vector from being relocated later.
8433   String::FlatContent content = str->GetFlatContent();
8434   DCHECK(content.IsFlat());
8435   is_one_byte_ = content.IsOneByte();
8436   if (is_one_byte_) {
8437     start_ = content.ToOneByteVector().start();
8438   } else {
8439     start_ = content.ToUC16Vector().start();
8440   }
8441 }
8442
8443
8444 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
8445   DCHECK(cons_string != NULL);
8446   root_ = cons_string;
8447   consumed_ = offset;
8448   // Force stack blown condition to trigger restart.
8449   depth_ = 1;
8450   maximum_depth_ = kStackSize + depth_;
8451   DCHECK(StackBlown());
8452 }
8453
8454
8455 String* ConsStringIterator::Continue(int* offset_out) {
8456   DCHECK(depth_ != 0);
8457   DCHECK_EQ(0, *offset_out);
8458   bool blew_stack = StackBlown();
8459   String* string = NULL;
8460   // Get the next leaf if there is one.
8461   if (!blew_stack) string = NextLeaf(&blew_stack);
8462   // Restart search from root.
8463   if (blew_stack) {
8464     DCHECK(string == NULL);
8465     string = Search(offset_out);
8466   }
8467   // Ensure future calls return null immediately.
8468   if (string == NULL) Reset(NULL);
8469   return string;
8470 }
8471
8472
8473 String* ConsStringIterator::Search(int* offset_out) {
8474   ConsString* cons_string = root_;
8475   // Reset the stack, pushing the root string.
8476   depth_ = 1;
8477   maximum_depth_ = 1;
8478   frames_[0] = cons_string;
8479   const int consumed = consumed_;
8480   int offset = 0;
8481   while (true) {
8482     // Loop until the string is found which contains the target offset.
8483     String* string = cons_string->first();
8484     int length = string->length();
8485     int32_t type;
8486     if (consumed < offset + length) {
8487       // Target offset is in the left branch.
8488       // Keep going if we're still in a ConString.
8489       type = string->map()->instance_type();
8490       if ((type & kStringRepresentationMask) == kConsStringTag) {
8491         cons_string = ConsString::cast(string);
8492         PushLeft(cons_string);
8493         continue;
8494       }
8495       // Tell the stack we're done descending.
8496       AdjustMaximumDepth();
8497     } else {
8498       // Descend right.
8499       // Update progress through the string.
8500       offset += length;
8501       // Keep going if we're still in a ConString.
8502       string = cons_string->second();
8503       type = string->map()->instance_type();
8504       if ((type & kStringRepresentationMask) == kConsStringTag) {
8505         cons_string = ConsString::cast(string);
8506         PushRight(cons_string);
8507         continue;
8508       }
8509       // Need this to be updated for the current string.
8510       length = string->length();
8511       // Account for the possibility of an empty right leaf.
8512       // This happens only if we have asked for an offset outside the string.
8513       if (length == 0) {
8514         // Reset so future operations will return null immediately.
8515         Reset(NULL);
8516         return NULL;
8517       }
8518       // Tell the stack we're done descending.
8519       AdjustMaximumDepth();
8520       // Pop stack so next iteration is in correct place.
8521       Pop();
8522     }
8523     DCHECK(length != 0);
8524     // Adjust return values and exit.
8525     consumed_ = offset + length;
8526     *offset_out = consumed - offset;
8527     return string;
8528   }
8529   UNREACHABLE();
8530   return NULL;
8531 }
8532
8533
8534 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
8535   while (true) {
8536     // Tree traversal complete.
8537     if (depth_ == 0) {
8538       *blew_stack = false;
8539       return NULL;
8540     }
8541     // We've lost track of higher nodes.
8542     if (StackBlown()) {
8543       *blew_stack = true;
8544       return NULL;
8545     }
8546     // Go right.
8547     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8548     String* string = cons_string->second();
8549     int32_t type = string->map()->instance_type();
8550     if ((type & kStringRepresentationMask) != kConsStringTag) {
8551       // Pop stack so next iteration is in correct place.
8552       Pop();
8553       int length = string->length();
8554       // Could be a flattened ConsString.
8555       if (length == 0) continue;
8556       consumed_ += length;
8557       return string;
8558     }
8559     cons_string = ConsString::cast(string);
8560     PushRight(cons_string);
8561     // Need to traverse all the way left.
8562     while (true) {
8563       // Continue left.
8564       string = cons_string->first();
8565       type = string->map()->instance_type();
8566       if ((type & kStringRepresentationMask) != kConsStringTag) {
8567         AdjustMaximumDepth();
8568         int length = string->length();
8569         DCHECK(length != 0);
8570         consumed_ += length;
8571         return string;
8572       }
8573       cons_string = ConsString::cast(string);
8574       PushLeft(cons_string);
8575     }
8576   }
8577   UNREACHABLE();
8578   return NULL;
8579 }
8580
8581
8582 uint16_t ConsString::ConsStringGet(int index) {
8583   DCHECK(index >= 0 && index < this->length());
8584
8585   // Check for a flattened cons string
8586   if (second()->length() == 0) {
8587     String* left = first();
8588     return left->Get(index);
8589   }
8590
8591   String* string = String::cast(this);
8592
8593   while (true) {
8594     if (StringShape(string).IsCons()) {
8595       ConsString* cons_string = ConsString::cast(string);
8596       String* left = cons_string->first();
8597       if (left->length() > index) {
8598         string = left;
8599       } else {
8600         index -= left->length();
8601         string = cons_string->second();
8602       }
8603     } else {
8604       return string->Get(index);
8605     }
8606   }
8607
8608   UNREACHABLE();
8609   return 0;
8610 }
8611
8612
8613 uint16_t SlicedString::SlicedStringGet(int index) {
8614   return parent()->Get(offset() + index);
8615 }
8616
8617
8618 template <typename sinkchar>
8619 void String::WriteToFlat(String* src,
8620                          sinkchar* sink,
8621                          int f,
8622                          int t) {
8623   String* source = src;
8624   int from = f;
8625   int to = t;
8626   while (true) {
8627     DCHECK(0 <= from && from <= to && to <= source->length());
8628     switch (StringShape(source).full_representation_tag()) {
8629       case kOneByteStringTag | kExternalStringTag: {
8630         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8631                   to - from);
8632         return;
8633       }
8634       case kTwoByteStringTag | kExternalStringTag: {
8635         const uc16* data =
8636             ExternalTwoByteString::cast(source)->GetChars();
8637         CopyChars(sink,
8638                   data + from,
8639                   to - from);
8640         return;
8641       }
8642       case kOneByteStringTag | kSeqStringTag: {
8643         CopyChars(sink,
8644                   SeqOneByteString::cast(source)->GetChars() + from,
8645                   to - from);
8646         return;
8647       }
8648       case kTwoByteStringTag | kSeqStringTag: {
8649         CopyChars(sink,
8650                   SeqTwoByteString::cast(source)->GetChars() + from,
8651                   to - from);
8652         return;
8653       }
8654       case kOneByteStringTag | kConsStringTag:
8655       case kTwoByteStringTag | kConsStringTag: {
8656         ConsString* cons_string = ConsString::cast(source);
8657         String* first = cons_string->first();
8658         int boundary = first->length();
8659         if (to - boundary >= boundary - from) {
8660           // Right hand side is longer.  Recurse over left.
8661           if (from < boundary) {
8662             WriteToFlat(first, sink, from, boundary);
8663             sink += boundary - from;
8664             from = 0;
8665           } else {
8666             from -= boundary;
8667           }
8668           to -= boundary;
8669           source = cons_string->second();
8670         } else {
8671           // Left hand side is longer.  Recurse over right.
8672           if (to > boundary) {
8673             String* second = cons_string->second();
8674             // When repeatedly appending to a string, we get a cons string that
8675             // is unbalanced to the left, a list, essentially.  We inline the
8676             // common case of sequential one-byte right child.
8677             if (to - boundary == 1) {
8678               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8679             } else if (second->IsSeqOneByteString()) {
8680               CopyChars(sink + boundary - from,
8681                         SeqOneByteString::cast(second)->GetChars(),
8682                         to - boundary);
8683             } else {
8684               WriteToFlat(second,
8685                           sink + boundary - from,
8686                           0,
8687                           to - boundary);
8688             }
8689             to = boundary;
8690           }
8691           source = first;
8692         }
8693         break;
8694       }
8695       case kOneByteStringTag | kSlicedStringTag:
8696       case kTwoByteStringTag | kSlicedStringTag: {
8697         SlicedString* slice = SlicedString::cast(source);
8698         unsigned offset = slice->offset();
8699         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8700         return;
8701       }
8702     }
8703   }
8704 }
8705
8706
8707
8708 template <typename SourceChar>
8709 static void CalculateLineEndsImpl(Isolate* isolate,
8710                                   List<int>* line_ends,
8711                                   Vector<const SourceChar> src,
8712                                   bool include_ending_line) {
8713   const int src_len = src.length();
8714   UnicodeCache* cache = isolate->unicode_cache();
8715   for (int i = 0; i < src_len - 1; i++) {
8716     SourceChar current = src[i];
8717     SourceChar next = src[i + 1];
8718     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
8719   }
8720
8721   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
8722     line_ends->Add(src_len - 1);
8723   } else if (include_ending_line) {
8724     // Even if the last line misses a line end, it is counted.
8725     line_ends->Add(src_len);
8726   }
8727 }
8728
8729
8730 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
8731                                              bool include_ending_line) {
8732   src = Flatten(src);
8733   // Rough estimate of line count based on a roughly estimated average
8734   // length of (unpacked) code.
8735   int line_count_estimate = src->length() >> 4;
8736   List<int> line_ends(line_count_estimate);
8737   Isolate* isolate = src->GetIsolate();
8738   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
8739     // Dispatch on type of strings.
8740     String::FlatContent content = src->GetFlatContent();
8741     DCHECK(content.IsFlat());
8742     if (content.IsOneByte()) {
8743       CalculateLineEndsImpl(isolate,
8744                             &line_ends,
8745                             content.ToOneByteVector(),
8746                             include_ending_line);
8747     } else {
8748       CalculateLineEndsImpl(isolate,
8749                             &line_ends,
8750                             content.ToUC16Vector(),
8751                             include_ending_line);
8752     }
8753   }
8754   int line_count = line_ends.length();
8755   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
8756   for (int i = 0; i < line_count; i++) {
8757     array->set(i, Smi::FromInt(line_ends[i]));
8758   }
8759   return array;
8760 }
8761
8762
8763 // Compares the contents of two strings by reading and comparing
8764 // int-sized blocks of characters.
8765 template <typename Char>
8766 static inline bool CompareRawStringContents(const Char* const a,
8767                                             const Char* const b,
8768                                             int length) {
8769   return CompareChars(a, b, length) == 0;
8770 }
8771
8772
8773 template<typename Chars1, typename Chars2>
8774 class RawStringComparator : public AllStatic {
8775  public:
8776   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8777     DCHECK(sizeof(Chars1) != sizeof(Chars2));
8778     for (int i = 0; i < len; i++) {
8779       if (a[i] != b[i]) {
8780         return false;
8781       }
8782     }
8783     return true;
8784   }
8785 };
8786
8787
8788 template<>
8789 class RawStringComparator<uint16_t, uint16_t> {
8790  public:
8791   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8792     return CompareRawStringContents(a, b, len);
8793   }
8794 };
8795
8796
8797 template<>
8798 class RawStringComparator<uint8_t, uint8_t> {
8799  public:
8800   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8801     return CompareRawStringContents(a, b, len);
8802   }
8803 };
8804
8805
8806 class StringComparator {
8807   class State {
8808    public:
8809     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
8810
8811     void Init(String* string) {
8812       ConsString* cons_string = String::VisitFlat(this, string);
8813       iter_.Reset(cons_string);
8814       if (cons_string != NULL) {
8815         int offset;
8816         string = iter_.Next(&offset);
8817         String::VisitFlat(this, string, offset);
8818       }
8819     }
8820
8821     inline void VisitOneByteString(const uint8_t* chars, int length) {
8822       is_one_byte_ = true;
8823       buffer8_ = chars;
8824       length_ = length;
8825     }
8826
8827     inline void VisitTwoByteString(const uint16_t* chars, int length) {
8828       is_one_byte_ = false;
8829       buffer16_ = chars;
8830       length_ = length;
8831     }
8832
8833     void Advance(int consumed) {
8834       DCHECK(consumed <= length_);
8835       // Still in buffer.
8836       if (length_ != consumed) {
8837         if (is_one_byte_) {
8838           buffer8_ += consumed;
8839         } else {
8840           buffer16_ += consumed;
8841         }
8842         length_ -= consumed;
8843         return;
8844       }
8845       // Advance state.
8846       int offset;
8847       String* next = iter_.Next(&offset);
8848       DCHECK_EQ(0, offset);
8849       DCHECK(next != NULL);
8850       String::VisitFlat(this, next);
8851     }
8852
8853     ConsStringIterator iter_;
8854     bool is_one_byte_;
8855     int length_;
8856     union {
8857       const uint8_t* buffer8_;
8858       const uint16_t* buffer16_;
8859     };
8860
8861    private:
8862     DISALLOW_COPY_AND_ASSIGN(State);
8863   };
8864
8865  public:
8866   inline StringComparator() {}
8867
8868   template<typename Chars1, typename Chars2>
8869   static inline bool Equals(State* state_1, State* state_2, int to_check) {
8870     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8871     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8872     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8873   }
8874
8875   bool Equals(String* string_1, String* string_2) {
8876     int length = string_1->length();
8877     state_1_.Init(string_1);
8878     state_2_.Init(string_2);
8879     while (true) {
8880       int to_check = Min(state_1_.length_, state_2_.length_);
8881       DCHECK(to_check > 0 && to_check <= length);
8882       bool is_equal;
8883       if (state_1_.is_one_byte_) {
8884         if (state_2_.is_one_byte_) {
8885           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8886         } else {
8887           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8888         }
8889       } else {
8890         if (state_2_.is_one_byte_) {
8891           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8892         } else {
8893           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8894         }
8895       }
8896       // Looping done.
8897       if (!is_equal) return false;
8898       length -= to_check;
8899       // Exit condition. Strings are equal.
8900       if (length == 0) return true;
8901       state_1_.Advance(to_check);
8902       state_2_.Advance(to_check);
8903     }
8904   }
8905
8906  private:
8907   State state_1_;
8908   State state_2_;
8909
8910   DISALLOW_COPY_AND_ASSIGN(StringComparator);
8911 };
8912
8913
8914 bool String::SlowEquals(String* other) {
8915   DisallowHeapAllocation no_gc;
8916   // Fast check: negative check with lengths.
8917   int len = length();
8918   if (len != other->length()) return false;
8919   if (len == 0) return true;
8920
8921   // Fast check: if hash code is computed for both strings
8922   // a fast negative check can be performed.
8923   if (HasHashCode() && other->HasHashCode()) {
8924 #ifdef ENABLE_SLOW_DCHECKS
8925     if (FLAG_enable_slow_asserts) {
8926       if (Hash() != other->Hash()) {
8927         bool found_difference = false;
8928         for (int i = 0; i < len; i++) {
8929           if (Get(i) != other->Get(i)) {
8930             found_difference = true;
8931             break;
8932           }
8933         }
8934         DCHECK(found_difference);
8935       }
8936     }
8937 #endif
8938     if (Hash() != other->Hash()) return false;
8939   }
8940
8941   // We know the strings are both non-empty. Compare the first chars
8942   // before we try to flatten the strings.
8943   if (this->Get(0) != other->Get(0)) return false;
8944
8945   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
8946     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
8947     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
8948     return CompareRawStringContents(str1, str2, len);
8949   }
8950
8951   StringComparator comparator;
8952   return comparator.Equals(this, other);
8953 }
8954
8955
8956 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
8957   // Fast check: negative check with lengths.
8958   int one_length = one->length();
8959   if (one_length != two->length()) return false;
8960   if (one_length == 0) return true;
8961
8962   // Fast check: if hash code is computed for both strings
8963   // a fast negative check can be performed.
8964   if (one->HasHashCode() && two->HasHashCode()) {
8965 #ifdef ENABLE_SLOW_DCHECKS
8966     if (FLAG_enable_slow_asserts) {
8967       if (one->Hash() != two->Hash()) {
8968         bool found_difference = false;
8969         for (int i = 0; i < one_length; i++) {
8970           if (one->Get(i) != two->Get(i)) {
8971             found_difference = true;
8972             break;
8973           }
8974         }
8975         DCHECK(found_difference);
8976       }
8977     }
8978 #endif
8979     if (one->Hash() != two->Hash()) return false;
8980   }
8981
8982   // We know the strings are both non-empty. Compare the first chars
8983   // before we try to flatten the strings.
8984   if (one->Get(0) != two->Get(0)) return false;
8985
8986   one = String::Flatten(one);
8987   two = String::Flatten(two);
8988
8989   DisallowHeapAllocation no_gc;
8990   String::FlatContent flat1 = one->GetFlatContent();
8991   String::FlatContent flat2 = two->GetFlatContent();
8992
8993   if (flat1.IsOneByte() && flat2.IsOneByte()) {
8994       return CompareRawStringContents(flat1.ToOneByteVector().start(),
8995                                       flat2.ToOneByteVector().start(),
8996                                       one_length);
8997   } else {
8998     for (int i = 0; i < one_length; i++) {
8999       if (flat1.Get(i) != flat2.Get(i)) return false;
9000     }
9001     return true;
9002   }
9003 }
9004
9005
9006 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9007   int slen = length();
9008   // Can't check exact length equality, but we can check bounds.
9009   int str_len = str.length();
9010   if (!allow_prefix_match &&
9011       (str_len < slen ||
9012           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9013     return false;
9014   }
9015   int i;
9016   size_t remaining_in_str = static_cast<size_t>(str_len);
9017   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9018   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9019     size_t cursor = 0;
9020     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9021     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9022     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9023       if (i > slen - 1) return false;
9024       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9025       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9026     } else {
9027       if (Get(i) != r) return false;
9028     }
9029     utf8_data += cursor;
9030     remaining_in_str -= cursor;
9031   }
9032   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9033 }
9034
9035
9036 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9037   int slen = length();
9038   if (str.length() != slen) return false;
9039   DisallowHeapAllocation no_gc;
9040   FlatContent content = GetFlatContent();
9041   if (content.IsOneByte()) {
9042     return CompareChars(content.ToOneByteVector().start(),
9043                         str.start(), slen) == 0;
9044   }
9045   for (int i = 0; i < slen; i++) {
9046     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9047   }
9048   return true;
9049 }
9050
9051
9052 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9053   int slen = length();
9054   if (str.length() != slen) return false;
9055   DisallowHeapAllocation no_gc;
9056   FlatContent content = GetFlatContent();
9057   if (content.IsTwoByte()) {
9058     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9059   }
9060   for (int i = 0; i < slen; i++) {
9061     if (Get(i) != str[i]) return false;
9062   }
9063   return true;
9064 }
9065
9066
9067 uint32_t String::ComputeAndSetHash() {
9068   // Should only be called if hash code has not yet been computed.
9069   DCHECK(!HasHashCode());
9070
9071   // Store the hash code in the object.
9072   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9073   set_hash_field(field);
9074
9075   // Check the hash code is there.
9076   DCHECK(HasHashCode());
9077   uint32_t result = field >> kHashShift;
9078   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9079   return result;
9080 }
9081
9082
9083 bool String::ComputeArrayIndex(uint32_t* index) {
9084   int length = this->length();
9085   if (length == 0 || length > kMaxArrayIndexSize) return false;
9086   StringCharacterStream stream(this);
9087   return StringToArrayIndex(&stream, index);
9088 }
9089
9090
9091 bool String::SlowAsArrayIndex(uint32_t* index) {
9092   if (length() <= kMaxCachedArrayIndexLength) {
9093     Hash();  // force computation of hash code
9094     uint32_t field = hash_field();
9095     if ((field & kIsNotArrayIndexMask) != 0) return false;
9096     // Isolate the array index form the full hash field.
9097     *index = ArrayIndexValueBits::decode(field);
9098     return true;
9099   } else {
9100     return ComputeArrayIndex(index);
9101   }
9102 }
9103
9104
9105 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9106   int new_size, old_size;
9107   int old_length = string->length();
9108   if (old_length <= new_length) return string;
9109
9110   if (string->IsSeqOneByteString()) {
9111     old_size = SeqOneByteString::SizeFor(old_length);
9112     new_size = SeqOneByteString::SizeFor(new_length);
9113   } else {
9114     DCHECK(string->IsSeqTwoByteString());
9115     old_size = SeqTwoByteString::SizeFor(old_length);
9116     new_size = SeqTwoByteString::SizeFor(new_length);
9117   }
9118
9119   int delta = old_size - new_size;
9120
9121   Address start_of_string = string->address();
9122   DCHECK_OBJECT_ALIGNED(start_of_string);
9123   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9124
9125   Heap* heap = string->GetHeap();
9126   NewSpace* newspace = heap->new_space();
9127   if (newspace->Contains(start_of_string) &&
9128       newspace->top() == start_of_string + old_size) {
9129     // Last allocated object in new space.  Simply lower allocation top.
9130     newspace->set_top(start_of_string + new_size);
9131   } else {
9132     // Sizes are pointer size aligned, so that we can use filler objects
9133     // that are a multiple of pointer size.
9134     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9135   }
9136   heap->AdjustLiveBytes(start_of_string, -delta, Heap::CONCURRENT_TO_SWEEPER);
9137
9138   // We are storing the new length using release store after creating a filler
9139   // for the left-over space to avoid races with the sweeper thread.
9140   string->synchronized_set_length(new_length);
9141
9142   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9143   return string;
9144 }
9145
9146
9147 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9148   // For array indexes mix the length into the hash as an array index could
9149   // be zero.
9150   DCHECK(length > 0);
9151   DCHECK(length <= String::kMaxArrayIndexSize);
9152   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9153          (1 << String::kArrayIndexValueBits));
9154
9155   value <<= String::ArrayIndexValueBits::kShift;
9156   value |= length << String::ArrayIndexLengthBits::kShift;
9157
9158   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9159   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9160          (value & String::kContainsCachedArrayIndexMask) == 0);
9161   return value;
9162 }
9163
9164
9165 uint32_t StringHasher::GetHashField() {
9166   if (length_ <= String::kMaxHashCalcLength) {
9167     if (is_array_index_) {
9168       return MakeArrayIndexHash(array_index_, length_);
9169     }
9170     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9171            String::kIsNotArrayIndexMask;
9172   } else {
9173     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9174   }
9175 }
9176
9177
9178 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9179                                        uint32_t seed,
9180                                        int* utf16_length_out) {
9181   int vector_length = chars.length();
9182   // Handle some edge cases
9183   if (vector_length <= 1) {
9184     DCHECK(vector_length == 0 ||
9185            static_cast<uint8_t>(chars.start()[0]) <=
9186                unibrow::Utf8::kMaxOneByteChar);
9187     *utf16_length_out = vector_length;
9188     return HashSequentialString(chars.start(), vector_length, seed);
9189   }
9190   // Start with a fake length which won't affect computation.
9191   // It will be updated later.
9192   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9193   size_t remaining = static_cast<size_t>(vector_length);
9194   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9195   int utf16_length = 0;
9196   bool is_index = true;
9197   DCHECK(hasher.is_array_index_);
9198   while (remaining > 0) {
9199     size_t consumed = 0;
9200     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9201     DCHECK(consumed > 0 && consumed <= remaining);
9202     stream += consumed;
9203     remaining -= consumed;
9204     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9205     utf16_length += is_two_characters ? 2 : 1;
9206     // No need to keep hashing. But we do need to calculate utf16_length.
9207     if (utf16_length > String::kMaxHashCalcLength) continue;
9208     if (is_two_characters) {
9209       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9210       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9211       hasher.AddCharacter(c1);
9212       hasher.AddCharacter(c2);
9213       if (is_index) is_index = hasher.UpdateIndex(c1);
9214       if (is_index) is_index = hasher.UpdateIndex(c2);
9215     } else {
9216       hasher.AddCharacter(c);
9217       if (is_index) is_index = hasher.UpdateIndex(c);
9218     }
9219   }
9220   *utf16_length_out = static_cast<int>(utf16_length);
9221   // Must set length here so that hash computation is correct.
9222   hasher.length_ = utf16_length;
9223   return hasher.GetHashField();
9224 }
9225
9226
9227 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
9228   // Run small ConsStrings through ConsStringIterator.
9229   if (cons_string->length() < 64) {
9230     ConsStringIterator iter(cons_string);
9231     int offset;
9232     String* string;
9233     while (nullptr != (string = iter.Next(&offset))) {
9234       DCHECK_EQ(0, offset);
9235       String::VisitFlat(this, string, 0);
9236     }
9237     return;
9238   }
9239   // Slow case.
9240   const int max_length = String::kMaxHashCalcLength;
9241   int length = std::min(cons_string->length(), max_length);
9242   if (cons_string->HasOnlyOneByteChars()) {
9243     uint8_t* buffer = new uint8_t[length];
9244     String::WriteToFlat(cons_string, buffer, 0, length);
9245     AddCharacters(buffer, length);
9246     delete[] buffer;
9247   } else {
9248     uint16_t* buffer = new uint16_t[length];
9249     String::WriteToFlat(cons_string, buffer, 0, length);
9250     AddCharacters(buffer, length);
9251     delete[] buffer;
9252   }
9253 }
9254
9255
9256 void String::PrintOn(FILE* file) {
9257   int length = this->length();
9258   for (int i = 0; i < length; i++) {
9259     PrintF(file, "%c", Get(i));
9260   }
9261 }
9262
9263
9264 inline static uint32_t ObjectAddressForHashing(Object* object) {
9265   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9266   return value & MemoryChunk::kAlignmentMask;
9267 }
9268
9269
9270 int Map::Hash() {
9271   // For performance reasons we only hash the 3 most variable fields of a map:
9272   // constructor, prototype and bit_field2. For predictability reasons we
9273   // use objects' offsets in respective pages for hashing instead of raw
9274   // addresses.
9275
9276   // Shift away the tag.
9277   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
9278
9279   // XOR-ing the prototype and constructor directly yields too many zero bits
9280   // when the two pointers are close (which is fairly common).
9281   // To avoid this we shift the prototype bits relatively to the constructor.
9282   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9283
9284   return hash ^ (hash >> 16) ^ bit_field2();
9285 }
9286
9287
9288 static bool CheckEquivalent(Map* first, Map* second) {
9289   return first->GetConstructor() == second->GetConstructor() &&
9290          first->prototype() == second->prototype() &&
9291          first->instance_type() == second->instance_type() &&
9292          first->bit_field() == second->bit_field() &&
9293          first->is_extensible() == second->is_extensible() &&
9294          first->is_strong() == second->is_strong() &&
9295          first->has_instance_call_handler() ==
9296              second->has_instance_call_handler();
9297 }
9298
9299
9300 bool Map::EquivalentToForTransition(Map* other) {
9301   return CheckEquivalent(this, other);
9302 }
9303
9304
9305 bool Map::EquivalentToForNormalization(Map* other,
9306                                        PropertyNormalizationMode mode) {
9307   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9308       ? 0 : other->inobject_properties();
9309   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
9310          inobject_properties() == properties;
9311 }
9312
9313
9314 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9315   // Iterate over all fields in the body but take care in dealing with
9316   // the code entry.
9317   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9318   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9319   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9320 }
9321
9322
9323 bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
9324   DisallowHeapAllocation no_gc;
9325   if (shared() == candidate) return true;
9326   if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
9327   DeoptimizationInputData* const data =
9328       DeoptimizationInputData::cast(code()->deoptimization_data());
9329   if (data->length() == 0) return false;
9330   FixedArray* const literals = data->LiteralArray();
9331   int const inlined_count = data->InlinedFunctionCount()->value();
9332   for (int i = 0; i < inlined_count; ++i) {
9333     if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
9334       return true;
9335     }
9336   }
9337   return false;
9338 }
9339
9340
9341 void JSFunction::MarkForOptimization() {
9342   Isolate* isolate = GetIsolate();
9343   // Do not optimize if function contains break points.
9344   if (shared()->HasDebugInfo()) return;
9345   DCHECK(!IsOptimized());
9346   DCHECK(shared()->allows_lazy_compilation() ||
9347          !shared()->optimization_disabled());
9348   DCHECK(!shared()->HasDebugInfo());
9349   set_code_no_write_barrier(
9350       isolate->builtins()->builtin(Builtins::kCompileOptimized));
9351   // No write barrier required, since the builtin is part of the root set.
9352 }
9353
9354
9355 void JSFunction::AttemptConcurrentOptimization() {
9356   Isolate* isolate = GetIsolate();
9357   if (!isolate->concurrent_recompilation_enabled() ||
9358       isolate->bootstrapper()->IsActive()) {
9359     MarkForOptimization();
9360     return;
9361   }
9362   if (isolate->concurrent_osr_enabled() &&
9363       isolate->optimizing_compile_dispatcher()->IsQueuedForOSR(this)) {
9364     // Do not attempt regular recompilation if we already queued this for OSR.
9365     // TODO(yangguo): This is necessary so that we don't install optimized
9366     // code on a function that is already optimized, since OSR and regular
9367     // recompilation race.  This goes away as soon as OSR becomes one-shot.
9368     return;
9369   }
9370   DCHECK(!IsInOptimizationQueue());
9371   DCHECK(!IsOptimized());
9372   DCHECK(shared()->allows_lazy_compilation() ||
9373          !shared()->optimization_disabled());
9374   DCHECK(isolate->concurrent_recompilation_enabled());
9375   if (FLAG_trace_concurrent_recompilation) {
9376     PrintF("  ** Marking ");
9377     ShortPrint();
9378     PrintF(" for concurrent recompilation.\n");
9379   }
9380   set_code_no_write_barrier(
9381       isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9382   // No write barrier required, since the builtin is part of the root set.
9383 }
9384
9385
9386 Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9387   Isolate* isolate = function->GetIsolate();
9388   Handle<Map> map(function->map());
9389   Handle<SharedFunctionInfo> shared(function->shared());
9390   Handle<Context> context(function->context());
9391   Handle<JSFunction> clone =
9392       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9393
9394   if (shared->bound()) {
9395     clone->set_function_bindings(function->function_bindings());
9396   }
9397
9398   // In typical case, __proto__ of ``function`` is the default Function
9399   // prototype, which means that SetPrototype below is a no-op.
9400   // In rare cases when that is not true, we mutate the clone's __proto__.
9401   Handle<Object> original_prototype(map->prototype(), isolate);
9402   if (*original_prototype != clone->map()->prototype()) {
9403     JSObject::SetPrototype(clone, original_prototype, false).Assert();
9404   }
9405
9406   return clone;
9407 }
9408
9409
9410 void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
9411     Handle<SharedFunctionInfo> shared, Handle<Code> code) {
9412   Isolate* isolate = shared->GetIsolate();
9413   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9414   Handle<Object> value(shared->optimized_code_map(), isolate);
9415   if (value->IsSmi()) return;  // Empty code maps are unsupported.
9416   Handle<FixedArray> code_map = Handle<FixedArray>::cast(value);
9417   code_map->set(kSharedCodeIndex, *code);
9418 }
9419
9420
9421 void SharedFunctionInfo::AddToOptimizedCodeMap(
9422     Handle<SharedFunctionInfo> shared,
9423     Handle<Context> native_context,
9424     Handle<Code> code,
9425     Handle<FixedArray> literals,
9426     BailoutId osr_ast_id) {
9427   Isolate* isolate = shared->GetIsolate();
9428   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9429   DCHECK(native_context->IsNativeContext());
9430   STATIC_ASSERT(kEntryLength == 4);
9431   Handle<FixedArray> new_code_map;
9432   Handle<Object> value(shared->optimized_code_map(), isolate);
9433   int old_length;
9434   if (value->IsSmi()) {
9435     // No optimized code map.
9436     DCHECK_EQ(0, Smi::cast(*value)->value());
9437     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9438     old_length = kEntriesStart;
9439   } else {
9440     // Copy old map and append one new entry.
9441     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9442     DCHECK(!shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code);
9443     old_length = old_code_map->length();
9444     new_code_map = FixedArray::CopySize(
9445         old_code_map, old_length + kEntryLength);
9446     // Zap the old map for the sake of the heap verifier.
9447     if (Heap::ShouldZapGarbage()) {
9448       Object** data = old_code_map->data_start();
9449       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9450     }
9451   }
9452   new_code_map->set(old_length + kContextOffset, *native_context);
9453   new_code_map->set(old_length + kCachedCodeOffset, *code);
9454   new_code_map->set(old_length + kLiteralsOffset, *literals);
9455   new_code_map->set(old_length + kOsrAstIdOffset,
9456                     Smi::FromInt(osr_ast_id.ToInt()));
9457
9458 #ifdef DEBUG
9459   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9460     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9461     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9462     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9463            Code::OPTIMIZED_FUNCTION);
9464     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9465     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9466   }
9467 #endif
9468   shared->set_optimized_code_map(*new_code_map);
9469 }
9470
9471
9472 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9473   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9474
9475   // If the next map link slot is already used then the function was
9476   // enqueued with code flushing and we remove it now.
9477   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9478     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9479     flusher->EvictOptimizedCodeMap(this);
9480   }
9481
9482   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9483   set_optimized_code_map(Smi::FromInt(0));
9484 }
9485
9486
9487 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9488                                                    const char* reason) {
9489   DisallowHeapAllocation no_gc;
9490   if (optimized_code_map()->IsSmi()) return;
9491
9492   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9493   int dst = kEntriesStart;
9494   int length = code_map->length();
9495   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9496     DCHECK(code_map->get(src)->IsNativeContext());
9497     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9498       // Evict the src entry by not copying it to the dst entry.
9499       if (FLAG_trace_opt) {
9500         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9501         ShortPrint();
9502         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9503         if (osr.IsNone()) {
9504           PrintF("]\n");
9505         } else {
9506           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9507         }
9508       }
9509     } else {
9510       // Keep the src entry by copying it to the dst entry.
9511       if (dst != src) {
9512         code_map->set(dst + kContextOffset,
9513                       code_map->get(src + kContextOffset));
9514         code_map->set(dst + kCachedCodeOffset,
9515                       code_map->get(src + kCachedCodeOffset));
9516         code_map->set(dst + kLiteralsOffset,
9517                       code_map->get(src + kLiteralsOffset));
9518         code_map->set(dst + kOsrAstIdOffset,
9519                       code_map->get(src + kOsrAstIdOffset));
9520       }
9521       dst += kEntryLength;
9522     }
9523   }
9524   if (code_map->get(kSharedCodeIndex) == optimized_code) {
9525     // Evict context-independent code as well.
9526     code_map->set_undefined(kSharedCodeIndex);
9527     if (FLAG_trace_opt) {
9528       PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9529       ShortPrint();
9530       PrintF(" (context-independent code)]\n");
9531     }
9532   }
9533   if (dst != length) {
9534     // Always trim even when array is cleared because of heap verifier.
9535     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
9536                                                                 length - dst);
9537     if (code_map->length() == kEntriesStart &&
9538         code_map->get(kSharedCodeIndex)->IsUndefined()) {
9539       ClearOptimizedCodeMap();
9540     }
9541   }
9542 }
9543
9544
9545 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9546   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9547   DCHECK(shrink_by % kEntryLength == 0);
9548   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9549   // Always trim even when array is cleared because of heap verifier.
9550   GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
9551                                                               shrink_by);
9552   if (code_map->length() == kEntriesStart &&
9553       code_map->get(kSharedCodeIndex)->IsUndefined()) {
9554     ClearOptimizedCodeMap();
9555   }
9556 }
9557
9558
9559 static void GetMinInobjectSlack(Map* map, void* data) {
9560   int slack = map->unused_property_fields();
9561   if (*reinterpret_cast<int*>(data) > slack) {
9562     *reinterpret_cast<int*>(data) = slack;
9563   }
9564 }
9565
9566
9567 static void ShrinkInstanceSize(Map* map, void* data) {
9568   int slack = *reinterpret_cast<int*>(data);
9569   map->set_inobject_properties(map->inobject_properties() - slack);
9570   map->set_unused_property_fields(map->unused_property_fields() - slack);
9571   map->set_instance_size(map->instance_size() - slack * kPointerSize);
9572
9573   // Visitor id might depend on the instance size, recalculate it.
9574   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9575 }
9576
9577
9578 void JSFunction::CompleteInobjectSlackTracking() {
9579   DCHECK(has_initial_map());
9580   Map* map = initial_map();
9581
9582   DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
9583   map->set_counter(Map::kRetainingCounterStart);
9584
9585   int slack = map->unused_property_fields();
9586   TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack);
9587   if (slack != 0) {
9588     // Resize the initial map and all maps in its transition tree.
9589     TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack);
9590   }
9591 }
9592
9593
9594 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
9595   DisallowHeapAllocation no_gc;
9596   if (!object->HasFastProperties()) return false;
9597   Map* map = object->map();
9598   if (map->is_prototype_map()) return false;
9599   DescriptorArray* descriptors = map->instance_descriptors();
9600   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
9601     PropertyDetails details = descriptors->GetDetails(i);
9602     if (details.location() == kDescriptor) continue;
9603     if (details.representation().IsHeapObject() ||
9604         details.representation().IsTagged()) {
9605       FieldIndex index = FieldIndex::ForDescriptor(map, i);
9606       if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9607     }
9608   }
9609   return false;
9610 }
9611
9612
9613 // static
9614 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9615                                    PrototypeOptimizationMode mode) {
9616   if (object->IsGlobalObject()) return;
9617   if (object->IsJSGlobalProxy()) return;
9618   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9619     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9620     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9621                                   "NormalizeAsPrototype");
9622   }
9623   Handle<Map> previous_map(object->map());
9624   if (!object->HasFastProperties()) {
9625     JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9626   }
9627   if (!object->map()->is_prototype_map()) {
9628     if (object->map() == *previous_map) {
9629       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9630       JSObject::MigrateToMap(object, new_map);
9631     }
9632     object->map()->set_is_prototype_map(true);
9633
9634     // Replace the pointer to the exact constructor with the Object function
9635     // from the same context if undetectable from JS. This is to avoid keeping
9636     // memory alive unnecessarily.
9637     Object* maybe_constructor = object->map()->GetConstructor();
9638     if (maybe_constructor->IsJSFunction()) {
9639       JSFunction* constructor = JSFunction::cast(maybe_constructor);
9640       Isolate* isolate = object->GetIsolate();
9641       if (!constructor->shared()->IsApiFunction() &&
9642           object->class_name() == isolate->heap()->Object_string()) {
9643         Handle<String> constructor_name(object->constructor_name(), isolate);
9644         Context* context = constructor->context()->native_context();
9645         JSFunction* object_function = context->object_function();
9646         object->map()->SetConstructor(object_function);
9647         Handle<PrototypeInfo> proto_info =
9648             Map::GetOrCreatePrototypeInfo(object, isolate);
9649         proto_info->set_constructor_name(*constructor_name);
9650       }
9651     }
9652   }
9653 }
9654
9655
9656 // static
9657 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9658   if (!object->map()->is_prototype_map()) return;
9659   OptimizeAsPrototype(object, FAST_PROTOTYPE);
9660 }
9661
9662
9663 // static
9664 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
9665   DCHECK(FLAG_track_prototype_users);
9666   // Contract: In line with InvalidatePrototypeChains()'s requirements,
9667   // leaf maps don't need to register as users, only prototypes do.
9668   DCHECK(user->is_prototype_map());
9669
9670   Handle<Map> current_user = user;
9671   for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
9672     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
9673     if (maybe_proto->IsJSGlobalProxy()) continue;
9674     // Proxies on the prototype chain are not supported.
9675     if (maybe_proto->IsJSProxy()) return;
9676     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
9677     bool just_registered =
9678         RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate);
9679     // Walk up the prototype chain as far as links haven't been registered yet.
9680     if (!just_registered) break;
9681     current_user = handle(proto->map(), isolate);
9682   }
9683 }
9684
9685
9686 // Returns true if the user was not yet registered.
9687 // static
9688 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype,
9689                                                     Handle<HeapObject> user,
9690                                                     Isolate* isolate) {
9691   Handle<PrototypeInfo> proto_info =
9692       Map::GetOrCreatePrototypeInfo(prototype, isolate);
9693   Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
9694   bool was_present = false;
9695   Handle<WeakFixedArray> new_array = WeakFixedArray::Add(
9696       maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present);
9697   if (!maybe_registry.is_identical_to(new_array)) {
9698     proto_info->set_prototype_users(*new_array);
9699   }
9700   if (FLAG_trace_prototype_users && !was_present) {
9701     PrintF("Registering %p as a user of prototype %p (map=%p).\n",
9702            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype),
9703            reinterpret_cast<void*>(prototype->map()));
9704   }
9705   return !was_present;
9706 }
9707
9708
9709 // Can be called regardless of whether |user| was actually registered with
9710 // |prototype|. Returns true when there was a registration.
9711 // static
9712 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9713                                        Handle<HeapObject> user) {
9714   Isolate* isolate = prototype->GetIsolate();
9715   if (prototype->IsJSGlobalProxy()) {
9716     PrototypeIterator iter(isolate, prototype);
9717     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9718   }
9719   DCHECK(prototype->map()->is_prototype_map());
9720   Object* maybe_proto_info = prototype->map()->prototype_info();
9721   if (!maybe_proto_info->IsPrototypeInfo()) return false;
9722   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
9723                                    isolate);
9724   Object* maybe_registry = proto_info->prototype_users();
9725   if (!maybe_registry->IsWeakFixedArray()) return false;
9726   bool result = WeakFixedArray::cast(maybe_registry)->Remove(user);
9727   if (FLAG_trace_prototype_users && result) {
9728     PrintF("Unregistering %p as a user of prototype %p.\n",
9729            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
9730   }
9731   return result;
9732 }
9733
9734
9735 static void InvalidatePrototypeChainsInternal(Map* map) {
9736   if (!map->is_prototype_map()) return;
9737   if (FLAG_trace_prototype_users) {
9738     PrintF("Invalidating prototype map %p 's cell\n",
9739            reinterpret_cast<void*>(map));
9740   }
9741   Object* maybe_proto_info = map->prototype_info();
9742   if (!maybe_proto_info->IsPrototypeInfo()) return;
9743   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
9744   Object* maybe_cell = proto_info->validity_cell();
9745   if (maybe_cell->IsCell()) {
9746     // Just set the value; the cell will be replaced lazily.
9747     Cell* cell = Cell::cast(maybe_cell);
9748     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
9749   }
9750
9751   Object* maybe_array = proto_info->prototype_users();
9752   if (!maybe_array->IsWeakFixedArray()) return;
9753
9754   WeakFixedArray* users = WeakFixedArray::cast(maybe_array);
9755   for (int i = 0; i < users->Length(); ++i) {
9756     Object* maybe_user = users->Get(i);
9757     if (maybe_user->IsSmi()) continue;
9758
9759     // For now, only maps register themselves as users.
9760     Map* user = Map::cast(maybe_user);
9761     // Walk the prototype chain (backwards, towards leaf objects) if necessary.
9762     InvalidatePrototypeChainsInternal(user);
9763   }
9764 }
9765
9766
9767 // static
9768 void JSObject::InvalidatePrototypeChains(Map* map) {
9769   if (!FLAG_eliminate_prototype_chain_checks) return;
9770   DisallowHeapAllocation no_gc;
9771   if (map->IsJSGlobalProxyMap()) {
9772     PrototypeIterator iter(map);
9773     map = JSObject::cast(iter.GetCurrent())->map();
9774   }
9775   InvalidatePrototypeChainsInternal(map);
9776 }
9777
9778
9779 // static
9780 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
9781                                                     Isolate* isolate) {
9782   Object* maybe_proto_info = prototype->map()->prototype_info();
9783   if (maybe_proto_info->IsPrototypeInfo()) {
9784     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
9785   }
9786   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
9787   prototype->map()->set_prototype_info(*proto_info);
9788   return proto_info;
9789 }
9790
9791
9792 // static
9793 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
9794                                                         Isolate* isolate) {
9795   Handle<Object> maybe_prototype(map->prototype(), isolate);
9796   if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
9797   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
9798   if (prototype->IsJSGlobalProxy()) {
9799     PrototypeIterator iter(isolate, prototype);
9800     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9801   }
9802   // Ensure the prototype is registered with its own prototypes so its cell
9803   // will be invalidated when necessary.
9804   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
9805                                       isolate);
9806   Handle<PrototypeInfo> proto_info =
9807       GetOrCreatePrototypeInfo(prototype, isolate);
9808   Object* maybe_cell = proto_info->validity_cell();
9809   // Return existing cell if it's still valid.
9810   if (maybe_cell->IsCell()) {
9811     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
9812     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
9813       return cell;
9814     }
9815   }
9816   // Otherwise create a new cell.
9817   Handle<Cell> cell = isolate->factory()->NewCell(
9818       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
9819   proto_info->set_validity_cell(*cell);
9820   return cell;
9821 }
9822
9823
9824 // static
9825 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
9826                        PrototypeOptimizationMode proto_mode) {
9827   if (prototype->IsJSObject()) {
9828     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9829     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9830   }
9831   WriteBarrierMode wb_mode =
9832       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9833   map->set_prototype(*prototype, wb_mode);
9834 }
9835
9836
9837 Handle<Object> CacheInitialJSArrayMaps(
9838     Handle<Context> native_context, Handle<Map> initial_map) {
9839   // Replace all of the cached initial array maps in the native context with
9840   // the appropriate transitioned elements kind maps.
9841   Factory* factory = native_context->GetIsolate()->factory();
9842   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9843       kElementsKindCount, TENURED);
9844
9845   Handle<Map> current_map = initial_map;
9846   ElementsKind kind = current_map->elements_kind();
9847   DCHECK(kind == GetInitialFastElementsKind());
9848   maps->set(kind, *current_map);
9849   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9850        i < kFastElementsKindCount; ++i) {
9851     Handle<Map> new_map;
9852     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9853     Map* maybe_elements_transition = current_map->ElementsTransitionMap();
9854     if (maybe_elements_transition != NULL) {
9855       new_map = handle(maybe_elements_transition);
9856       DCHECK(new_map->elements_kind() == next_kind);
9857     } else {
9858       new_map = Map::CopyAsElementsKind(
9859           current_map, next_kind, INSERT_TRANSITION);
9860     }
9861     maps->set(next_kind, *new_map);
9862     current_map = new_map;
9863   }
9864   if (initial_map->is_strong())
9865     native_context->set_js_array_strong_maps(*maps);
9866   else
9867     native_context->set_js_array_maps(*maps);
9868   return initial_map;
9869 }
9870
9871
9872 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9873                                       Handle<Object> value) {
9874   Isolate* isolate = function->GetIsolate();
9875
9876   DCHECK(value->IsJSReceiver());
9877
9878   // Now some logic for the maps of the objects that are created by using this
9879   // function as a constructor.
9880   if (function->has_initial_map()) {
9881     // If the function has allocated the initial map replace it with a
9882     // copy containing the new prototype.  Also complete any in-object
9883     // slack tracking that is in progress at this point because it is
9884     // still tracking the old copy.
9885     if (function->IsInobjectSlackTrackingInProgress()) {
9886       function->CompleteInobjectSlackTracking();
9887     }
9888
9889     Handle<Map> initial_map(function->initial_map(), isolate);
9890
9891     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9892         initial_map->instance_type() == JS_OBJECT_TYPE) {
9893       // Put the value in the initial map field until an initial map is needed.
9894       // At that point, a new initial map is created and the prototype is put
9895       // into the initial map where it belongs.
9896       function->set_prototype_or_initial_map(*value);
9897     } else {
9898       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
9899       JSFunction::SetInitialMap(function, new_map, value);
9900
9901       // If the function is used as the global Array function, cache the
9902       // updated initial maps (and transitioned versions) in the native context.
9903       Handle<Context> native_context(function->context()->native_context(),
9904                                      isolate);
9905       Handle<Object> array_function(
9906           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
9907       if (array_function->IsJSFunction() &&
9908           *function == JSFunction::cast(*array_function)) {
9909         CacheInitialJSArrayMaps(native_context, new_map);
9910         Handle<Map> new_strong_map = Map::Copy(new_map, "SetInstancePrototype");
9911         new_strong_map->set_is_strong();
9912         CacheInitialJSArrayMaps(native_context, new_strong_map);
9913       }
9914     }
9915
9916     // Deoptimize all code that embeds the previous initial map.
9917     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9918         isolate, DependentCode::kInitialMapChangedGroup);
9919   } else {
9920     // Put the value in the initial map field until an initial map is
9921     // needed.  At that point, a new initial map is created and the
9922     // prototype is put into the initial map where it belongs.
9923     function->set_prototype_or_initial_map(*value);
9924     if (value->IsJSObject()) {
9925       // Optimize as prototype to detach it from its transition tree.
9926       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
9927                                     FAST_PROTOTYPE);
9928     }
9929   }
9930   isolate->heap()->ClearInstanceofCache();
9931 }
9932
9933
9934 void JSFunction::SetPrototype(Handle<JSFunction> function,
9935                               Handle<Object> value) {
9936   DCHECK(function->should_have_prototype());
9937   Handle<Object> construct_prototype = value;
9938
9939   // If the value is not a JSReceiver, store the value in the map's
9940   // constructor field so it can be accessed.  Also, set the prototype
9941   // used for constructing objects to the original object prototype.
9942   // See ECMA-262 13.2.2.
9943   if (!value->IsJSReceiver()) {
9944     // Copy the map so this does not affect unrelated functions.
9945     // Remove map transitions because they point to maps with a
9946     // different prototype.
9947     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
9948
9949     JSObject::MigrateToMap(function, new_map);
9950     new_map->SetConstructor(*value);
9951     new_map->set_non_instance_prototype(true);
9952     Isolate* isolate = new_map->GetIsolate();
9953     construct_prototype = handle(
9954         isolate->context()->native_context()->initial_object_prototype(),
9955         isolate);
9956   } else {
9957     function->map()->set_non_instance_prototype(false);
9958   }
9959
9960   return SetInstancePrototype(function, construct_prototype);
9961 }
9962
9963
9964 bool JSFunction::RemovePrototype() {
9965   Context* native_context = context()->native_context();
9966   Map* no_prototype_map =
9967       is_strict(shared()->language_mode())
9968           ? native_context->strict_function_without_prototype_map()
9969           : native_context->sloppy_function_without_prototype_map();
9970
9971   if (map() == no_prototype_map) return true;
9972
9973 #ifdef DEBUG
9974   if (map() != (is_strict(shared()->language_mode())
9975                     ? native_context->strict_function_map()
9976                     : native_context->sloppy_function_map())) {
9977     return false;
9978   }
9979 #endif
9980
9981   set_map(no_prototype_map);
9982   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9983   return true;
9984 }
9985
9986
9987 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9988                                Handle<Object> prototype) {
9989   if (map->prototype() != *prototype) {
9990     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
9991   }
9992   function->set_prototype_or_initial_map(*map);
9993   map->SetConstructor(*function);
9994 #if TRACE_MAPS
9995   if (FLAG_trace_maps) {
9996     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
9997            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
9998            function->shared()->DebugName()->ToCString().get());
9999   }
10000 #endif
10001 }
10002
10003
10004 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
10005   if (function->has_initial_map()) return;
10006   Isolate* isolate = function->GetIsolate();
10007
10008   // First create a new map with the size and number of in-object properties
10009   // suggested by the function.
10010   InstanceType instance_type;
10011   int instance_size;
10012   int in_object_properties;
10013   if (function->shared()->is_generator()) {
10014     instance_type = JS_GENERATOR_OBJECT_TYPE;
10015     instance_size = JSGeneratorObject::kSize;
10016     in_object_properties = 0;
10017   } else {
10018     instance_type = JS_OBJECT_TYPE;
10019     instance_size = function->shared()->CalculateInstanceSize();
10020     in_object_properties = function->shared()->CalculateInObjectProperties();
10021   }
10022   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10023
10024   // Fetch or allocate prototype.
10025   Handle<Object> prototype;
10026   if (function->has_instance_prototype()) {
10027     prototype = handle(function->instance_prototype(), isolate);
10028   } else {
10029     prototype = isolate->factory()->NewFunctionPrototype(function);
10030   }
10031   map->set_inobject_properties(in_object_properties);
10032   map->set_unused_property_fields(in_object_properties);
10033   DCHECK(map->has_fast_object_elements());
10034
10035   // Finally link initial map and constructor function.
10036   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10037
10038   if (!function->shared()->is_generator()) {
10039     function->StartInobjectSlackTracking();
10040   }
10041 }
10042
10043
10044 void JSFunction::SetInstanceClassName(String* name) {
10045   shared()->set_instance_class_name(name);
10046 }
10047
10048
10049 void JSFunction::PrintName(FILE* out) {
10050   base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10051   PrintF(out, "%s", name.get());
10052 }
10053
10054
10055 // The filter is a pattern that matches function names in this way:
10056 //   "*"      all; the default
10057 //   "-"      all but the top-level function
10058 //   "-name"  all but the function "name"
10059 //   ""       only the top-level function
10060 //   "name"   only the function "name"
10061 //   "name*"  only functions starting with "name"
10062 //   "~"      none; the tilde is not an identifier
10063 bool JSFunction::PassesFilter(const char* raw_filter) {
10064   if (*raw_filter == '*') return true;
10065   String* name = shared()->DebugName();
10066   Vector<const char> filter = CStrVector(raw_filter);
10067   if (filter.length() == 0) return name->length() == 0;
10068   if (filter[0] == '-') {
10069     // Negative filter.
10070     if (filter.length() == 1) {
10071       return (name->length() != 0);
10072     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10073       return false;
10074     }
10075     if (filter[filter.length() - 1] == '*' &&
10076         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10077       return false;
10078     }
10079     return true;
10080
10081   } else if (name->IsUtf8EqualTo(filter)) {
10082     return true;
10083   }
10084   if (filter[filter.length() - 1] == '*' &&
10085       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10086     return true;
10087   }
10088   return false;
10089 }
10090
10091
10092 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
10093   Isolate* isolate = function->GetIsolate();
10094   Handle<Object> name =
10095       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
10096   if (name->IsString()) return Handle<String>::cast(name);
10097   return handle(function->shared()->DebugName(), isolate);
10098 }
10099
10100
10101 void Oddball::Initialize(Isolate* isolate,
10102                          Handle<Oddball> oddball,
10103                          const char* to_string,
10104                          Handle<Object> to_number,
10105                          byte kind) {
10106   Handle<String> internalized_to_string =
10107       isolate->factory()->InternalizeUtf8String(to_string);
10108   oddball->set_to_string(*internalized_to_string);
10109   oddball->set_to_number(*to_number);
10110   oddball->set_kind(kind);
10111 }
10112
10113
10114 void Script::InitLineEnds(Handle<Script> script) {
10115   if (!script->line_ends()->IsUndefined()) return;
10116
10117   Isolate* isolate = script->GetIsolate();
10118
10119   if (!script->source()->IsString()) {
10120     DCHECK(script->source()->IsUndefined());
10121     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10122     script->set_line_ends(*empty);
10123     DCHECK(script->line_ends()->IsFixedArray());
10124     return;
10125   }
10126
10127   Handle<String> src(String::cast(script->source()), isolate);
10128
10129   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10130
10131   if (*array != isolate->heap()->empty_fixed_array()) {
10132     array->set_map(isolate->heap()->fixed_cow_array_map());
10133   }
10134
10135   script->set_line_ends(*array);
10136   DCHECK(script->line_ends()->IsFixedArray());
10137 }
10138
10139
10140 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10141   int line_number = GetLineNumber(script, code_pos);
10142   if (line_number == -1) return -1;
10143
10144   DisallowHeapAllocation no_allocation;
10145   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10146   line_number = line_number - script->line_offset()->value();
10147   if (line_number == 0) return code_pos + script->column_offset()->value();
10148   int prev_line_end_pos =
10149       Smi::cast(line_ends_array->get(line_number - 1))->value();
10150   return code_pos - (prev_line_end_pos + 1);
10151 }
10152
10153
10154 int Script::GetLineNumberWithArray(int code_pos) {
10155   DisallowHeapAllocation no_allocation;
10156   DCHECK(line_ends()->IsFixedArray());
10157   FixedArray* line_ends_array = FixedArray::cast(line_ends());
10158   int line_ends_len = line_ends_array->length();
10159   if (line_ends_len == 0) return -1;
10160
10161   if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
10162     return line_offset()->value();
10163   }
10164
10165   int left = 0;
10166   int right = line_ends_len;
10167   while (int half = (right - left) / 2) {
10168     if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
10169       right -= half;
10170     } else {
10171       left += half;
10172     }
10173   }
10174   return right + line_offset()->value();
10175 }
10176
10177
10178 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10179   InitLineEnds(script);
10180   return script->GetLineNumberWithArray(code_pos);
10181 }
10182
10183
10184 int Script::GetLineNumber(int code_pos) {
10185   DisallowHeapAllocation no_allocation;
10186   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10187
10188   // Slow mode: we do not have line_ends. We have to iterate through source.
10189   if (!source()->IsString()) return -1;
10190
10191   String* source_string = String::cast(source());
10192   int line = 0;
10193   int len = source_string->length();
10194   for (int pos = 0; pos < len; pos++) {
10195     if (pos == code_pos) break;
10196     if (source_string->Get(pos) == '\n') line++;
10197   }
10198   return line;
10199 }
10200
10201
10202 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10203   Isolate* isolate = script->GetIsolate();
10204   Handle<String> name_or_source_url_key =
10205       isolate->factory()->InternalizeOneByteString(
10206           STATIC_CHAR_VECTOR("nameOrSourceURL"));
10207   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10208   Handle<Object> property = Object::GetProperty(
10209       script_wrapper, name_or_source_url_key).ToHandleChecked();
10210   DCHECK(property->IsJSFunction());
10211   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10212   Handle<Object> result;
10213   // Do not check against pending exception, since this function may be called
10214   // when an exception has already been pending.
10215   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10216     return isolate->factory()->undefined_value();
10217   }
10218   return result;
10219 }
10220
10221
10222 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10223   Isolate* isolate = script->GetIsolate();
10224   if (!script->wrapper()->IsUndefined()) {
10225     DCHECK(script->wrapper()->IsWeakCell());
10226     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
10227     if (!cell->cleared()) {
10228       // Return a handle for the existing script wrapper from the cache.
10229       return handle(JSObject::cast(cell->value()));
10230     }
10231     // If we found an empty WeakCell, that means the script wrapper was
10232     // GCed.  We are not notified directly of that, so we decrement here
10233     // so that we at least don't count double for any given script.
10234     isolate->counters()->script_wrappers()->Decrement();
10235   }
10236   // Construct a new script wrapper.
10237   isolate->counters()->script_wrappers()->Increment();
10238   Handle<JSFunction> constructor = isolate->script_function();
10239   Handle<JSValue> result =
10240       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10241   result->set_value(*script);
10242   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
10243   script->set_wrapper(*cell);
10244   return result;
10245 }
10246
10247
10248 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
10249     FunctionLiteral* fun) {
10250   if (shared_function_infos()->IsWeakFixedArray()) {
10251     WeakFixedArray* array = WeakFixedArray::cast(shared_function_infos());
10252     for (int i = 0; i < array->Length(); i++) {
10253       Object* obj = array->Get(i);
10254       if (!obj->IsSharedFunctionInfo()) continue;
10255       SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
10256       if (fun->function_token_position() == shared->function_token_position() &&
10257           fun->start_position() == shared->start_position()) {
10258         return Handle<SharedFunctionInfo>(shared);
10259       }
10260     }
10261   }
10262   return MaybeHandle<SharedFunctionInfo>();
10263 }
10264
10265
10266 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
10267                                    Handle<Object> script_object) {
10268   if (shared->script() == *script_object) return;
10269   // Remove shared function info from old script's list.
10270   if (shared->script()->IsScript()) {
10271     Script* old_script = Script::cast(shared->script());
10272     if (old_script->shared_function_infos()->IsWeakFixedArray()) {
10273       WeakFixedArray* list =
10274           WeakFixedArray::cast(old_script->shared_function_infos());
10275       list->Remove(shared);
10276     }
10277   }
10278   // Add shared function info to new script's list.
10279   if (script_object->IsScript()) {
10280     Handle<Script> script = Handle<Script>::cast(script_object);
10281     Handle<Object> list(script->shared_function_infos(), shared->GetIsolate());
10282 #ifdef DEBUG
10283     bool found = false;
10284     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAddIfNotFound,
10285                                &found);
10286     CHECK(!found);
10287 #else
10288     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAlwaysAdd);
10289 #endif  // DEBUG
10290     script->set_shared_function_infos(*list);
10291   }
10292   // Finally set new script.
10293   shared->set_script(*script_object);
10294 }
10295
10296
10297 String* SharedFunctionInfo::DebugName() {
10298   Object* n = name();
10299   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10300   return String::cast(n);
10301 }
10302
10303
10304 bool SharedFunctionInfo::HasSourceCode() const {
10305   return !script()->IsUndefined() &&
10306          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10307 }
10308
10309
10310 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10311   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10312   Handle<String> source(String::cast(Script::cast(script())->source()));
10313   return GetIsolate()->factory()->NewSubString(
10314       source, start_position(), end_position());
10315 }
10316
10317
10318 bool SharedFunctionInfo::IsInlineable() {
10319   // Check that the function has a script associated with it.
10320   if (!script()->IsScript()) return false;
10321   return !optimization_disabled();
10322 }
10323
10324
10325 int SharedFunctionInfo::SourceSize() {
10326   return end_position() - start_position();
10327 }
10328
10329
10330 int SharedFunctionInfo::CalculateInstanceSize() {
10331   int instance_size =
10332       JSObject::kHeaderSize +
10333       expected_nof_properties() * kPointerSize;
10334   if (instance_size > JSObject::kMaxInstanceSize) {
10335     instance_size = JSObject::kMaxInstanceSize;
10336   }
10337   return instance_size;
10338 }
10339
10340
10341 int SharedFunctionInfo::CalculateInObjectProperties() {
10342   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10343 }
10344
10345
10346 // Output the source code without any allocation in the heap.
10347 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
10348   const SharedFunctionInfo* s = v.value;
10349   // For some native functions there is no source.
10350   if (!s->HasSourceCode()) return os << "<No Source>";
10351
10352   // Get the source for the script which this function came from.
10353   // Don't use String::cast because we don't want more assertion errors while
10354   // we are already creating a stack dump.
10355   String* script_source =
10356       reinterpret_cast<String*>(Script::cast(s->script())->source());
10357
10358   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10359
10360   if (!s->is_toplevel()) {
10361     os << "function ";
10362     Object* name = s->name();
10363     if (name->IsString() && String::cast(name)->length() > 0) {
10364       String::cast(name)->PrintUC16(os);
10365     }
10366   }
10367
10368   int len = s->end_position() - s->start_position();
10369   if (len <= v.max_length || v.max_length < 0) {
10370     script_source->PrintUC16(os, s->start_position(), s->end_position());
10371     return os;
10372   } else {
10373     script_source->PrintUC16(os, s->start_position(),
10374                              s->start_position() + v.max_length);
10375     return os << "...\n";
10376   }
10377 }
10378
10379
10380 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10381   if (code->instruction_size() != recompiled->instruction_size()) return false;
10382   ByteArray* code_relocation = code->relocation_info();
10383   ByteArray* recompiled_relocation = recompiled->relocation_info();
10384   int length = code_relocation->length();
10385   if (length != recompiled_relocation->length()) return false;
10386   int compare = memcmp(code_relocation->GetDataStartAddress(),
10387                        recompiled_relocation->GetDataStartAddress(),
10388                        length);
10389   return compare == 0;
10390 }
10391
10392
10393 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10394   DCHECK(!has_deoptimization_support());
10395   DisallowHeapAllocation no_allocation;
10396   Code* code = this->code();
10397   if (IsCodeEquivalent(code, recompiled)) {
10398     // Copy the deoptimization data from the recompiled code.
10399     code->set_deoptimization_data(recompiled->deoptimization_data());
10400     code->set_has_deoptimization_support(true);
10401   } else {
10402     // TODO(3025757): In case the recompiled isn't equivalent to the
10403     // old code, we have to replace it. We should try to avoid this
10404     // altogether because it flushes valuable type feedback by
10405     // effectively resetting all IC state.
10406     ReplaceCode(recompiled);
10407   }
10408   DCHECK(has_deoptimization_support());
10409 }
10410
10411
10412 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10413   // Disable optimization for the shared function info and mark the
10414   // code as non-optimizable. The marker on the shared function info
10415   // is there because we flush non-optimized code thereby loosing the
10416   // non-optimizable information for the code. When the code is
10417   // regenerated and set on the shared function info it is marked as
10418   // non-optimizable if optimization is disabled for the shared
10419   // function info.
10420   DCHECK(reason != kNoReason);
10421   set_optimization_disabled(true);
10422   set_disable_optimization_reason(reason);
10423   // Code should be the lazy compilation stub or else unoptimized.
10424   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10425   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10426   if (FLAG_trace_opt) {
10427     PrintF("[disabled optimization for ");
10428     ShortPrint();
10429     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10430   }
10431 }
10432
10433
10434 void SharedFunctionInfo::InitFromFunctionLiteral(
10435     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
10436   shared_info->set_length(lit->scope()->default_function_length());
10437   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
10438   shared_info->set_function_token_position(lit->function_token_position());
10439   shared_info->set_start_position(lit->start_position());
10440   shared_info->set_end_position(lit->end_position());
10441   shared_info->set_is_expression(lit->is_expression());
10442   shared_info->set_is_anonymous(lit->is_anonymous());
10443   shared_info->set_inferred_name(*lit->inferred_name());
10444   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
10445   shared_info->set_allows_lazy_compilation_without_context(
10446       lit->AllowsLazyCompilationWithoutContext());
10447   shared_info->set_language_mode(lit->language_mode());
10448   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
10449   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
10450   shared_info->set_ast_node_count(lit->ast_node_count());
10451   shared_info->set_is_function(lit->is_function());
10452   if (lit->dont_optimize_reason() != kNoReason) {
10453     shared_info->DisableOptimization(lit->dont_optimize_reason());
10454   }
10455   shared_info->set_dont_crankshaft(lit->flags() &
10456                                    AstProperties::kDontCrankshaft);
10457   shared_info->set_kind(lit->kind());
10458   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
10459   shared_info->set_asm_function(lit->scope()->asm_function());
10460 }
10461
10462
10463 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10464   DCHECK(!id.IsNone());
10465   Code* unoptimized = code();
10466   DeoptimizationOutputData* data =
10467       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10468   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10469   USE(ignore);
10470   return true;  // Return true if there was no DCHECK.
10471 }
10472
10473
10474 void JSFunction::StartInobjectSlackTracking() {
10475   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10476
10477   Map* map = initial_map();
10478
10479   // No tracking during the snapshot construction phase.
10480   Isolate* isolate = GetIsolate();
10481   if (isolate->serializer_enabled()) return;
10482
10483   if (map->unused_property_fields() == 0) return;
10484
10485   map->set_counter(Map::kSlackTrackingCounterStart);
10486 }
10487
10488
10489 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10490   code()->ClearInlineCaches();
10491   // If we clear ICs, we need to clear the type feedback vector too, since
10492   // CallICs are synced with a feedback vector slot.
10493   ClearTypeFeedbackInfo();
10494   set_ic_age(new_ic_age);
10495   if (code()->kind() == Code::FUNCTION) {
10496     code()->set_profiler_ticks(0);
10497     if (optimization_disabled() &&
10498         opt_count() >= FLAG_max_opt_count) {
10499       // Re-enable optimizations if they were disabled due to opt_count limit.
10500       set_optimization_disabled(false);
10501     }
10502     set_opt_count(0);
10503     set_deopt_count(0);
10504   }
10505 }
10506
10507
10508 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
10509     Context* native_context, BailoutId osr_ast_id) {
10510   DisallowHeapAllocation no_gc;
10511   DCHECK(native_context->IsNativeContext());
10512   Object* value = optimized_code_map();
10513   if (!value->IsSmi()) {
10514     FixedArray* optimized_code_map = FixedArray::cast(value);
10515     int length = optimized_code_map->length();
10516     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10517     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10518       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10519           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10520         return {Code::cast(optimized_code_map->get(i + kCachedCodeOffset)),
10521                 FixedArray::cast(optimized_code_map->get(i + kLiteralsOffset))};
10522       }
10523     }
10524     Object* shared_code = optimized_code_map->get(kSharedCodeIndex);
10525     if (shared_code->IsCode() && osr_ast_id.IsNone()) {
10526       return {Code::cast(shared_code), nullptr};
10527     }
10528     if (FLAG_trace_opt) {
10529       PrintF("[didn't find optimized code in optimized code map for ");
10530       ShortPrint();
10531       PrintF("]\n");
10532     }
10533   }
10534   return {nullptr, nullptr};
10535 }
10536
10537
10538 #define DECLARE_TAG(ignore1, name, ignore2) name,
10539 const char* const VisitorSynchronization::kTags[
10540     VisitorSynchronization::kNumberOfSyncTags] = {
10541   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10542 };
10543 #undef DECLARE_TAG
10544
10545
10546 #define DECLARE_TAG(ignore1, ignore2, name) name,
10547 const char* const VisitorSynchronization::kTagNames[
10548     VisitorSynchronization::kNumberOfSyncTags] = {
10549   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10550 };
10551 #undef DECLARE_TAG
10552
10553
10554 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10555   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10556   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10557   Object* old_target = target;
10558   VisitPointer(&target);
10559   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10560 }
10561
10562
10563 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10564   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10565   Object* stub = rinfo->code_age_stub();
10566   if (stub) {
10567     VisitPointer(&stub);
10568   }
10569 }
10570
10571
10572 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10573   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10574   Object* old_code = code;
10575   VisitPointer(&code);
10576   if (code != old_code) {
10577     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10578   }
10579 }
10580
10581
10582 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10583   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10584   Object* cell = rinfo->target_cell();
10585   Object* old_cell = cell;
10586   VisitPointer(&cell);
10587   if (cell != old_cell) {
10588     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10589   }
10590 }
10591
10592
10593 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10594   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10595          rinfo->IsPatchedDebugBreakSlotSequence());
10596   Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
10597   Object* old_target = target;
10598   VisitPointer(&target);
10599   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10600 }
10601
10602
10603 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10604   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10605   Object* p = rinfo->target_object();
10606   VisitPointer(&p);
10607 }
10608
10609
10610 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10611   Address p = rinfo->target_external_reference();
10612   VisitExternalReference(&p);
10613 }
10614
10615
10616 void Code::InvalidateRelocation() {
10617   InvalidateEmbeddedObjects();
10618   set_relocation_info(GetHeap()->empty_byte_array());
10619 }
10620
10621
10622 void Code::InvalidateEmbeddedObjects() {
10623   Object* undefined = GetHeap()->undefined_value();
10624   Cell* undefined_cell = GetHeap()->undefined_cell();
10625   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10626                   RelocInfo::ModeMask(RelocInfo::CELL);
10627   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10628     RelocInfo::Mode mode = it.rinfo()->rmode();
10629     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10630       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10631     } else if (mode == RelocInfo::CELL) {
10632       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10633     }
10634   }
10635 }
10636
10637
10638 void Code::Relocate(intptr_t delta) {
10639   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10640     it.rinfo()->apply(delta);
10641   }
10642   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10643 }
10644
10645
10646 void Code::CopyFrom(const CodeDesc& desc) {
10647   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10648
10649   // copy code
10650   CopyBytes(instruction_start(), desc.buffer,
10651             static_cast<size_t>(desc.instr_size));
10652
10653   // copy reloc info
10654   CopyBytes(relocation_start(),
10655             desc.buffer + desc.buffer_size - desc.reloc_size,
10656             static_cast<size_t>(desc.reloc_size));
10657
10658   // unbox handles and relocate
10659   intptr_t delta = instruction_start() - desc.buffer;
10660   int mode_mask = RelocInfo::kCodeTargetMask |
10661                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10662                   RelocInfo::ModeMask(RelocInfo::CELL) |
10663                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10664                   RelocInfo::kApplyMask;
10665   // Needed to find target_object and runtime_entry on X64
10666   Assembler* origin = desc.origin;
10667   AllowDeferredHandleDereference embedding_raw_address;
10668   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10669     RelocInfo::Mode mode = it.rinfo()->rmode();
10670     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10671       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10672       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10673     } else if (mode == RelocInfo::CELL) {
10674       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10675       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10676     } else if (RelocInfo::IsCodeTarget(mode)) {
10677       // rewrite code handles in inline cache targets to direct
10678       // pointers to the first instruction in the code object
10679       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10680       Code* code = Code::cast(*p);
10681       it.rinfo()->set_target_address(code->instruction_start(),
10682                                      SKIP_WRITE_BARRIER,
10683                                      SKIP_ICACHE_FLUSH);
10684     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10685       Address p = it.rinfo()->target_runtime_entry(origin);
10686       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10687                                            SKIP_ICACHE_FLUSH);
10688     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10689       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10690       Code* code = Code::cast(*p);
10691       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10692     } else {
10693       it.rinfo()->apply(delta);
10694     }
10695   }
10696   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10697 }
10698
10699
10700 // Locate the source position which is closest to the address in the code. This
10701 // is using the source position information embedded in the relocation info.
10702 // The position returned is relative to the beginning of the script where the
10703 // source for this function is found.
10704 int Code::SourcePosition(Address pc) {
10705   int distance = kMaxInt;
10706   int position = RelocInfo::kNoPosition;  // Initially no position found.
10707   // Run through all the relocation info to find the best matching source
10708   // position. All the code needs to be considered as the sequence of the
10709   // instructions in the code does not necessarily follow the same order as the
10710   // source.
10711   RelocIterator it(this, RelocInfo::kPositionMask);
10712   while (!it.done()) {
10713     // Only look at positions after the current pc.
10714     if (it.rinfo()->pc() < pc) {
10715       // Get position and distance.
10716
10717       int dist = static_cast<int>(pc - it.rinfo()->pc());
10718       int pos = static_cast<int>(it.rinfo()->data());
10719       // If this position is closer than the current candidate or if it has the
10720       // same distance as the current candidate and the position is higher then
10721       // this position is the new candidate.
10722       if ((dist < distance) ||
10723           (dist == distance && pos > position)) {
10724         position = pos;
10725         distance = dist;
10726       }
10727     }
10728     it.next();
10729   }
10730   return position;
10731 }
10732
10733
10734 // Same as Code::SourcePosition above except it only looks for statement
10735 // positions.
10736 int Code::SourceStatementPosition(Address pc) {
10737   // First find the position as close as possible using all position
10738   // information.
10739   int position = SourcePosition(pc);
10740   // Now find the closest statement position before the position.
10741   int statement_position = 0;
10742   RelocIterator it(this, RelocInfo::kPositionMask);
10743   while (!it.done()) {
10744     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10745       int p = static_cast<int>(it.rinfo()->data());
10746       if (statement_position < p && p <= position) {
10747         statement_position = p;
10748       }
10749     }
10750     it.next();
10751   }
10752   return statement_position;
10753 }
10754
10755
10756 SafepointEntry Code::GetSafepointEntry(Address pc) {
10757   SafepointTable table(this);
10758   return table.FindEntry(pc);
10759 }
10760
10761
10762 Object* Code::FindNthObject(int n, Map* match_map) {
10763   DCHECK(is_inline_cache_stub());
10764   DisallowHeapAllocation no_allocation;
10765   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10766   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10767     RelocInfo* info = it.rinfo();
10768     Object* object = info->target_object();
10769     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10770     if (object->IsHeapObject()) {
10771       if (HeapObject::cast(object)->map() == match_map) {
10772         if (--n == 0) return object;
10773       }
10774     }
10775   }
10776   return NULL;
10777 }
10778
10779
10780 AllocationSite* Code::FindFirstAllocationSite() {
10781   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10782   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10783 }
10784
10785
10786 Map* Code::FindFirstMap() {
10787   Object* result = FindNthObject(1, GetHeap()->meta_map());
10788   return (result != NULL) ? Map::cast(result) : NULL;
10789 }
10790
10791
10792 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10793   DCHECK(is_inline_cache_stub() || is_handler());
10794   DisallowHeapAllocation no_allocation;
10795   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10796   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10797   int current_pattern = 0;
10798   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10799     RelocInfo* info = it.rinfo();
10800     Object* object = info->target_object();
10801     if (object->IsHeapObject()) {
10802       if (object->IsWeakCell()) {
10803         object = HeapObject::cast(WeakCell::cast(object)->value());
10804       }
10805       Map* map = HeapObject::cast(object)->map();
10806       if (map == *pattern.find_[current_pattern]) {
10807         info->set_target_object(*pattern.replace_[current_pattern]);
10808         if (++current_pattern == pattern.count_) return;
10809       }
10810     }
10811   }
10812   UNREACHABLE();
10813 }
10814
10815
10816 void Code::FindAllMaps(MapHandleList* maps) {
10817   DCHECK(is_inline_cache_stub());
10818   DisallowHeapAllocation no_allocation;
10819   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10820   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10821     RelocInfo* info = it.rinfo();
10822     Object* object = info->target_object();
10823     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10824     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10825   }
10826 }
10827
10828
10829 Code* Code::FindFirstHandler() {
10830   DCHECK(is_inline_cache_stub());
10831   DisallowHeapAllocation no_allocation;
10832   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10833              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10834   bool skip_next_handler = false;
10835   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10836     RelocInfo* info = it.rinfo();
10837     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10838       Object* obj = info->target_object();
10839       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10840     } else {
10841       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10842       if (code->kind() == Code::HANDLER) {
10843         if (!skip_next_handler) return code;
10844         skip_next_handler = false;
10845       }
10846     }
10847   }
10848   return NULL;
10849 }
10850
10851
10852 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10853   DCHECK(is_inline_cache_stub());
10854   DisallowHeapAllocation no_allocation;
10855   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10856              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10857   bool skip_next_handler = false;
10858   int i = 0;
10859   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10860     if (i == length) return true;
10861     RelocInfo* info = it.rinfo();
10862     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10863       Object* obj = info->target_object();
10864       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10865     } else {
10866       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10867       // IC stubs with handlers never contain non-handler code objects before
10868       // handler targets.
10869       if (code->kind() != Code::HANDLER) break;
10870       if (!skip_next_handler) {
10871         code_list->Add(Handle<Code>(code));
10872         i++;
10873       }
10874       skip_next_handler = false;
10875     }
10876   }
10877   return i == length;
10878 }
10879
10880
10881 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
10882   DCHECK(is_inline_cache_stub());
10883   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10884              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10885   bool return_next = false;
10886   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10887     RelocInfo* info = it.rinfo();
10888     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10889       Object* object = info->target_object();
10890       if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10891       if (object == map) return_next = true;
10892     } else if (return_next) {
10893       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10894       DCHECK(code->kind() == Code::HANDLER);
10895       return handle(code);
10896     }
10897   }
10898   return MaybeHandle<Code>();
10899 }
10900
10901
10902 Name* Code::FindFirstName() {
10903   DCHECK(is_inline_cache_stub());
10904   DisallowHeapAllocation no_allocation;
10905   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10906   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10907     RelocInfo* info = it.rinfo();
10908     Object* object = info->target_object();
10909     if (object->IsName()) return Name::cast(object);
10910   }
10911   return NULL;
10912 }
10913
10914
10915 void Code::ClearInlineCaches() {
10916   ClearInlineCaches(NULL);
10917 }
10918
10919
10920 void Code::ClearInlineCaches(Code::Kind kind) {
10921   ClearInlineCaches(&kind);
10922 }
10923
10924
10925 void Code::ClearInlineCaches(Code::Kind* kind) {
10926   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10927              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10928              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10929   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10930     RelocInfo* info = it.rinfo();
10931     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10932     if (target->is_inline_cache_stub()) {
10933       if (kind == NULL || *kind == target->kind()) {
10934         IC::Clear(this->GetIsolate(), info->pc(),
10935                   info->host()->constant_pool());
10936       }
10937     }
10938   }
10939 }
10940
10941
10942 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
10943   feedback_vector()->ClearSlots(this);
10944   feedback_vector()->ClearICSlots(this);
10945 }
10946
10947
10948 void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
10949   feedback_vector()->ClearSlotsAtGCTime(this);
10950   feedback_vector()->ClearICSlotsAtGCTime(this);
10951 }
10952
10953
10954 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
10955   DisallowHeapAllocation no_gc;
10956   DCHECK(kind() == FUNCTION);
10957   BackEdgeTable back_edges(this, &no_gc);
10958   for (uint32_t i = 0; i < back_edges.length(); i++) {
10959     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10960   }
10961   return BailoutId::None();
10962 }
10963
10964
10965 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
10966   DisallowHeapAllocation no_gc;
10967   DCHECK(kind() == FUNCTION);
10968   BackEdgeTable back_edges(this, &no_gc);
10969   for (uint32_t i = 0; i < back_edges.length(); i++) {
10970     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10971   }
10972   UNREACHABLE();  // We expect to find the back edge.
10973   return 0;
10974 }
10975
10976
10977 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10978   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10979 }
10980
10981
10982 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10983   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10984       NO_MARKING_PARITY);
10985 }
10986
10987
10988 // NextAge defines the Code::Age state transitions during a GC cycle.
10989 static Code::Age NextAge(Code::Age age) {
10990   switch (age) {
10991     case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
10992     case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
10993     case Code::kLastCodeAge:  // Clamp at last Code::Age value.
10994       return age;
10995     case Code::kExecutedOnceCodeAge:
10996       // Pre-age code that has only been executed once.
10997       return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
10998     default:
10999       return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
11000   }
11001 }
11002
11003
11004 // IsOldAge defines the collection criteria for a Code object.
11005 static bool IsOldAge(Code::Age age) {
11006   return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
11007 }
11008
11009
11010 void Code::MakeYoung(Isolate* isolate) {
11011   byte* sequence = FindCodeAgeSequence();
11012   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
11013 }
11014
11015
11016 void Code::MarkToBeExecutedOnce(Isolate* isolate) {
11017   byte* sequence = FindCodeAgeSequence();
11018   if (sequence != NULL) {
11019     PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
11020                          NO_MARKING_PARITY);
11021   }
11022 }
11023
11024
11025 void Code::MakeOlder(MarkingParity current_parity) {
11026   byte* sequence = FindCodeAgeSequence();
11027   if (sequence != NULL) {
11028     Age age;
11029     MarkingParity code_parity;
11030     Isolate* isolate = GetIsolate();
11031     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11032     Age next_age = NextAge(age);
11033     if (age != next_age && code_parity != current_parity) {
11034       PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
11035     }
11036   }
11037 }
11038
11039
11040 bool Code::IsOld() {
11041   return IsOldAge(GetAge());
11042 }
11043
11044
11045 byte* Code::FindCodeAgeSequence() {
11046   return FLAG_age_code &&
11047       prologue_offset() != Code::kPrologueOffsetNotSet &&
11048       (kind() == OPTIMIZED_FUNCTION ||
11049        (kind() == FUNCTION && !has_debug_break_slots()))
11050       ? instruction_start() + prologue_offset()
11051       : NULL;
11052 }
11053
11054
11055 Code::Age Code::GetAge() {
11056   byte* sequence = FindCodeAgeSequence();
11057   if (sequence == NULL) {
11058     return kNoAgeCodeAge;
11059   }
11060   Age age;
11061   MarkingParity parity;
11062   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11063   return age;
11064 }
11065
11066
11067 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11068                                MarkingParity* parity) {
11069   Isolate* isolate = code->GetIsolate();
11070   Builtins* builtins = isolate->builtins();
11071   Code* stub = NULL;
11072 #define HANDLE_CODE_AGE(AGE)                                            \
11073   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11074   if (code == stub) {                                                   \
11075     *age = k##AGE##CodeAge;                                             \
11076     *parity = EVEN_MARKING_PARITY;                                      \
11077     return;                                                             \
11078   }                                                                     \
11079   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11080   if (code == stub) {                                                   \
11081     *age = k##AGE##CodeAge;                                             \
11082     *parity = ODD_MARKING_PARITY;                                       \
11083     return;                                                             \
11084   }
11085   CODE_AGE_LIST(HANDLE_CODE_AGE)
11086 #undef HANDLE_CODE_AGE
11087   stub = *builtins->MarkCodeAsExecutedOnce();
11088   if (code == stub) {
11089     *age = kNotExecutedCodeAge;
11090     *parity = NO_MARKING_PARITY;
11091     return;
11092   }
11093   stub = *builtins->MarkCodeAsExecutedTwice();
11094   if (code == stub) {
11095     *age = kExecutedOnceCodeAge;
11096     *parity = NO_MARKING_PARITY;
11097     return;
11098   }
11099   stub = *builtins->MarkCodeAsToBeExecutedOnce();
11100   if (code == stub) {
11101     *age = kToBeExecutedOnceCodeAge;
11102     *parity = NO_MARKING_PARITY;
11103     return;
11104   }
11105   UNREACHABLE();
11106 }
11107
11108
11109 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11110   Builtins* builtins = isolate->builtins();
11111   switch (age) {
11112 #define HANDLE_CODE_AGE(AGE)                                            \
11113     case k##AGE##CodeAge: {                                             \
11114       Code* stub = parity == EVEN_MARKING_PARITY                        \
11115           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11116           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11117       return stub;                                                      \
11118     }
11119     CODE_AGE_LIST(HANDLE_CODE_AGE)
11120 #undef HANDLE_CODE_AGE
11121     case kNotExecutedCodeAge: {
11122       DCHECK(parity == NO_MARKING_PARITY);
11123       return *builtins->MarkCodeAsExecutedOnce();
11124     }
11125     case kExecutedOnceCodeAge: {
11126       DCHECK(parity == NO_MARKING_PARITY);
11127       return *builtins->MarkCodeAsExecutedTwice();
11128     }
11129     case kToBeExecutedOnceCodeAge: {
11130       DCHECK(parity == NO_MARKING_PARITY);
11131       return *builtins->MarkCodeAsToBeExecutedOnce();
11132     }
11133     default:
11134       UNREACHABLE();
11135       break;
11136   }
11137   return NULL;
11138 }
11139
11140
11141 void Code::PrintDeoptLocation(FILE* out, Address pc) {
11142   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
11143   class SourcePosition pos = info.position;
11144   if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
11145     if (FLAG_hydrogen_track_positions) {
11146       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
11147              pos.inlining_id(), pos.position(),
11148              Deoptimizer::GetDeoptReason(info.deopt_reason));
11149     } else {
11150       PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
11151              Deoptimizer::GetDeoptReason(info.deopt_reason));
11152     }
11153   }
11154 }
11155
11156
11157 bool Code::CanDeoptAt(Address pc) {
11158   DeoptimizationInputData* deopt_data =
11159       DeoptimizationInputData::cast(deoptimization_data());
11160   Address code_start_address = instruction_start();
11161   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11162     if (deopt_data->Pc(i)->value() == -1) continue;
11163     Address address = code_start_address + deopt_data->Pc(i)->value();
11164     if (address == pc) return true;
11165   }
11166   return false;
11167 }
11168
11169
11170 // Identify kind of code.
11171 const char* Code::Kind2String(Kind kind) {
11172   switch (kind) {
11173 #define CASE(name) case name: return #name;
11174     CODE_KIND_LIST(CASE)
11175 #undef CASE
11176     case NUMBER_OF_KINDS: break;
11177   }
11178   UNREACHABLE();
11179   return NULL;
11180 }
11181
11182
11183 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
11184   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
11185   WeakCell* raw_cell = code->CachedWeakCell();
11186   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
11187   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
11188   DeoptimizationInputData::cast(code->deoptimization_data())
11189       ->SetWeakCellCache(*cell);
11190   return cell;
11191 }
11192
11193
11194 WeakCell* Code::CachedWeakCell() {
11195   DCHECK(kind() == OPTIMIZED_FUNCTION);
11196   Object* weak_cell_cache =
11197       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
11198   if (weak_cell_cache->IsWeakCell()) {
11199     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
11200     return WeakCell::cast(weak_cell_cache);
11201   }
11202   return NULL;
11203 }
11204
11205
11206 #ifdef ENABLE_DISASSEMBLER
11207
11208 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11209     std::ostream& os) {  // NOLINT
11210   disasm::NameConverter converter;
11211   int const inlined_function_count = InlinedFunctionCount()->value();
11212   os << "Inlined functions (count = " << inlined_function_count << ")\n";
11213   for (int id = 0; id < inlined_function_count; ++id) {
11214     Object* info = LiteralArray()->get(id);
11215     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
11216   }
11217   os << "\n";
11218   int deopt_count = DeoptCount();
11219   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11220   if (0 != deopt_count) {
11221     os << " index  ast id    argc     pc";
11222     if (FLAG_print_code_verbose) os << "  commands";
11223     os << "\n";
11224   }
11225   for (int i = 0; i < deopt_count; i++) {
11226     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
11227        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
11228        << std::setw(6) << Pc(i)->value();
11229
11230     if (!FLAG_print_code_verbose) {
11231       os << "\n";
11232       continue;
11233     }
11234     // Print details of the frame translation.
11235     int translation_index = TranslationIndex(i)->value();
11236     TranslationIterator iterator(TranslationByteArray(), translation_index);
11237     Translation::Opcode opcode =
11238         static_cast<Translation::Opcode>(iterator.Next());
11239     DCHECK(Translation::BEGIN == opcode);
11240     int frame_count = iterator.Next();
11241     int jsframe_count = iterator.Next();
11242     os << "  " << Translation::StringFor(opcode)
11243        << " {frame count=" << frame_count
11244        << ", js frame count=" << jsframe_count << "}\n";
11245
11246     while (iterator.HasNext() &&
11247            Translation::BEGIN !=
11248            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11249       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
11250
11251       switch (opcode) {
11252         case Translation::BEGIN:
11253           UNREACHABLE();
11254           break;
11255
11256         case Translation::JS_FRAME: {
11257           int ast_id = iterator.Next();
11258           int shared_info_id = iterator.Next();
11259           unsigned height = iterator.Next();
11260           Object* shared_info = LiteralArray()->get(shared_info_id);
11261           os << "{ast_id=" << ast_id << ", function="
11262              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11263              << ", height=" << height << "}";
11264           break;
11265         }
11266
11267         case Translation::JS_FRAME_FUNCTION: {
11268           os << "{function}";
11269           break;
11270         }
11271
11272         case Translation::COMPILED_STUB_FRAME: {
11273           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11274           os << "{kind=" << stub_kind << "}";
11275           break;
11276         }
11277
11278         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11279         case Translation::CONSTRUCT_STUB_FRAME: {
11280           int shared_info_id = iterator.Next();
11281           Object* shared_info = LiteralArray()->get(shared_info_id);
11282           unsigned height = iterator.Next();
11283           os << "{function="
11284              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11285              << ", height=" << height << "}";
11286           break;
11287         }
11288
11289         case Translation::GETTER_STUB_FRAME:
11290         case Translation::SETTER_STUB_FRAME: {
11291           int shared_info_id = iterator.Next();
11292           Object* shared_info = LiteralArray()->get(shared_info_id);
11293           os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
11294                                           ->DebugName()) << "}";
11295           break;
11296         }
11297
11298         case Translation::REGISTER: {
11299           int reg_code = iterator.Next();
11300           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11301           break;
11302         }
11303
11304         case Translation::INT32_REGISTER: {
11305           int reg_code = iterator.Next();
11306           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11307           break;
11308         }
11309
11310         case Translation::UINT32_REGISTER: {
11311           int reg_code = iterator.Next();
11312           os << "{input=" << converter.NameOfCPURegister(reg_code)
11313              << " (unsigned)}";
11314           break;
11315         }
11316
11317         case Translation::BOOL_REGISTER: {
11318           int reg_code = iterator.Next();
11319           os << "{input=" << converter.NameOfCPURegister(reg_code)
11320              << " (bool)}";
11321           break;
11322         }
11323
11324         case Translation::DOUBLE_REGISTER: {
11325           int reg_code = iterator.Next();
11326           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11327              << "}";
11328           break;
11329         }
11330
11331         case Translation::STACK_SLOT: {
11332           int input_slot_index = iterator.Next();
11333           os << "{input=" << input_slot_index << "}";
11334           break;
11335         }
11336
11337         case Translation::INT32_STACK_SLOT: {
11338           int input_slot_index = iterator.Next();
11339           os << "{input=" << input_slot_index << "}";
11340           break;
11341         }
11342
11343         case Translation::UINT32_STACK_SLOT: {
11344           int input_slot_index = iterator.Next();
11345           os << "{input=" << input_slot_index << " (unsigned)}";
11346           break;
11347         }
11348
11349         case Translation::BOOL_STACK_SLOT: {
11350           int input_slot_index = iterator.Next();
11351           os << "{input=" << input_slot_index << " (bool)}";
11352           break;
11353         }
11354
11355         case Translation::DOUBLE_STACK_SLOT: {
11356           int input_slot_index = iterator.Next();
11357           os << "{input=" << input_slot_index << "}";
11358           break;
11359         }
11360
11361         case Translation::LITERAL: {
11362           unsigned literal_index = iterator.Next();
11363           os << "{literal_id=" << literal_index << "}";
11364           break;
11365         }
11366
11367         case Translation::DUPLICATED_OBJECT: {
11368           int object_index = iterator.Next();
11369           os << "{object_index=" << object_index << "}";
11370           break;
11371         }
11372
11373         case Translation::ARGUMENTS_OBJECT:
11374         case Translation::CAPTURED_OBJECT: {
11375           int args_length = iterator.Next();
11376           os << "{length=" << args_length << "}";
11377           break;
11378         }
11379       }
11380       os << "\n";
11381     }
11382   }
11383 }
11384
11385
11386 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11387     std::ostream& os) {  // NOLINT
11388   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11389      << ")\n";
11390   if (this->DeoptPoints() == 0) return;
11391
11392   os << "ast id        pc  state\n";
11393   for (int i = 0; i < this->DeoptPoints(); i++) {
11394     int pc_and_state = this->PcAndState(i)->value();
11395     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
11396        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
11397        << FullCodeGenerator::State2String(
11398               FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
11399   }
11400 }
11401
11402
11403 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
11404   os << "   from   to       hdlr\n";
11405   for (int i = 0; i < length(); i += kRangeEntrySize) {
11406     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
11407     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
11408     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
11409     int handler_offset = HandlerOffsetField::decode(handler_field);
11410     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11411     int depth = Smi::cast(get(i + kRangeDepthIndex))->value();
11412     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
11413        << ")  ->  " << std::setw(4) << handler_offset
11414        << " (prediction=" << prediction << ", depth=" << depth << ")\n";
11415   }
11416 }
11417
11418
11419 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
11420   os << "   off      hdlr (c)\n";
11421   for (int i = 0; i < length(); i += kReturnEntrySize) {
11422     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
11423     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
11424     int handler_offset = HandlerOffsetField::decode(handler_field);
11425     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11426     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
11427        << handler_offset << " (prediction=" << prediction << ")\n";
11428   }
11429 }
11430
11431
11432 const char* Code::ICState2String(InlineCacheState state) {
11433   switch (state) {
11434     case UNINITIALIZED: return "UNINITIALIZED";
11435     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11436     case MONOMORPHIC: return "MONOMORPHIC";
11437     case PROTOTYPE_FAILURE:
11438       return "PROTOTYPE_FAILURE";
11439     case POLYMORPHIC: return "POLYMORPHIC";
11440     case MEGAMORPHIC: return "MEGAMORPHIC";
11441     case GENERIC: return "GENERIC";
11442     case DEBUG_STUB: return "DEBUG_STUB";
11443     case DEFAULT:
11444       return "DEFAULT";
11445   }
11446   UNREACHABLE();
11447   return NULL;
11448 }
11449
11450
11451 const char* Code::StubType2String(StubType type) {
11452   switch (type) {
11453     case NORMAL: return "NORMAL";
11454     case FAST: return "FAST";
11455   }
11456   UNREACHABLE();  // keep the compiler happy
11457   return NULL;
11458 }
11459
11460
11461 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
11462                              Kind kind, ExtraICState extra) {
11463   os << "extra_ic_state = ";
11464   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
11465       is_strict(static_cast<LanguageMode>(extra))) {
11466     os << "STRICT\n";
11467   } else {
11468     os << extra << "\n";
11469   }
11470 }
11471
11472
11473 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
11474   os << "kind = " << Kind2String(kind()) << "\n";
11475   if (IsCodeStubOrIC()) {
11476     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11477     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11478   }
11479   if (is_inline_cache_stub()) {
11480     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11481     PrintExtraICState(os, kind(), extra_ic_state());
11482     if (ic_state() == MONOMORPHIC) {
11483       os << "type = " << StubType2String(type()) << "\n";
11484     }
11485     if (is_compare_ic_stub()) {
11486       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11487       CompareICStub stub(stub_key(), GetIsolate());
11488       os << "compare_state = " << CompareICState::GetStateName(stub.left())
11489          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
11490          << CompareICState::GetStateName(stub.state()) << "\n";
11491       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
11492     }
11493   }
11494   if ((name != NULL) && (name[0] != '\0')) {
11495     os << "name = " << name << "\n";
11496   }
11497   if (kind() == OPTIMIZED_FUNCTION) {
11498     os << "stack_slots = " << stack_slots() << "\n";
11499   }
11500   os << "compiler = " << (is_turbofanned()
11501                               ? "turbofan"
11502                               : is_crankshafted() ? "crankshaft"
11503                                                   : kind() == Code::FUNCTION
11504                                                         ? "full-codegen"
11505                                                         : "unknown") << "\n";
11506
11507   os << "Instructions (size = " << instruction_size() << ")\n";
11508   {
11509     Isolate* isolate = GetIsolate();
11510     int size = instruction_size();
11511     int safepoint_offset =
11512         is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
11513     int back_edge_offset = (kind() == Code::FUNCTION)
11514                                ? static_cast<int>(back_edge_table_offset())
11515                                : size;
11516     int constant_pool_offset = FLAG_enable_embedded_constant_pool
11517                                    ? this->constant_pool_offset()
11518                                    : size;
11519
11520     // Stop before reaching any embedded tables
11521     int code_size = Min(safepoint_offset, back_edge_offset);
11522     code_size = Min(code_size, constant_pool_offset);
11523     byte* begin = instruction_start();
11524     byte* end = begin + code_size;
11525     Disassembler::Decode(isolate, &os, begin, end, this);
11526
11527     if (constant_pool_offset < size) {
11528       int constant_pool_size = size - constant_pool_offset;
11529       DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
11530       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
11531       Vector<char> buf = Vector<char>::New(50);
11532       intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
11533       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
11534         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
11535         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
11536       }
11537     }
11538   }
11539   os << "\n";
11540
11541   if (kind() == FUNCTION) {
11542     DeoptimizationOutputData* data =
11543         DeoptimizationOutputData::cast(this->deoptimization_data());
11544     data->DeoptimizationOutputDataPrint(os);
11545   } else if (kind() == OPTIMIZED_FUNCTION) {
11546     DeoptimizationInputData* data =
11547         DeoptimizationInputData::cast(this->deoptimization_data());
11548     data->DeoptimizationInputDataPrint(os);
11549   }
11550   os << "\n";
11551
11552   if (is_crankshafted()) {
11553     SafepointTable table(this);
11554     os << "Safepoints (size = " << table.size() << ")\n";
11555     for (unsigned i = 0; i < table.length(); i++) {
11556       unsigned pc_offset = table.GetPcOffset(i);
11557       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
11558       os << std::setw(4) << pc_offset << "  ";
11559       table.PrintEntry(i, os);
11560       os << " (sp -> fp)  ";
11561       SafepointEntry entry = table.GetEntry(i);
11562       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11563         os << std::setw(6) << entry.deoptimization_index();
11564       } else {
11565         os << "<none>";
11566       }
11567       if (entry.argument_count() > 0) {
11568         os << " argc: " << entry.argument_count();
11569       }
11570       os << "\n";
11571     }
11572     os << "\n";
11573   } else if (kind() == FUNCTION) {
11574     unsigned offset = back_edge_table_offset();
11575     // If there is no back edge table, the "table start" will be at or after
11576     // (due to alignment) the end of the instruction stream.
11577     if (static_cast<int>(offset) < instruction_size()) {
11578       DisallowHeapAllocation no_gc;
11579       BackEdgeTable back_edges(this, &no_gc);
11580
11581       os << "Back edges (size = " << back_edges.length() << ")\n";
11582       os << "ast_id  pc_offset  loop_depth\n";
11583
11584       for (uint32_t i = 0; i < back_edges.length(); i++) {
11585         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
11586            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
11587            << back_edges.loop_depth(i) << "\n";
11588       }
11589
11590       os << "\n";
11591     }
11592 #ifdef OBJECT_PRINT
11593     if (!type_feedback_info()->IsUndefined()) {
11594       OFStream os(stdout);
11595       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11596       os << "\n";
11597     }
11598 #endif
11599   }
11600
11601   if (handler_table()->length() > 0) {
11602     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
11603     if (kind() == FUNCTION) {
11604       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
11605     } else if (kind() == OPTIMIZED_FUNCTION) {
11606       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
11607     }
11608     os << "\n";
11609   }
11610
11611   os << "RelocInfo (size = " << relocation_size() << ")\n";
11612   for (RelocIterator it(this); !it.done(); it.next()) {
11613     it.rinfo()->Print(GetIsolate(), os);
11614   }
11615   os << "\n";
11616 }
11617 #endif  // ENABLE_DISASSEMBLER
11618
11619
11620 void BytecodeArray::Disassemble(std::ostream& os) {
11621   os << "Frame size " << frame_size() << "\n";
11622   Vector<char> buf = Vector<char>::New(50);
11623   int bytecode_size = 0;
11624   for (int i = 0; i < this->length(); i += bytecode_size) {
11625     interpreter::Bytecode bytecode = static_cast<interpreter::Bytecode>(get(i));
11626     bytecode_size = interpreter::Bytecodes::Size(bytecode);
11627
11628     SNPrintF(buf, "%p : ", GetFirstBytecodeAddress() + i);
11629     os << buf.start();
11630     for (int j = 0; j < bytecode_size; j++) {
11631       SNPrintF(buf, "%02x ", get(i + j));
11632       os << buf.start();
11633     }
11634     for (int j = bytecode_size; j < interpreter::Bytecodes::kMaximumSize; j++) {
11635       os << "   ";
11636     }
11637     os << bytecode << "\n";
11638   }
11639 }
11640
11641
11642 // static
11643 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11644   DCHECK(capacity >= 0);
11645   array->GetIsolate()->factory()->NewJSArrayStorage(
11646       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11647 }
11648
11649
11650 // Returns false if the passed-in index is marked non-configurable, which will
11651 // cause the truncation operation to halt, and thus no further old values need
11652 // be collected.
11653 static bool GetOldValue(Isolate* isolate,
11654                         Handle<JSObject> object,
11655                         uint32_t index,
11656                         List<Handle<Object> >* old_values,
11657                         List<uint32_t>* indices) {
11658   LookupIterator it(isolate, object, index, LookupIterator::HIDDEN);
11659   CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
11660   DCHECK(it.IsFound());
11661   if (!it.IsConfigurable()) return false;
11662   Handle<Object> value =
11663       it.state() == LookupIterator::ACCESSOR
11664           ? Handle<Object>::cast(isolate->factory()->the_hole_value())
11665           : JSReceiver::GetDataProperty(&it);
11666   old_values->Add(value);
11667   indices->Add(index);
11668   return true;
11669 }
11670
11671
11672 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
11673   // We should never end in here with a pixel or external array.
11674   DCHECK(array->AllowsSetLength());
11675   if (array->SetLengthWouldNormalize(new_length)) {
11676     JSObject::NormalizeElements(array);
11677   }
11678   array->GetElementsAccessor()->SetLength(array, new_length);
11679 }
11680
11681
11682 MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
11683                                                  uint32_t new_length) {
11684   if (!array->map()->is_observed()) {
11685     SetLength(array, new_length);
11686     return array;
11687   }
11688
11689   Isolate* isolate = array->GetIsolate();
11690   List<uint32_t> indices;
11691   List<Handle<Object> > old_values;
11692   Handle<Object> old_length_handle(array->length(), isolate);
11693   uint32_t old_length = 0;
11694   CHECK(old_length_handle->ToArrayLength(&old_length));
11695
11696   static const PropertyAttributes kNoAttrFilter = NONE;
11697   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11698   if (num_elements > 0) {
11699     if (old_length == static_cast<uint32_t>(num_elements)) {
11700       // Simple case for arrays without holes.
11701       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11702         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11703       }
11704     } else {
11705       // For sparse arrays, only iterate over existing elements.
11706       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11707       // the to-be-removed indices twice.
11708       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11709       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11710       while (num_elements-- > 0) {
11711         uint32_t index = NumberToUint32(keys->get(num_elements));
11712         if (index < new_length) break;
11713         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11714       }
11715     }
11716   }
11717
11718   SetLength(array, new_length);
11719
11720   CHECK(array->length()->ToArrayLength(&new_length));
11721   if (old_length == new_length) return array;
11722
11723   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
11724
11725   for (int i = 0; i < indices.length(); ++i) {
11726     // For deletions where the property was an accessor, old_values[i]
11727     // will be the hole, which instructs EnqueueChangeRecord to elide
11728     // the "oldValue" property.
11729     RETURN_ON_EXCEPTION(
11730         isolate,
11731         JSObject::EnqueueChangeRecord(
11732             array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11733             old_values[i]),
11734         Object);
11735   }
11736
11737   RETURN_ON_EXCEPTION(isolate,
11738                       JSObject::EnqueueChangeRecord(
11739                           array, "update", isolate->factory()->length_string(),
11740                           old_length_handle),
11741                       Object);
11742
11743   RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
11744
11745   uint32_t index = Min(old_length, new_length);
11746   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11747   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11748   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11749   if (delete_count > 0) {
11750     for (int i = indices.length() - 1; i >= 0; i--) {
11751       // Skip deletions where the property was an accessor, leaving holes
11752       // in the array of old values.
11753       if (old_values[i]->IsTheHole()) continue;
11754       JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
11755           .Assert();
11756     }
11757
11758     JSArray::SetLength(deleted, delete_count);
11759   }
11760
11761   RETURN_ON_EXCEPTION(
11762       isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
11763
11764   return array;
11765 }
11766
11767
11768 // static
11769 void Map::AddDependentCode(Handle<Map> map,
11770                            DependentCode::DependencyGroup group,
11771                            Handle<Code> code) {
11772   Handle<WeakCell> cell = Code::WeakCellFor(code);
11773   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
11774       Handle<DependentCode>(map->dependent_code()), group, cell);
11775   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11776 }
11777
11778
11779 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
11780   Recompute(entries);
11781 }
11782
11783
11784 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
11785   start_indexes_[0] = 0;
11786   for (int g = 1; g <= kGroupCount; g++) {
11787     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11788     start_indexes_[g] = start_indexes_[g - 1] + count;
11789   }
11790 }
11791
11792
11793 Handle<DependentCode> DependentCode::InsertCompilationDependencies(
11794     Handle<DependentCode> entries, DependencyGroup group,
11795     Handle<Foreign> info) {
11796   return Insert(entries, group, info);
11797 }
11798
11799
11800 Handle<DependentCode> DependentCode::InsertWeakCode(
11801     Handle<DependentCode> entries, DependencyGroup group,
11802     Handle<WeakCell> code_cell) {
11803   return Insert(entries, group, code_cell);
11804 }
11805
11806
11807 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
11808                                             DependencyGroup group,
11809                                             Handle<Object> object) {
11810   GroupStartIndexes starts(*entries);
11811   int start = starts.at(group);
11812   int end = starts.at(group + 1);
11813   int number_of_entries = starts.number_of_entries();
11814   // Check for existing entry to avoid duplicates.
11815   for (int i = start; i < end; i++) {
11816     if (entries->object_at(i) == *object) return entries;
11817   }
11818   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11819     entries = EnsureSpace(entries);
11820     // The number of codes can change after Compact and GC.
11821     starts.Recompute(*entries);
11822     start = starts.at(group);
11823     end = starts.at(group + 1);
11824   }
11825
11826   entries->ExtendGroup(group);
11827   entries->set_object_at(end, *object);
11828   entries->set_number_of_entries(group, end + 1 - start);
11829   return entries;
11830 }
11831
11832
11833 Handle<DependentCode> DependentCode::EnsureSpace(
11834     Handle<DependentCode> entries) {
11835   if (entries->length() == 0) {
11836     entries = Handle<DependentCode>::cast(
11837         FixedArray::CopySize(entries, kCodesStartIndex + 1, TENURED));
11838     for (int g = 0; g < kGroupCount; g++) {
11839       entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11840     }
11841     return entries;
11842   }
11843   if (entries->Compact()) return entries;
11844   GroupStartIndexes starts(*entries);
11845   int capacity =
11846       kCodesStartIndex + DependentCode::Grow(starts.number_of_entries());
11847   return Handle<DependentCode>::cast(
11848       FixedArray::CopySize(entries, capacity, TENURED));
11849 }
11850
11851
11852 bool DependentCode::Compact() {
11853   GroupStartIndexes starts(this);
11854   int n = 0;
11855   for (int g = 0; g < kGroupCount; g++) {
11856     int start = starts.at(g);
11857     int end = starts.at(g + 1);
11858     int count = 0;
11859     DCHECK(start >= n);
11860     for (int i = start; i < end; i++) {
11861       Object* obj = object_at(i);
11862       if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
11863         if (i != n + count) {
11864           copy(i, n + count);
11865         }
11866         count++;
11867       }
11868     }
11869     if (count != end - start) {
11870       set_number_of_entries(static_cast<DependencyGroup>(g), count);
11871     }
11872     n += count;
11873   }
11874   return n < starts.number_of_entries();
11875 }
11876
11877
11878 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
11879                                          WeakCell* code_cell) {
11880   DisallowHeapAllocation no_gc;
11881   GroupStartIndexes starts(this);
11882   int start = starts.at(group);
11883   int end = starts.at(group + 1);
11884   for (int i = start; i < end; i++) {
11885     if (object_at(i) == info) {
11886       set_object_at(i, code_cell);
11887       break;
11888     }
11889   }
11890
11891 #ifdef DEBUG
11892   for (int i = start; i < end; i++) {
11893     DCHECK(object_at(i) != info);
11894   }
11895 #endif
11896 }
11897
11898
11899 void DependentCode::RemoveCompilationDependencies(
11900     DependentCode::DependencyGroup group, Foreign* info) {
11901   DisallowHeapAllocation no_allocation;
11902   GroupStartIndexes starts(this);
11903   int start = starts.at(group);
11904   int end = starts.at(group + 1);
11905   // Find compilation info wrapper.
11906   int info_pos = -1;
11907   for (int i = start; i < end; i++) {
11908     if (object_at(i) == info) {
11909       info_pos = i;
11910       break;
11911     }
11912   }
11913   if (info_pos == -1) return;  // Not found.
11914   int gap = info_pos;
11915   // Use the last of each group to fill the gap in the previous group.
11916   for (int i = group; i < kGroupCount; i++) {
11917     int last_of_group = starts.at(i + 1) - 1;
11918     DCHECK(last_of_group >= gap);
11919     if (last_of_group == gap) continue;
11920     copy(last_of_group, gap);
11921     gap = last_of_group;
11922   }
11923   DCHECK(gap == starts.number_of_entries() - 1);
11924   clear_at(gap);  // Clear last gap.
11925   set_number_of_entries(group, end - start - 1);
11926
11927 #ifdef DEBUG
11928   for (int i = start; i < end - 1; i++) {
11929     DCHECK(object_at(i) != info);
11930   }
11931 #endif
11932 }
11933
11934
11935 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
11936   GroupStartIndexes starts(this);
11937   int start = starts.at(group);
11938   int end = starts.at(group + 1);
11939   for (int i = start; i < end; i++) {
11940     if (object_at(i) == code_cell) return true;
11941   }
11942   return false;
11943 }
11944
11945
11946 bool DependentCode::MarkCodeForDeoptimization(
11947     Isolate* isolate,
11948     DependentCode::DependencyGroup group) {
11949   DisallowHeapAllocation no_allocation_scope;
11950   DependentCode::GroupStartIndexes starts(this);
11951   int start = starts.at(group);
11952   int end = starts.at(group + 1);
11953   int code_entries = starts.number_of_entries();
11954   if (start == end) return false;
11955
11956   // Mark all the code that needs to be deoptimized.
11957   bool marked = false;
11958   bool invalidate_embedded_objects = group == kWeakCodeGroup;
11959   for (int i = start; i < end; i++) {
11960     Object* obj = object_at(i);
11961     if (obj->IsWeakCell()) {
11962       WeakCell* cell = WeakCell::cast(obj);
11963       if (cell->cleared()) continue;
11964       Code* code = Code::cast(cell->value());
11965       if (!code->marked_for_deoptimization()) {
11966         SetMarkedForDeoptimization(code, group);
11967         if (invalidate_embedded_objects) {
11968           code->InvalidateEmbeddedObjects();
11969         }
11970         marked = true;
11971       }
11972     } else {
11973       DCHECK(obj->IsForeign());
11974       CompilationDependencies* info =
11975           reinterpret_cast<CompilationDependencies*>(
11976               Foreign::cast(obj)->foreign_address());
11977       info->Abort();
11978     }
11979   }
11980   // Compact the array by moving all subsequent groups to fill in the new holes.
11981   for (int src = end, dst = start; src < code_entries; src++, dst++) {
11982     copy(src, dst);
11983   }
11984   // Now the holes are at the end of the array, zap them for heap-verifier.
11985   int removed = end - start;
11986   for (int i = code_entries - removed; i < code_entries; i++) {
11987     clear_at(i);
11988   }
11989   set_number_of_entries(group, 0);
11990   return marked;
11991 }
11992
11993
11994 void DependentCode::DeoptimizeDependentCodeGroup(
11995     Isolate* isolate,
11996     DependentCode::DependencyGroup group) {
11997   DCHECK(AllowCodeDependencyChange::IsAllowed());
11998   DisallowHeapAllocation no_allocation_scope;
11999   bool marked = MarkCodeForDeoptimization(isolate, group);
12000   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
12001 }
12002
12003
12004 void DependentCode::SetMarkedForDeoptimization(Code* code,
12005                                                DependencyGroup group) {
12006   code->set_marked_for_deoptimization(true);
12007   if (FLAG_trace_deopt &&
12008       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
12009     DeoptimizationInputData* deopt_data =
12010         DeoptimizationInputData::cast(code->deoptimization_data());
12011     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
12012     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
12013                          " (opt #%d) for deoptimization, reason: %s]\n",
12014            reinterpret_cast<intptr_t>(code),
12015            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
12016   }
12017 }
12018
12019
12020 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
12021   switch (group) {
12022     case kWeakCodeGroup:
12023       return "weak-code";
12024     case kTransitionGroup:
12025       return "transition";
12026     case kPrototypeCheckGroup:
12027       return "prototype-check";
12028     case kPropertyCellChangedGroup:
12029       return "property-cell-changed";
12030     case kFieldTypeGroup:
12031       return "field-type";
12032     case kInitialMapChangedGroup:
12033       return "initial-map-changed";
12034     case kAllocationSiteTenuringChangedGroup:
12035       return "allocation-site-tenuring-changed";
12036     case kAllocationSiteTransitionChangedGroup:
12037       return "allocation-site-transition-changed";
12038   }
12039   UNREACHABLE();
12040   return "?";
12041 }
12042
12043
12044 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12045                                        Handle<Object> prototype,
12046                                        PrototypeOptimizationMode mode) {
12047   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
12048   if (new_map.is_null()) {
12049     new_map = Copy(map, "TransitionToPrototype");
12050     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
12051     Map::SetPrototype(new_map, prototype, mode);
12052   }
12053   return new_map;
12054 }
12055
12056
12057 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12058                                            Handle<Object> value,
12059                                            bool from_javascript) {
12060 #ifdef DEBUG
12061   int size = object->Size();
12062 #endif
12063
12064   Isolate* isolate = object->GetIsolate();
12065   // Strong objects may not have their prototype set via __proto__ or
12066   // setPrototypeOf.
12067   if (from_javascript && object->map()->is_strong()) {
12068     THROW_NEW_ERROR(isolate,
12069                     NewTypeError(MessageTemplate::kStrongSetProto, object),
12070                     Object);
12071   }
12072   Heap* heap = isolate->heap();
12073   // Silently ignore the change if value is not a JSObject or null.
12074   // SpiderMonkey behaves this way.
12075   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12076
12077   // From 8.6.2 Object Internal Methods
12078   // ...
12079   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12080   // [[Prototype]] internal properties of the object may not be modified.
12081   // ...
12082   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12083   // or [[Extensible]] must not violate the invariants defined in the preceding
12084   // paragraph.
12085   if (!object->map()->is_extensible()) {
12086     THROW_NEW_ERROR(isolate,
12087                     NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12088                     Object);
12089   }
12090
12091   // Before we can set the prototype we need to be sure
12092   // prototype cycles are prevented.
12093   // It is sufficient to validate that the receiver is not in the new prototype
12094   // chain.
12095   for (PrototypeIterator iter(isolate, *value,
12096                               PrototypeIterator::START_AT_RECEIVER);
12097        !iter.IsAtEnd(); iter.Advance()) {
12098     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12099       // Cycle detected.
12100       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto),
12101                       Object);
12102     }
12103   }
12104
12105   bool dictionary_elements_in_chain =
12106       object->map()->DictionaryElementsInPrototypeChainOnly();
12107   Handle<JSObject> real_receiver = object;
12108
12109   if (from_javascript) {
12110     // Find the first object in the chain whose prototype object is not
12111     // hidden and set the new prototype on that object.
12112     PrototypeIterator iter(isolate, real_receiver);
12113     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12114       real_receiver =
12115           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12116       iter.Advance();
12117       if (!real_receiver->map()->is_extensible()) {
12118         THROW_NEW_ERROR(
12119             isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12120             Object);
12121       }
12122     }
12123   }
12124
12125   // Set the new prototype of the object.
12126   Handle<Map> map(real_receiver->map());
12127
12128   // Nothing to do if prototype is already set.
12129   if (map->prototype() == *value) return value;
12130
12131   isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
12132
12133   PrototypeOptimizationMode mode =
12134       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12135   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12136   DCHECK(new_map->prototype() == *value);
12137   JSObject::MigrateToMap(real_receiver, new_map);
12138
12139   if (from_javascript && !dictionary_elements_in_chain &&
12140       new_map->DictionaryElementsInPrototypeChainOnly()) {
12141     // If the prototype chain didn't previously have element callbacks, then
12142     // KeyedStoreICs need to be cleared to ensure any that involve this
12143     // map go generic.
12144     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12145   }
12146
12147   heap->ClearInstanceofCache();
12148   DCHECK(size == object->Size());
12149   return value;
12150 }
12151
12152
12153 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12154                                         Arguments* args,
12155                                         uint32_t first_arg,
12156                                         uint32_t arg_count,
12157                                         EnsureElementsMode mode) {
12158   // Elements in |Arguments| are ordered backwards (because they're on the
12159   // stack), but the method that's called here iterates over them in forward
12160   // direction.
12161   return EnsureCanContainElements(
12162       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12163 }
12164
12165
12166 ElementsAccessor* JSObject::GetElementsAccessor() {
12167   return ElementsAccessor::ForKind(GetElementsKind());
12168 }
12169
12170
12171 void JSObject::ValidateElements(Handle<JSObject> object) {
12172 #ifdef ENABLE_SLOW_DCHECKS
12173   if (FLAG_enable_slow_asserts) {
12174     ElementsAccessor* accessor = object->GetElementsAccessor();
12175     accessor->Validate(object);
12176   }
12177 #endif
12178 }
12179
12180
12181 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
12182                                         uint32_t index,
12183                                         uint32_t* new_capacity) {
12184   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
12185                 JSObject::kMaxUncheckedFastElementsLength);
12186   if (index < capacity) {
12187     *new_capacity = capacity;
12188     return false;
12189   }
12190   if (index - capacity >= JSObject::kMaxGap) return true;
12191   *new_capacity = JSObject::NewElementsCapacity(index + 1);
12192   DCHECK_LT(index, *new_capacity);
12193   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
12194       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
12195        object->GetHeap()->InNewSpace(object))) {
12196     return false;
12197   }
12198   // If the fast-case backing storage takes up roughly three times as
12199   // much space (in machine words) as a dictionary backing storage
12200   // would, the object should have slow elements.
12201   int used_elements = object->GetFastElementsUsage();
12202   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12203                         SeededNumberDictionary::kEntrySize;
12204   return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
12205 }
12206
12207
12208 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
12209   if (HasFastElements()) {
12210     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12211     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12212     uint32_t new_capacity;
12213     return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
12214   }
12215   return false;
12216 }
12217
12218
12219 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
12220   if (object->HasSloppyArgumentsElements()) {
12221     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
12222   }
12223   DCHECK(object->HasDictionaryElements());
12224   SeededNumberDictionary* dictionary = object->element_dictionary();
12225   ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
12226   for (int i = 0; i < dictionary->Capacity(); i++) {
12227     Object* key = dictionary->KeyAt(i);
12228     if (key->IsNumber()) {
12229       Object* value = dictionary->ValueAt(i);
12230       if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
12231       if (!value->IsSmi()) {
12232         if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
12233         kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12234       }
12235     }
12236   }
12237   return kind;
12238 }
12239
12240
12241 static bool ShouldConvertToFastElements(JSObject* object,
12242                                         SeededNumberDictionary* dictionary,
12243                                         uint32_t index,
12244                                         uint32_t* new_capacity) {
12245   // If properties with non-standard attributes or accessors were added, we
12246   // cannot go back to fast elements.
12247   if (dictionary->requires_slow_elements()) return false;
12248
12249   // Adding a property with this index will require slow elements.
12250   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
12251
12252   if (object->IsJSArray()) {
12253     Object* length = JSArray::cast(object)->length();
12254     if (!length->IsSmi()) return false;
12255     *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
12256   } else {
12257     *new_capacity = dictionary->max_number_key() + 1;
12258   }
12259   *new_capacity = Max(index + 1, *new_capacity);
12260
12261   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
12262                              SeededNumberDictionary::kEntrySize;
12263   return 2 * dictionary_size >= *new_capacity;
12264 }
12265
12266
12267 // static
12268 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
12269                                              uint32_t index,
12270                                              Handle<Object> value,
12271                                              PropertyAttributes attributes) {
12272   DCHECK(object->map()->is_extensible());
12273
12274   Isolate* isolate = object->GetIsolate();
12275
12276   uint32_t old_length = 0;
12277   uint32_t new_capacity = 0;
12278
12279   Handle<Object> old_length_handle;
12280   if (object->IsJSArray()) {
12281     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
12282     if (object->map()->is_observed()) {
12283       old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
12284     }
12285   }
12286
12287   ElementsKind kind = object->GetElementsKind();
12288   FixedArrayBase* elements = object->elements();
12289   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
12290   if (IsSloppyArgumentsElements(kind)) {
12291     elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
12292     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
12293   }
12294
12295   if (attributes != NONE) {
12296     kind = dictionary_kind;
12297   } else if (elements->IsSeededNumberDictionary()) {
12298     kind = ShouldConvertToFastElements(*object,
12299                                        SeededNumberDictionary::cast(elements),
12300                                        index, &new_capacity)
12301                ? BestFittingFastElementsKind(*object)
12302                : dictionary_kind;  // Overwrite in case of arguments.
12303   } else if (ShouldConvertToSlowElements(
12304                  *object, static_cast<uint32_t>(elements->length()), index,
12305                  &new_capacity)) {
12306     kind = dictionary_kind;
12307   }
12308
12309   ElementsKind to = value->OptimalElementsKind();
12310   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
12311     to = GetHoleyElementsKind(to);
12312     kind = GetHoleyElementsKind(kind);
12313   }
12314   to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
12315   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
12316   accessor->Add(object, index, value, attributes, new_capacity);
12317
12318   uint32_t new_length = old_length;
12319   Handle<Object> new_length_handle;
12320   if (object->IsJSArray() && index >= old_length) {
12321     new_length = index + 1;
12322     new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
12323     JSArray::cast(*object)->set_length(*new_length_handle);
12324   }
12325
12326   if (!old_length_handle.is_null() && new_length != old_length) {
12327     // |old_length_handle| is kept null above unless the object is observed.
12328     DCHECK(object->map()->is_observed());
12329     Handle<JSArray> array = Handle<JSArray>::cast(object);
12330     Handle<String> name = isolate->factory()->Uint32ToString(index);
12331
12332     RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12333     RETURN_ON_EXCEPTION(
12334         isolate, EnqueueChangeRecord(array, "add", name,
12335                                      isolate->factory()->the_hole_value()),
12336         Object);
12337     RETURN_ON_EXCEPTION(isolate,
12338                         EnqueueChangeRecord(array, "update",
12339                                             isolate->factory()->length_string(),
12340                                             old_length_handle),
12341                         Object);
12342     RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
12343     Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12344     RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
12345                                                      new_length - old_length),
12346                         Object);
12347   } else if (object->map()->is_observed()) {
12348     Handle<String> name = isolate->factory()->Uint32ToString(index);
12349     RETURN_ON_EXCEPTION(
12350         isolate, EnqueueChangeRecord(object, "add", name,
12351                                      isolate->factory()->the_hole_value()),
12352         Object);
12353   }
12354
12355   return value;
12356 }
12357
12358
12359 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
12360   if (!HasFastElements()) return false;
12361   uint32_t capacity = static_cast<uint32_t>(elements()->length());
12362   uint32_t new_capacity;
12363   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
12364          ShouldConvertToSlowElements(this, capacity, new_length - 1,
12365                                      &new_capacity);
12366 }
12367
12368
12369 const double AllocationSite::kPretenureRatio = 0.85;
12370
12371
12372 void AllocationSite::ResetPretenureDecision() {
12373   set_pretenure_decision(kUndecided);
12374   set_memento_found_count(0);
12375   set_memento_create_count(0);
12376 }
12377
12378
12379 PretenureFlag AllocationSite::GetPretenureMode() {
12380   PretenureDecision mode = pretenure_decision();
12381   // Zombie objects "decide" to be untenured.
12382   return mode == kTenure ? TENURED : NOT_TENURED;
12383 }
12384
12385
12386 bool AllocationSite::IsNestedSite() {
12387   DCHECK(FLAG_trace_track_allocation_sites);
12388   Object* current = GetHeap()->allocation_sites_list();
12389   while (current->IsAllocationSite()) {
12390     AllocationSite* current_site = AllocationSite::cast(current);
12391     if (current_site->nested_site() == this) {
12392       return true;
12393     }
12394     current = current_site->weak_next();
12395   }
12396   return false;
12397 }
12398
12399
12400 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
12401                                               ElementsKind to_kind) {
12402   Isolate* isolate = site->GetIsolate();
12403
12404   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12405     Handle<JSArray> transition_info =
12406         handle(JSArray::cast(site->transition_info()));
12407     ElementsKind kind = transition_info->GetElementsKind();
12408     // if kind is holey ensure that to_kind is as well.
12409     if (IsHoleyElementsKind(kind)) {
12410       to_kind = GetHoleyElementsKind(to_kind);
12411     }
12412     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12413       // If the array is huge, it's not likely to be defined in a local
12414       // function, so we shouldn't make new instances of it very often.
12415       uint32_t length = 0;
12416       CHECK(transition_info->length()->ToArrayLength(&length));
12417       if (length <= kMaximumArrayBytesToPretransition) {
12418         if (FLAG_trace_track_allocation_sites) {
12419           bool is_nested = site->IsNestedSite();
12420           PrintF(
12421               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12422               reinterpret_cast<void*>(*site),
12423               is_nested ? "(nested)" : "",
12424               ElementsKindToString(kind),
12425               ElementsKindToString(to_kind));
12426         }
12427         JSObject::TransitionElementsKind(transition_info, to_kind);
12428         site->dependent_code()->DeoptimizeDependentCodeGroup(
12429             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12430       }
12431     }
12432   } else {
12433     ElementsKind kind = site->GetElementsKind();
12434     // if kind is holey ensure that to_kind is as well.
12435     if (IsHoleyElementsKind(kind)) {
12436       to_kind = GetHoleyElementsKind(to_kind);
12437     }
12438     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12439       if (FLAG_trace_track_allocation_sites) {
12440         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12441                reinterpret_cast<void*>(*site),
12442                ElementsKindToString(kind),
12443                ElementsKindToString(to_kind));
12444       }
12445       site->SetElementsKind(to_kind);
12446       site->dependent_code()->DeoptimizeDependentCodeGroup(
12447           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12448     }
12449   }
12450 }
12451
12452
12453 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
12454   switch (decision) {
12455     case kUndecided: return "undecided";
12456     case kDontTenure: return "don't tenure";
12457     case kMaybeTenure: return "maybe tenure";
12458     case kTenure: return "tenure";
12459     case kZombie: return "zombie";
12460     default: UNREACHABLE();
12461   }
12462   return NULL;
12463 }
12464
12465
12466 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
12467                                     ElementsKind to_kind) {
12468   if (!object->IsJSArray()) return;
12469
12470   Heap* heap = object->GetHeap();
12471   if (!heap->InNewSpace(*object)) return;
12472
12473   Handle<AllocationSite> site;
12474   {
12475     DisallowHeapAllocation no_allocation;
12476
12477     AllocationMemento* memento = heap->FindAllocationMemento(*object);
12478     if (memento == NULL) return;
12479
12480     // Walk through to the Allocation Site
12481     site = handle(memento->GetAllocationSite());
12482   }
12483   AllocationSite::DigestTransitionFeedback(site, to_kind);
12484 }
12485
12486
12487 void JSObject::TransitionElementsKind(Handle<JSObject> object,
12488                                       ElementsKind to_kind) {
12489   ElementsKind from_kind = object->GetElementsKind();
12490
12491   if (IsFastHoleyElementsKind(from_kind)) {
12492     to_kind = GetHoleyElementsKind(to_kind);
12493   }
12494
12495   if (from_kind == to_kind) return;
12496
12497   // This method should never be called for any other case.
12498   DCHECK(IsFastElementsKind(from_kind));
12499   DCHECK(IsFastElementsKind(to_kind));
12500   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
12501
12502   UpdateAllocationSite(object, to_kind);
12503   if (object->elements() == object->GetHeap()->empty_fixed_array() ||
12504       IsFastDoubleElementsKind(from_kind) ==
12505           IsFastDoubleElementsKind(to_kind)) {
12506     // No change is needed to the elements() buffer, the transition
12507     // only requires a map change.
12508     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12509     MigrateToMap(object, new_map);
12510     if (FLAG_trace_elements_transitions) {
12511       Handle<FixedArrayBase> elms(object->elements());
12512       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12513     }
12514   } else {
12515     DCHECK((IsFastSmiElementsKind(from_kind) &&
12516             IsFastDoubleElementsKind(to_kind)) ||
12517            (IsFastDoubleElementsKind(from_kind) &&
12518             IsFastObjectElementsKind(to_kind)));
12519     uint32_t c = static_cast<uint32_t>(object->elements()->length());
12520     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
12521   }
12522 }
12523
12524
12525 // static
12526 bool Map::IsValidElementsTransition(ElementsKind from_kind,
12527                                     ElementsKind to_kind) {
12528   // Transitions can't go backwards.
12529   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12530     return false;
12531   }
12532
12533   // Transitions from HOLEY -> PACKED are not allowed.
12534   return !IsFastHoleyElementsKind(from_kind) ||
12535       IsFastHoleyElementsKind(to_kind);
12536 }
12537
12538
12539 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
12540   LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
12541                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12542   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
12543   CHECK(it.IsFound());
12544   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
12545   return it.IsReadOnly();
12546 }
12547
12548
12549 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
12550                                         uint32_t index) {
12551   uint32_t length = 0;
12552   CHECK(array->length()->ToArrayLength(&length));
12553   if (length <= index) return HasReadOnlyLength(array);
12554   return false;
12555 }
12556
12557
12558 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
12559   Isolate* isolate = array->GetIsolate();
12560   Handle<Name> length = isolate->factory()->length_string();
12561   THROW_NEW_ERROR(
12562       isolate,
12563       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array),
12564       Object);
12565 }
12566
12567
12568 template <typename BackingStore>
12569 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
12570   int limit = object->IsJSArray()
12571                   ? Smi::cast(JSArray::cast(object)->length())->value()
12572                   : store->length();
12573   int used = 0;
12574   for (int i = 0; i < limit; ++i) {
12575     if (!store->is_the_hole(i)) ++used;
12576   }
12577   return used;
12578 }
12579
12580
12581 int JSObject::GetFastElementsUsage() {
12582   FixedArrayBase* store = elements();
12583   switch (GetElementsKind()) {
12584     case FAST_SMI_ELEMENTS:
12585     case FAST_DOUBLE_ELEMENTS:
12586     case FAST_ELEMENTS:
12587       // Only JSArray have packed elements.
12588       return Smi::cast(JSArray::cast(this)->length())->value();
12589     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
12590       store = FixedArray::cast(FixedArray::cast(store)->get(1));
12591     // Fall through.
12592     case FAST_HOLEY_SMI_ELEMENTS:
12593     case FAST_HOLEY_ELEMENTS:
12594       return FastHoleyElementsUsage(this, FixedArray::cast(store));
12595     case FAST_HOLEY_DOUBLE_ELEMENTS:
12596       if (elements()->length() == 0) return 0;
12597       return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
12598
12599     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
12600     case DICTIONARY_ELEMENTS:
12601 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
12602     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
12603     case TYPE##_ELEMENTS:                                                    \
12604
12605     TYPED_ARRAYS(TYPED_ARRAY_CASE)
12606 #undef TYPED_ARRAY_CASE
12607     UNREACHABLE();
12608   }
12609   return 0;
12610 }
12611
12612
12613 // Certain compilers request function template instantiation when they
12614 // see the definition of the other template functions in the
12615 // class. This requires us to have the template functions put
12616 // together, so even though this function belongs in objects-debug.cc,
12617 // we keep it here instead to satisfy certain compilers.
12618 #ifdef OBJECT_PRINT
12619 template <typename Derived, typename Shape, typename Key>
12620 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
12621   int capacity = this->Capacity();
12622   for (int i = 0; i < capacity; i++) {
12623     Object* k = this->KeyAt(i);
12624     if (this->IsKey(k)) {
12625       os << " ";
12626       if (k->IsString()) {
12627         String::cast(k)->StringPrint(os);
12628       } else {
12629         os << Brief(k);
12630       }
12631       os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i)
12632          << "\n";
12633     }
12634   }
12635 }
12636 #endif
12637
12638
12639 template<typename Derived, typename Shape, typename Key>
12640 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
12641   int pos = 0;
12642   int capacity = this->Capacity();
12643   DisallowHeapAllocation no_gc;
12644   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
12645   for (int i = 0; i < capacity; i++) {
12646     Object* k = this->KeyAt(i);
12647     if (this->IsKey(k)) {
12648       elements->set(pos++, this->ValueAt(i), mode);
12649     }
12650   }
12651   DCHECK(pos == elements->length());
12652 }
12653
12654
12655 InterceptorInfo* JSObject::GetNamedInterceptor() {
12656   DCHECK(map()->has_named_interceptor());
12657   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12658   DCHECK(constructor->shared()->IsApiFunction());
12659   Object* result =
12660       constructor->shared()->get_api_func_data()->named_property_handler();
12661   return InterceptorInfo::cast(result);
12662 }
12663
12664
12665 InterceptorInfo* JSObject::GetIndexedInterceptor() {
12666   DCHECK(map()->has_indexed_interceptor());
12667   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12668   DCHECK(constructor->shared()->IsApiFunction());
12669   Object* result =
12670       constructor->shared()->get_api_func_data()->indexed_property_handler();
12671   return InterceptorInfo::cast(result);
12672 }
12673
12674
12675 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
12676                                                          bool* done) {
12677   *done = false;
12678   Isolate* isolate = it->isolate();
12679   // Make sure that the top context does not change when doing callbacks or
12680   // interceptor calls.
12681   AssertNoContextChange ncc(isolate);
12682
12683   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
12684   Handle<InterceptorInfo> interceptor = it->GetInterceptor();
12685   if (interceptor->getter()->IsUndefined()) {
12686     return isolate->factory()->undefined_value();
12687   }
12688
12689   Handle<JSObject> holder = it->GetHolder<JSObject>();
12690   v8::Local<v8::Value> result;
12691   PropertyCallbackArguments args(isolate, interceptor->data(),
12692                                  *it->GetReceiver(), *holder);
12693
12694   if (it->IsElement()) {
12695     uint32_t index = it->index();
12696     v8::IndexedPropertyGetterCallback getter =
12697         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
12698     LOG(isolate,
12699         ApiIndexedPropertyAccess("interceptor-indexed-get", *holder, index));
12700     result = args.Call(getter, index);
12701   } else {
12702     Handle<Name> name = it->name();
12703
12704     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
12705       return isolate->factory()->undefined_value();
12706     }
12707
12708     v8::GenericNamedPropertyGetterCallback getter =
12709         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
12710             interceptor->getter());
12711     LOG(isolate,
12712         ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
12713     result = args.Call(getter, v8::Utils::ToLocal(name));
12714   }
12715
12716   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12717   if (result.IsEmpty()) return isolate->factory()->undefined_value();
12718   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12719   result_internal->VerifyApiCallResultType();
12720   *done = true;
12721   // Rebox handle before return
12722   return handle(*result_internal, isolate);
12723 }
12724
12725
12726 // Compute the property keys from the interceptor.
12727 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
12728     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12729   Isolate* isolate = receiver->GetIsolate();
12730   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
12731   PropertyCallbackArguments
12732       args(isolate, interceptor->data(), *receiver, *object);
12733   v8::Local<v8::Object> result;
12734   if (!interceptor->enumerator()->IsUndefined()) {
12735     v8::GenericNamedPropertyEnumeratorCallback enum_fun =
12736         v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>(
12737             interceptor->enumerator());
12738     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
12739     result = args.Call(enum_fun);
12740   }
12741   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12742   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12743          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12744   // Rebox before returning.
12745   return handle(*v8::Utils::OpenHandle(*result), isolate);
12746 }
12747
12748
12749 // Compute the element keys from the interceptor.
12750 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
12751     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12752   Isolate* isolate = receiver->GetIsolate();
12753   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12754   PropertyCallbackArguments
12755       args(isolate, interceptor->data(), *receiver, *object);
12756   v8::Local<v8::Object> result;
12757   if (!interceptor->enumerator()->IsUndefined()) {
12758     v8::IndexedPropertyEnumeratorCallback enum_fun =
12759         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
12760             interceptor->enumerator());
12761     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
12762     result = args.Call(enum_fun);
12763   }
12764   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12765   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12766          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12767   // Rebox before returning.
12768   return handle(*v8::Utils::OpenHandle(*result), isolate);
12769 }
12770
12771
12772 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
12773                                            Handle<Name> name) {
12774   LookupIterator it = LookupIterator::PropertyOrElement(
12775       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12776   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12777   if (!maybe_result.IsJust()) return Nothing<bool>();
12778   return Just(it.IsFound());
12779 }
12780
12781
12782 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
12783                                              uint32_t index) {
12784   Isolate* isolate = object->GetIsolate();
12785   LookupIterator it(isolate, object, index,
12786                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12787   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12788   if (!maybe_result.IsJust()) return Nothing<bool>();
12789   return Just(it.IsFound());
12790 }
12791
12792
12793 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
12794                                                    Handle<Name> name) {
12795   LookupIterator it = LookupIterator::PropertyOrElement(
12796       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12797   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12798   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
12799                                : Nothing<bool>();
12800 }
12801
12802
12803 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
12804   if (HasFastProperties()) {
12805     Map* map = this->map();
12806     if (filter == NONE) return map->NumberOfOwnDescriptors();
12807     if (filter & DONT_ENUM) {
12808       int result = map->EnumLength();
12809       if (result != kInvalidEnumCacheSentinel) return result;
12810     }
12811     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
12812   } else if (IsGlobalObject()) {
12813     return global_dictionary()->NumberOfElementsFilterAttributes(filter);
12814   } else {
12815     return property_dictionary()->NumberOfElementsFilterAttributes(filter);
12816   }
12817 }
12818
12819
12820 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
12821   Object* temp = get(i);
12822   set(i, get(j));
12823   set(j, temp);
12824   if (this != numbers) {
12825     temp = numbers->get(i);
12826     numbers->set(i, Smi::cast(numbers->get(j)));
12827     numbers->set(j, Smi::cast(temp));
12828   }
12829 }
12830
12831
12832 static void InsertionSortPairs(FixedArray* content,
12833                                FixedArray* numbers,
12834                                int len) {
12835   for (int i = 1; i < len; i++) {
12836     int j = i;
12837     while (j > 0 &&
12838            (NumberToUint32(numbers->get(j - 1)) >
12839             NumberToUint32(numbers->get(j)))) {
12840       content->SwapPairs(numbers, j - 1, j);
12841       j--;
12842     }
12843   }
12844 }
12845
12846
12847 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
12848   // In-place heap sort.
12849   DCHECK(content->length() == numbers->length());
12850
12851   // Bottom-up max-heap construction.
12852   for (int i = 1; i < len; ++i) {
12853     int child_index = i;
12854     while (child_index > 0) {
12855       int parent_index = ((child_index + 1) >> 1) - 1;
12856       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12857       uint32_t child_value = NumberToUint32(numbers->get(child_index));
12858       if (parent_value < child_value) {
12859         content->SwapPairs(numbers, parent_index, child_index);
12860       } else {
12861         break;
12862       }
12863       child_index = parent_index;
12864     }
12865   }
12866
12867   // Extract elements and create sorted array.
12868   for (int i = len - 1; i > 0; --i) {
12869     // Put max element at the back of the array.
12870     content->SwapPairs(numbers, 0, i);
12871     // Sift down the new top element.
12872     int parent_index = 0;
12873     while (true) {
12874       int child_index = ((parent_index + 1) << 1) - 1;
12875       if (child_index >= i) break;
12876       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
12877       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
12878       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12879       if (child_index + 1 >= i || child1_value > child2_value) {
12880         if (parent_value > child1_value) break;
12881         content->SwapPairs(numbers, parent_index, child_index);
12882         parent_index = child_index;
12883       } else {
12884         if (parent_value > child2_value) break;
12885         content->SwapPairs(numbers, parent_index, child_index + 1);
12886         parent_index = child_index + 1;
12887       }
12888     }
12889   }
12890 }
12891
12892
12893 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
12894 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
12895   DCHECK(this->length() == numbers->length());
12896   // For small arrays, simply use insertion sort.
12897   if (len <= 10) {
12898     InsertionSortPairs(this, numbers, len);
12899     return;
12900   }
12901   // Check the range of indices.
12902   uint32_t min_index = NumberToUint32(numbers->get(0));
12903   uint32_t max_index = min_index;
12904   uint32_t i;
12905   for (i = 1; i < len; i++) {
12906     if (NumberToUint32(numbers->get(i)) < min_index) {
12907       min_index = NumberToUint32(numbers->get(i));
12908     } else if (NumberToUint32(numbers->get(i)) > max_index) {
12909       max_index = NumberToUint32(numbers->get(i));
12910     }
12911   }
12912   if (max_index - min_index + 1 == len) {
12913     // Indices form a contiguous range, unless there are duplicates.
12914     // Do an in-place linear time sort assuming distinct numbers, but
12915     // avoid hanging in case they are not.
12916     for (i = 0; i < len; i++) {
12917       uint32_t p;
12918       uint32_t j = 0;
12919       // While the current element at i is not at its correct position p,
12920       // swap the elements at these two positions.
12921       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
12922              j++ < len) {
12923         SwapPairs(numbers, i, p);
12924       }
12925     }
12926   } else {
12927     HeapSortPairs(this, numbers, len);
12928     return;
12929   }
12930 }
12931
12932
12933 // Fill in the names of own properties into the supplied storage. The main
12934 // purpose of this function is to provide reflection information for the object
12935 // mirrors.
12936 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index,
12937                                   PropertyAttributes filter) {
12938   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
12939   if (HasFastProperties()) {
12940     int start_index = index;
12941     int real_size = map()->NumberOfOwnDescriptors();
12942     DescriptorArray* descs = map()->instance_descriptors();
12943     for (int i = 0; i < real_size; i++) {
12944       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
12945           !FilterKey(descs->GetKey(i), filter)) {
12946         storage->set(index++, descs->GetKey(i));
12947       }
12948     }
12949     return index - start_index;
12950   } else if (IsGlobalObject()) {
12951     return global_dictionary()->CopyKeysTo(storage, index, filter,
12952                                            GlobalDictionary::UNSORTED);
12953   } else {
12954     return property_dictionary()->CopyKeysTo(storage, index, filter,
12955                                              NameDictionary::UNSORTED);
12956   }
12957 }
12958
12959
12960 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
12961   return GetOwnElementKeys(NULL, filter);
12962 }
12963
12964
12965 int JSObject::NumberOfEnumElements() {
12966   // Fast case for objects with no elements.
12967   if (!IsJSValue() && HasFastObjectElements()) {
12968     uint32_t length = IsJSArray() ?
12969         static_cast<uint32_t>(
12970             Smi::cast(JSArray::cast(this)->length())->value()) :
12971         static_cast<uint32_t>(FixedArray::cast(elements())->length());
12972     if (length == 0) return 0;
12973   }
12974   // Compute the number of enumerable elements.
12975   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
12976 }
12977
12978
12979 int JSObject::GetOwnElementKeys(FixedArray* storage,
12980                                 PropertyAttributes filter) {
12981   int counter = 0;
12982
12983   // If this is a String wrapper, add the string indices first,
12984   // as they're guaranteed to preced the elements in numerical order
12985   // and ascending order is required by ECMA-262, 6th, 9.1.12.
12986   if (IsJSValue()) {
12987     Object* val = JSValue::cast(this)->value();
12988     if (val->IsString()) {
12989       String* str = String::cast(val);
12990       if (storage) {
12991         for (int i = 0; i < str->length(); i++) {
12992           storage->set(counter + i, Smi::FromInt(i));
12993         }
12994       }
12995       counter += str->length();
12996     }
12997   }
12998
12999   switch (GetElementsKind()) {
13000     case FAST_SMI_ELEMENTS:
13001     case FAST_ELEMENTS:
13002     case FAST_HOLEY_SMI_ELEMENTS:
13003     case FAST_HOLEY_ELEMENTS: {
13004       int length = IsJSArray() ?
13005           Smi::cast(JSArray::cast(this)->length())->value() :
13006           FixedArray::cast(elements())->length();
13007       for (int i = 0; i < length; i++) {
13008         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
13009           if (storage != NULL) {
13010             storage->set(counter, Smi::FromInt(i));
13011           }
13012           counter++;
13013         }
13014       }
13015       DCHECK(!storage || storage->length() >= counter);
13016       break;
13017     }
13018     case FAST_DOUBLE_ELEMENTS:
13019     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13020       int length = IsJSArray() ?
13021           Smi::cast(JSArray::cast(this)->length())->value() :
13022           FixedArrayBase::cast(elements())->length();
13023       for (int i = 0; i < length; i++) {
13024         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
13025           if (storage != NULL) {
13026             storage->set(counter, Smi::FromInt(i));
13027           }
13028           counter++;
13029         }
13030       }
13031       DCHECK(!storage || storage->length() >= counter);
13032       break;
13033     }
13034
13035 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13036     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13037     case TYPE##_ELEMENTS:                                                    \
13038
13039     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13040 #undef TYPED_ARRAY_CASE
13041     {
13042       int length = FixedArrayBase::cast(elements())->length();
13043       while (counter < length) {
13044         if (storage != NULL) {
13045           storage->set(counter, Smi::FromInt(counter));
13046         }
13047         counter++;
13048       }
13049       DCHECK(!storage || storage->length() >= counter);
13050       break;
13051     }
13052
13053     case DICTIONARY_ELEMENTS: {
13054       if (storage != NULL) {
13055         element_dictionary()->CopyKeysTo(storage, counter, filter,
13056                                          SeededNumberDictionary::SORTED);
13057       }
13058       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13059       break;
13060     }
13061     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
13062     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
13063       FixedArray* parameter_map = FixedArray::cast(elements());
13064       int mapped_length = parameter_map->length() - 2;
13065       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13066       if (arguments->IsDictionary()) {
13067         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13068         // will insert in storage starting at index 0.
13069         SeededNumberDictionary* dictionary =
13070             SeededNumberDictionary::cast(arguments);
13071         if (storage != NULL) {
13072           dictionary->CopyKeysTo(storage, counter, filter,
13073                                  SeededNumberDictionary::UNSORTED);
13074         }
13075         counter += dictionary->NumberOfElementsFilterAttributes(filter);
13076         for (int i = 0; i < mapped_length; ++i) {
13077           if (!parameter_map->get(i + 2)->IsTheHole()) {
13078             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13079             ++counter;
13080           }
13081         }
13082         if (storage != NULL) storage->SortPairs(storage, counter);
13083
13084       } else {
13085         int backing_length = arguments->length();
13086         int i = 0;
13087         for (; i < mapped_length; ++i) {
13088           if (!parameter_map->get(i + 2)->IsTheHole()) {
13089             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13090             ++counter;
13091           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13092             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13093             ++counter;
13094           }
13095         }
13096         for (; i < backing_length; ++i) {
13097           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13098           ++counter;
13099         }
13100       }
13101       break;
13102     }
13103   }
13104
13105   DCHECK(!storage || storage->length() == counter);
13106   return counter;
13107 }
13108
13109
13110 int JSObject::GetEnumElementKeys(FixedArray* storage) {
13111   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
13112 }
13113
13114
13115 const char* Symbol::PrivateSymbolToName() const {
13116   Heap* heap = GetIsolate()->heap();
13117 #define SYMBOL_CHECK_AND_PRINT(name) \
13118   if (this == heap->name()) return #name;
13119   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
13120 #undef SYMBOL_CHECK_AND_PRINT
13121   return "UNKNOWN";
13122 }
13123
13124
13125 void Symbol::SymbolShortPrint(std::ostream& os) {
13126   os << "<Symbol: " << Hash();
13127   if (!name()->IsUndefined()) {
13128     os << " ";
13129     HeapStringAllocator allocator;
13130     StringStream accumulator(&allocator);
13131     String::cast(name())->StringShortPrint(&accumulator);
13132     os << accumulator.ToCString().get();
13133   } else {
13134     os << " (" << PrivateSymbolToName() << ")";
13135   }
13136   os << ">";
13137 }
13138
13139
13140 // StringSharedKeys are used as keys in the eval cache.
13141 class StringSharedKey : public HashTableKey {
13142  public:
13143   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
13144                   LanguageMode language_mode, int scope_position)
13145       : source_(source),
13146         shared_(shared),
13147         language_mode_(language_mode),
13148         scope_position_(scope_position) {}
13149
13150   bool IsMatch(Object* other) override {
13151     DisallowHeapAllocation no_allocation;
13152     if (!other->IsFixedArray()) {
13153       if (!other->IsNumber()) return false;
13154       uint32_t other_hash = static_cast<uint32_t>(other->Number());
13155       return Hash() == other_hash;
13156     }
13157     FixedArray* other_array = FixedArray::cast(other);
13158     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13159     if (shared != *shared_) return false;
13160     int language_unchecked = Smi::cast(other_array->get(2))->value();
13161     DCHECK(is_valid_language_mode(language_unchecked));
13162     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13163     if (language_mode != language_mode_) return false;
13164     int scope_position = Smi::cast(other_array->get(3))->value();
13165     if (scope_position != scope_position_) return false;
13166     String* source = String::cast(other_array->get(1));
13167     return source->Equals(*source_);
13168   }
13169
13170   static uint32_t StringSharedHashHelper(String* source,
13171                                          SharedFunctionInfo* shared,
13172                                          LanguageMode language_mode,
13173                                          int scope_position) {
13174     uint32_t hash = source->Hash();
13175     if (shared->HasSourceCode()) {
13176       // Instead of using the SharedFunctionInfo pointer in the hash
13177       // code computation, we use a combination of the hash of the
13178       // script source code and the start position of the calling scope.
13179       // We do this to ensure that the cache entries can survive garbage
13180       // collection.
13181       Script* script(Script::cast(shared->script()));
13182       hash ^= String::cast(script->source())->Hash();
13183       STATIC_ASSERT(LANGUAGE_END == 3);
13184       if (is_strict(language_mode)) hash ^= 0x8000;
13185       if (is_strong(language_mode)) hash ^= 0x10000;
13186       hash += scope_position;
13187     }
13188     return hash;
13189   }
13190
13191   uint32_t Hash() override {
13192     return StringSharedHashHelper(*source_, *shared_, language_mode_,
13193                                   scope_position_);
13194   }
13195
13196   uint32_t HashForObject(Object* obj) override {
13197     DisallowHeapAllocation no_allocation;
13198     if (obj->IsNumber()) {
13199       return static_cast<uint32_t>(obj->Number());
13200     }
13201     FixedArray* other_array = FixedArray::cast(obj);
13202     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13203     String* source = String::cast(other_array->get(1));
13204     int language_unchecked = Smi::cast(other_array->get(2))->value();
13205     DCHECK(is_valid_language_mode(language_unchecked));
13206     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13207     int scope_position = Smi::cast(other_array->get(3))->value();
13208     return StringSharedHashHelper(source, shared, language_mode,
13209                                   scope_position);
13210   }
13211
13212
13213   Handle<Object> AsHandle(Isolate* isolate) override {
13214     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
13215     array->set(0, *shared_);
13216     array->set(1, *source_);
13217     array->set(2, Smi::FromInt(language_mode_));
13218     array->set(3, Smi::FromInt(scope_position_));
13219     return array;
13220   }
13221
13222  private:
13223   Handle<String> source_;
13224   Handle<SharedFunctionInfo> shared_;
13225   LanguageMode language_mode_;
13226   int scope_position_;
13227 };
13228
13229
13230 // RegExpKey carries the source and flags of a regular expression as key.
13231 class RegExpKey : public HashTableKey {
13232  public:
13233   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
13234       : string_(string),
13235         flags_(Smi::FromInt(flags.value())) { }
13236
13237   // Rather than storing the key in the hash table, a pointer to the
13238   // stored value is stored where the key should be.  IsMatch then
13239   // compares the search key to the found object, rather than comparing
13240   // a key to a key.
13241   bool IsMatch(Object* obj) override {
13242     FixedArray* val = FixedArray::cast(obj);
13243     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13244         && (flags_ == val->get(JSRegExp::kFlagsIndex));
13245   }
13246
13247   uint32_t Hash() override { return RegExpHash(*string_, flags_); }
13248
13249   Handle<Object> AsHandle(Isolate* isolate) override {
13250     // Plain hash maps, which is where regexp keys are used, don't
13251     // use this function.
13252     UNREACHABLE();
13253     return MaybeHandle<Object>().ToHandleChecked();
13254   }
13255
13256   uint32_t HashForObject(Object* obj) override {
13257     FixedArray* val = FixedArray::cast(obj);
13258     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13259                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13260   }
13261
13262   static uint32_t RegExpHash(String* string, Smi* flags) {
13263     return string->Hash() + flags->value();
13264   }
13265
13266   Handle<String> string_;
13267   Smi* flags_;
13268 };
13269
13270
13271 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
13272   if (hash_field_ == 0) Hash();
13273   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
13274 }
13275
13276
13277 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
13278   if (hash_field_ == 0) Hash();
13279   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
13280 }
13281
13282
13283 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
13284   if (hash_field_ == 0) Hash();
13285   return isolate->factory()->NewOneByteInternalizedSubString(
13286       string_, from_, length_, hash_field_);
13287 }
13288
13289
13290 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
13291   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
13292   return String::cast(string)->IsOneByteEqualTo(chars);
13293 }
13294
13295
13296 // InternalizedStringKey carries a string/internalized-string object as key.
13297 class InternalizedStringKey : public HashTableKey {
13298  public:
13299   explicit InternalizedStringKey(Handle<String> string)
13300       : string_(string) { }
13301
13302   bool IsMatch(Object* string) override {
13303     return String::cast(string)->Equals(*string_);
13304   }
13305
13306   uint32_t Hash() override { return string_->Hash(); }
13307
13308   uint32_t HashForObject(Object* other) override {
13309     return String::cast(other)->Hash();
13310   }
13311
13312   Handle<Object> AsHandle(Isolate* isolate) override {
13313     // Internalize the string if possible.
13314     MaybeHandle<Map> maybe_map =
13315         isolate->factory()->InternalizedStringMapForString(string_);
13316     Handle<Map> map;
13317     if (maybe_map.ToHandle(&map)) {
13318       string_->set_map_no_write_barrier(*map);
13319       DCHECK(string_->IsInternalizedString());
13320       return string_;
13321     }
13322     // Otherwise allocate a new internalized string.
13323     return isolate->factory()->NewInternalizedStringImpl(
13324         string_, string_->length(), string_->hash_field());
13325   }
13326
13327   static uint32_t StringHash(Object* obj) {
13328     return String::cast(obj)->Hash();
13329   }
13330
13331   Handle<String> string_;
13332 };
13333
13334
13335 template<typename Derived, typename Shape, typename Key>
13336 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
13337   IteratePointers(v, 0, kElementsStartOffset);
13338 }
13339
13340
13341 template<typename Derived, typename Shape, typename Key>
13342 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
13343   IteratePointers(v,
13344                   kElementsStartOffset,
13345                   kHeaderSize + length() * kPointerSize);
13346 }
13347
13348
13349 template<typename Derived, typename Shape, typename Key>
13350 Handle<Derived> HashTable<Derived, Shape, Key>::New(
13351     Isolate* isolate,
13352     int at_least_space_for,
13353     MinimumCapacity capacity_option,
13354     PretenureFlag pretenure) {
13355   DCHECK(0 <= at_least_space_for);
13356   DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
13357
13358   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13359                      ? at_least_space_for
13360                      : isolate->creating_default_snapshot()
13361                            ? ComputeCapacityForSerialization(at_least_space_for)
13362                            : ComputeCapacity(at_least_space_for);
13363   if (capacity > HashTable::kMaxCapacity) {
13364     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13365   }
13366
13367   Factory* factory = isolate->factory();
13368   int length = EntryToIndex(capacity);
13369   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
13370   array->set_map_no_write_barrier(*factory->hash_table_map());
13371   Handle<Derived> table = Handle<Derived>::cast(array);
13372
13373   table->SetNumberOfElements(0);
13374   table->SetNumberOfDeletedElements(0);
13375   table->SetCapacity(capacity);
13376   return table;
13377 }
13378
13379
13380 // Find entry for key otherwise return kNotFound.
13381 template <typename Derived, typename Shape>
13382 int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
13383   if (!key->IsUniqueName()) {
13384     return DerivedDictionary::FindEntry(key);
13385   }
13386
13387   // Optimized for unique names. Knowledge of the key type allows:
13388   // 1. Move the check if the key is unique out of the loop.
13389   // 2. Avoid comparing hash codes in unique-to-unique comparison.
13390   // 3. Detect a case when a dictionary key is not unique but the key is.
13391   //    In case of positive result the dictionary key may be replaced by the
13392   //    internalized string with minimal performance penalty. It gives a chance
13393   //    to perform further lookups in code stubs (and significant performance
13394   //    boost a certain style of code).
13395
13396   // EnsureCapacity will guarantee the hash table is never full.
13397   uint32_t capacity = this->Capacity();
13398   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
13399   uint32_t count = 1;
13400
13401   while (true) {
13402     int index = Derived::EntryToIndex(entry);
13403     Object* element = this->get(index);
13404     if (element->IsUndefined()) break;  // Empty entry.
13405     if (*key == element) return entry;
13406     if (!element->IsUniqueName() &&
13407         !element->IsTheHole() &&
13408         Name::cast(element)->Equals(*key)) {
13409       // Replace a key that is a non-internalized string by the equivalent
13410       // internalized string for faster further lookups.
13411       this->set(index, *key);
13412       return entry;
13413     }
13414     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
13415     entry = Derived::NextProbe(entry, count++, capacity);
13416   }
13417   return Derived::kNotFound;
13418 }
13419
13420
13421 template<typename Derived, typename Shape, typename Key>
13422 void HashTable<Derived, Shape, Key>::Rehash(
13423     Handle<Derived> new_table,
13424     Key key) {
13425   DCHECK(NumberOfElements() < new_table->Capacity());
13426
13427   DisallowHeapAllocation no_gc;
13428   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
13429
13430   // Copy prefix to new array.
13431   for (int i = kPrefixStartIndex;
13432        i < kPrefixStartIndex + Shape::kPrefixSize;
13433        i++) {
13434     new_table->set(i, get(i), mode);
13435   }
13436
13437   // Rehash the elements.
13438   int capacity = this->Capacity();
13439   for (int i = 0; i < capacity; i++) {
13440     uint32_t from_index = EntryToIndex(i);
13441     Object* k = this->get(from_index);
13442     if (IsKey(k)) {
13443       uint32_t hash = this->HashForObject(key, k);
13444       uint32_t insertion_index =
13445           EntryToIndex(new_table->FindInsertionEntry(hash));
13446       for (int j = 0; j < Shape::kEntrySize; j++) {
13447         new_table->set(insertion_index + j, get(from_index + j), mode);
13448       }
13449     }
13450   }
13451   new_table->SetNumberOfElements(NumberOfElements());
13452   new_table->SetNumberOfDeletedElements(0);
13453 }
13454
13455
13456 template<typename Derived, typename Shape, typename Key>
13457 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
13458     Key key,
13459     Object* k,
13460     int probe,
13461     uint32_t expected) {
13462   uint32_t hash = this->HashForObject(key, k);
13463   uint32_t capacity = this->Capacity();
13464   uint32_t entry = FirstProbe(hash, capacity);
13465   for (int i = 1; i < probe; i++) {
13466     if (entry == expected) return expected;
13467     entry = NextProbe(entry, i, capacity);
13468   }
13469   return entry;
13470 }
13471
13472
13473 template<typename Derived, typename Shape, typename Key>
13474 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
13475                                           uint32_t entry2,
13476                                           WriteBarrierMode mode) {
13477   int index1 = EntryToIndex(entry1);
13478   int index2 = EntryToIndex(entry2);
13479   Object* temp[Shape::kEntrySize];
13480   for (int j = 0; j < Shape::kEntrySize; j++) {
13481     temp[j] = get(index1 + j);
13482   }
13483   for (int j = 0; j < Shape::kEntrySize; j++) {
13484     set(index1 + j, get(index2 + j), mode);
13485   }
13486   for (int j = 0; j < Shape::kEntrySize; j++) {
13487     set(index2 + j, temp[j], mode);
13488   }
13489 }
13490
13491
13492 template<typename Derived, typename Shape, typename Key>
13493 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
13494   DisallowHeapAllocation no_gc;
13495   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
13496   uint32_t capacity = Capacity();
13497   bool done = false;
13498   for (int probe = 1; !done; probe++) {
13499     // All elements at entries given by one of the first _probe_ probes
13500     // are placed correctly. Other elements might need to be moved.
13501     done = true;
13502     for (uint32_t current = 0; current < capacity; current++) {
13503       Object* current_key = get(EntryToIndex(current));
13504       if (IsKey(current_key)) {
13505         uint32_t target = EntryForProbe(key, current_key, probe, current);
13506         if (current == target) continue;
13507         Object* target_key = get(EntryToIndex(target));
13508         if (!IsKey(target_key) ||
13509             EntryForProbe(key, target_key, probe, target) != target) {
13510           // Put the current element into the correct position.
13511           Swap(current, target, mode);
13512           // The other element will be processed on the next iteration.
13513           current--;
13514         } else {
13515           // The place for the current element is occupied. Leave the element
13516           // for the next probe.
13517           done = false;
13518         }
13519       }
13520     }
13521   }
13522 }
13523
13524
13525 template<typename Derived, typename Shape, typename Key>
13526 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
13527     Handle<Derived> table,
13528     int n,
13529     Key key,
13530     PretenureFlag pretenure) {
13531   Isolate* isolate = table->GetIsolate();
13532   int capacity = table->Capacity();
13533   int nof = table->NumberOfElements() + n;
13534   int nod = table->NumberOfDeletedElements();
13535   // Return if:
13536   //   50% is still free after adding n elements and
13537   //   at most 50% of the free elements are deleted elements.
13538   if (nod <= (capacity - nof) >> 1) {
13539     int needed_free = nof >> 1;
13540     if (nof + needed_free <= capacity) return table;
13541   }
13542
13543   const int kMinCapacityForPretenure = 256;
13544   bool should_pretenure = pretenure == TENURED ||
13545       ((capacity > kMinCapacityForPretenure) &&
13546           !isolate->heap()->InNewSpace(*table));
13547   Handle<Derived> new_table = HashTable::New(
13548       isolate,
13549       nof * 2,
13550       USE_DEFAULT_MINIMUM_CAPACITY,
13551       should_pretenure ? TENURED : NOT_TENURED);
13552
13553   table->Rehash(new_table, key);
13554   return new_table;
13555 }
13556
13557
13558 template<typename Derived, typename Shape, typename Key>
13559 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
13560                                                        Key key) {
13561   int capacity = table->Capacity();
13562   int nof = table->NumberOfElements();
13563
13564   // Shrink to fit the number of elements if only a quarter of the
13565   // capacity is filled with elements.
13566   if (nof > (capacity >> 2)) return table;
13567   // Allocate a new dictionary with room for at least the current
13568   // number of elements. The allocation method will make sure that
13569   // there is extra room in the dictionary for additions. Don't go
13570   // lower than room for 16 elements.
13571   int at_least_room_for = nof;
13572   if (at_least_room_for < 16) return table;
13573
13574   Isolate* isolate = table->GetIsolate();
13575   const int kMinCapacityForPretenure = 256;
13576   bool pretenure =
13577       (at_least_room_for > kMinCapacityForPretenure) &&
13578       !isolate->heap()->InNewSpace(*table);
13579   Handle<Derived> new_table = HashTable::New(
13580       isolate,
13581       at_least_room_for,
13582       USE_DEFAULT_MINIMUM_CAPACITY,
13583       pretenure ? TENURED : NOT_TENURED);
13584
13585   table->Rehash(new_table, key);
13586   return new_table;
13587 }
13588
13589
13590 template<typename Derived, typename Shape, typename Key>
13591 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
13592   uint32_t capacity = Capacity();
13593   uint32_t entry = FirstProbe(hash, capacity);
13594   uint32_t count = 1;
13595   // EnsureCapacity will guarantee the hash table is never full.
13596   while (true) {
13597     Object* element = KeyAt(entry);
13598     if (element->IsUndefined() || element->IsTheHole()) break;
13599     entry = NextProbe(entry, count++, capacity);
13600   }
13601   return entry;
13602 }
13603
13604
13605 // Force instantiation of template instances class.
13606 // Please note this list is compiler dependent.
13607
13608 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
13609
13610 template class HashTable<CompilationCacheTable,
13611                          CompilationCacheShape,
13612                          HashTableKey*>;
13613
13614 template class HashTable<ObjectHashTable,
13615                          ObjectHashTableShape,
13616                          Handle<Object> >;
13617
13618 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
13619
13620 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
13621
13622 template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
13623                           Handle<Name> >;
13624
13625 template class Dictionary<SeededNumberDictionary,
13626                           SeededNumberDictionaryShape,
13627                           uint32_t>;
13628
13629 template class Dictionary<UnseededNumberDictionary,
13630                           UnseededNumberDictionaryShape,
13631                           uint32_t>;
13632
13633 template Handle<SeededNumberDictionary>
13634 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13635     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13636
13637 template Handle<UnseededNumberDictionary>
13638 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13639     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13640
13641 template Handle<NameDictionary>
13642 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13643     New(Isolate*, int n, PretenureFlag pretenure);
13644
13645 template Handle<GlobalDictionary>
13646 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::New(
13647     Isolate*, int n, PretenureFlag pretenure);
13648
13649 template Handle<SeededNumberDictionary>
13650 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13651     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
13652
13653 template Handle<UnseededNumberDictionary>
13654 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13655     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
13656
13657 template Object*
13658 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13659     SlowReverseLookup(Object* value);
13660
13661 template Object*
13662 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13663     SlowReverseLookup(Object* value);
13664
13665 template Handle<Object>
13666 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
13667     Handle<NameDictionary>, int);
13668
13669 template Handle<Object>
13670 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13671            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
13672
13673 template Handle<NameDictionary>
13674 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13675     New(Isolate*, int, MinimumCapacity, PretenureFlag);
13676
13677 template Handle<NameDictionary>
13678 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13679     Shrink(Handle<NameDictionary>, Handle<Name>);
13680
13681 template Handle<SeededNumberDictionary>
13682 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13683     Shrink(Handle<SeededNumberDictionary>, uint32_t);
13684
13685 template Handle<NameDictionary>
13686 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
13687     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
13688
13689 template Handle<GlobalDictionary>
13690     Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Add(
13691         Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
13692         PropertyDetails);
13693
13694 template Handle<FixedArray> Dictionary<
13695     NameDictionary, NameDictionaryShape,
13696     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
13697
13698 template Handle<FixedArray> Dictionary<
13699     NameDictionary, NameDictionaryShape,
13700     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
13701
13702 template Handle<SeededNumberDictionary>
13703 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13704     Add(Handle<SeededNumberDictionary>,
13705         uint32_t,
13706         Handle<Object>,
13707         PropertyDetails);
13708
13709 template Handle<UnseededNumberDictionary>
13710 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13711     Add(Handle<UnseededNumberDictionary>,
13712         uint32_t,
13713         Handle<Object>,
13714         PropertyDetails);
13715
13716 template Handle<SeededNumberDictionary>
13717 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13718     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
13719
13720 template Handle<UnseededNumberDictionary>
13721 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13722     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
13723
13724 template Handle<NameDictionary>
13725 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13726     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
13727
13728 template bool Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13729                          uint32_t>::HasComplexElements();
13730
13731 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
13732                        uint32_t>::FindEntry(uint32_t);
13733
13734 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
13735     Handle<Name>);
13736
13737
13738 Handle<Object> JSObject::PrepareSlowElementsForSort(
13739     Handle<JSObject> object, uint32_t limit) {
13740   DCHECK(object->HasDictionaryElements());
13741   Isolate* isolate = object->GetIsolate();
13742   // Must stay in dictionary mode, either because of requires_slow_elements,
13743   // or because we are not going to sort (and therefore compact) all of the
13744   // elements.
13745   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
13746   Handle<SeededNumberDictionary> new_dict =
13747       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
13748
13749   uint32_t pos = 0;
13750   uint32_t undefs = 0;
13751   int capacity = dict->Capacity();
13752   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
13753   // Entry to the new dictionary does not cause it to grow, as we have
13754   // allocated one that is large enough for all entries.
13755   DisallowHeapAllocation no_gc;
13756   for (int i = 0; i < capacity; i++) {
13757     Object* k = dict->KeyAt(i);
13758     if (!dict->IsKey(k)) continue;
13759
13760     DCHECK(k->IsNumber());
13761     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
13762     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
13763     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
13764
13765     HandleScope scope(isolate);
13766     Handle<Object> value(dict->ValueAt(i), isolate);
13767     PropertyDetails details = dict->DetailsAt(i);
13768     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
13769       // Bail out and do the sorting of undefineds and array holes in JS.
13770       // Also bail out if the element is not supposed to be moved.
13771       return bailout;
13772     }
13773
13774     uint32_t key = NumberToUint32(k);
13775     if (key < limit) {
13776       if (value->IsUndefined()) {
13777         undefs++;
13778       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13779         // Adding an entry with the key beyond smi-range requires
13780         // allocation. Bailout.
13781         return bailout;
13782       } else {
13783         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13784             new_dict, pos, value, details);
13785         DCHECK(result.is_identical_to(new_dict));
13786         USE(result);
13787         pos++;
13788       }
13789     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
13790       // Adding an entry with the key beyond smi-range requires
13791       // allocation. Bailout.
13792       return bailout;
13793     } else {
13794       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13795           new_dict, key, value, details);
13796       DCHECK(result.is_identical_to(new_dict));
13797       USE(result);
13798     }
13799   }
13800
13801   uint32_t result = pos;
13802   PropertyDetails no_details = PropertyDetails::Empty();
13803   while (undefs > 0) {
13804     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13805       // Adding an entry with the key beyond smi-range requires
13806       // allocation. Bailout.
13807       return bailout;
13808     }
13809     HandleScope scope(isolate);
13810     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13811         new_dict, pos, isolate->factory()->undefined_value(), no_details);
13812     DCHECK(result.is_identical_to(new_dict));
13813     USE(result);
13814     pos++;
13815     undefs--;
13816   }
13817
13818   object->set_elements(*new_dict);
13819
13820   AllowHeapAllocation allocate_return_value;
13821   return isolate->factory()->NewNumberFromUint(result);
13822 }
13823
13824
13825 // Collects all defined (non-hole) and non-undefined (array) elements at
13826 // the start of the elements array.
13827 // If the object is in dictionary mode, it is converted to fast elements
13828 // mode.
13829 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
13830                                                 uint32_t limit) {
13831   Isolate* isolate = object->GetIsolate();
13832   if (object->HasSloppyArgumentsElements() ||
13833       object->map()->is_observed()) {
13834     return handle(Smi::FromInt(-1), isolate);
13835   }
13836
13837   if (object->HasDictionaryElements()) {
13838     // Convert to fast elements containing only the existing properties.
13839     // Ordering is irrelevant, since we are going to sort anyway.
13840     Handle<SeededNumberDictionary> dict(object->element_dictionary());
13841     if (object->IsJSArray() || dict->requires_slow_elements() ||
13842         dict->max_number_key() >= limit) {
13843       return JSObject::PrepareSlowElementsForSort(object, limit);
13844     }
13845     // Convert to fast elements.
13846
13847     Handle<Map> new_map =
13848         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
13849
13850     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
13851         NOT_TENURED: TENURED;
13852     Handle<FixedArray> fast_elements =
13853         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
13854     dict->CopyValuesTo(*fast_elements);
13855     JSObject::ValidateElements(object);
13856
13857     JSObject::SetMapAndElements(object, new_map, fast_elements);
13858   } else if (object->HasExternalArrayElements() ||
13859              object->HasFixedTypedArrayElements()) {
13860     // Typed arrays cannot have holes or undefined elements.
13861     return handle(Smi::FromInt(
13862         FixedArrayBase::cast(object->elements())->length()), isolate);
13863   } else if (!object->HasFastDoubleElements()) {
13864     EnsureWritableFastElements(object);
13865   }
13866   DCHECK(object->HasFastSmiOrObjectElements() ||
13867          object->HasFastDoubleElements());
13868
13869   // Collect holes at the end, undefined before that and the rest at the
13870   // start, and return the number of non-hole, non-undefined values.
13871
13872   Handle<FixedArrayBase> elements_base(object->elements());
13873   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
13874   if (limit > elements_length) {
13875     limit = elements_length ;
13876   }
13877   if (limit == 0) {
13878     return handle(Smi::FromInt(0), isolate);
13879   }
13880
13881   uint32_t result = 0;
13882   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
13883     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
13884     // Split elements into defined and the_hole, in that order.
13885     unsigned int holes = limit;
13886     // Assume most arrays contain no holes and undefined values, so minimize the
13887     // number of stores of non-undefined, non-the-hole values.
13888     for (unsigned int i = 0; i < holes; i++) {
13889       if (elements->is_the_hole(i)) {
13890         holes--;
13891       } else {
13892         continue;
13893       }
13894       // Position i needs to be filled.
13895       while (holes > i) {
13896         if (elements->is_the_hole(holes)) {
13897           holes--;
13898         } else {
13899           elements->set(i, elements->get_scalar(holes));
13900           break;
13901         }
13902       }
13903     }
13904     result = holes;
13905     while (holes < limit) {
13906       elements->set_the_hole(holes);
13907       holes++;
13908     }
13909   } else {
13910     FixedArray* elements = FixedArray::cast(*elements_base);
13911     DisallowHeapAllocation no_gc;
13912
13913     // Split elements into defined, undefined and the_hole, in that order.  Only
13914     // count locations for undefined and the hole, and fill them afterwards.
13915     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
13916     unsigned int undefs = limit;
13917     unsigned int holes = limit;
13918     // Assume most arrays contain no holes and undefined values, so minimize the
13919     // number of stores of non-undefined, non-the-hole values.
13920     for (unsigned int i = 0; i < undefs; i++) {
13921       Object* current = elements->get(i);
13922       if (current->IsTheHole()) {
13923         holes--;
13924         undefs--;
13925       } else if (current->IsUndefined()) {
13926         undefs--;
13927       } else {
13928         continue;
13929       }
13930       // Position i needs to be filled.
13931       while (undefs > i) {
13932         current = elements->get(undefs);
13933         if (current->IsTheHole()) {
13934           holes--;
13935           undefs--;
13936         } else if (current->IsUndefined()) {
13937           undefs--;
13938         } else {
13939           elements->set(i, current, write_barrier);
13940           break;
13941         }
13942       }
13943     }
13944     result = undefs;
13945     while (undefs < holes) {
13946       elements->set_undefined(undefs);
13947       undefs++;
13948     }
13949     while (holes < limit) {
13950       elements->set_the_hole(holes);
13951       holes++;
13952     }
13953   }
13954
13955   return isolate->factory()->NewNumberFromUint(result);
13956 }
13957
13958
13959 ExternalArrayType JSTypedArray::type() {
13960   switch (elements()->map()->instance_type()) {
13961 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
13962     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
13963     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
13964       return kExternal##Type##Array;
13965
13966     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
13967 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
13968
13969     default:
13970       UNREACHABLE();
13971       return static_cast<ExternalArrayType>(-1);
13972   }
13973 }
13974
13975
13976 size_t JSTypedArray::element_size() {
13977   switch (elements()->map()->instance_type()) {
13978 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
13979     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
13980       return size;
13981
13982     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
13983 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
13984
13985     default:
13986       UNREACHABLE();
13987       return 0;
13988   }
13989 }
13990
13991
13992 void FixedArray::SetValue(uint32_t index, Object* value) { set(index, value); }
13993
13994
13995 void FixedDoubleArray::SetValue(uint32_t index, Object* value) {
13996   set(index, value->Number());
13997 }
13998
13999
14000 void ExternalUint8ClampedArray::SetValue(uint32_t index, Object* value) {
14001   uint8_t clamped_value = 0;
14002   if (value->IsSmi()) {
14003     int int_value = Smi::cast(value)->value();
14004     if (int_value < 0) {
14005       clamped_value = 0;
14006     } else if (int_value > 255) {
14007       clamped_value = 255;
14008     } else {
14009       clamped_value = static_cast<uint8_t>(int_value);
14010     }
14011   } else if (value->IsHeapNumber()) {
14012     double double_value = HeapNumber::cast(value)->value();
14013     if (!(double_value > 0)) {
14014       // NaN and less than zero clamp to zero.
14015       clamped_value = 0;
14016     } else if (double_value > 255) {
14017       // Greater than 255 clamp to 255.
14018       clamped_value = 255;
14019     } else {
14020       // Other doubles are rounded to the nearest integer.
14021       clamped_value = static_cast<uint8_t>(lrint(double_value));
14022     }
14023   } else {
14024     // Clamp undefined to zero (default). All other types have been
14025     // converted to a number type further up in the call chain.
14026     DCHECK(value->IsUndefined());
14027   }
14028   set(index, clamped_value);
14029 }
14030
14031
14032 template <typename ExternalArrayClass, typename ValueType>
14033 static void ExternalArrayIntSetter(ExternalArrayClass* receiver, uint32_t index,
14034                                    Object* value) {
14035   ValueType cast_value = 0;
14036   if (value->IsSmi()) {
14037     int int_value = Smi::cast(value)->value();
14038     cast_value = static_cast<ValueType>(int_value);
14039   } else if (value->IsHeapNumber()) {
14040     double double_value = HeapNumber::cast(value)->value();
14041     cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
14042   } else {
14043     // Clamp undefined to zero (default). All other types have been
14044     // converted to a number type further up in the call chain.
14045     DCHECK(value->IsUndefined());
14046   }
14047   receiver->set(index, cast_value);
14048 }
14049
14050
14051 void ExternalInt8Array::SetValue(uint32_t index, Object* value) {
14052   ExternalArrayIntSetter<ExternalInt8Array, int8_t>(this, index, value);
14053 }
14054
14055
14056 void ExternalUint8Array::SetValue(uint32_t index, Object* value) {
14057   ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(this, index, value);
14058 }
14059
14060
14061 void ExternalInt16Array::SetValue(uint32_t index, Object* value) {
14062   ExternalArrayIntSetter<ExternalInt16Array, int16_t>(this, index, value);
14063 }
14064
14065
14066 void ExternalUint16Array::SetValue(uint32_t index, Object* value) {
14067   ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(this, index, value);
14068 }
14069
14070
14071 void ExternalInt32Array::SetValue(uint32_t index, Object* value) {
14072   ExternalArrayIntSetter<ExternalInt32Array, int32_t>(this, index, value);
14073 }
14074
14075
14076 void ExternalUint32Array::SetValue(uint32_t index, Object* value) {
14077   uint32_t cast_value = 0;
14078   if (value->IsSmi()) {
14079     int int_value = Smi::cast(value)->value();
14080     cast_value = static_cast<uint32_t>(int_value);
14081   } else if (value->IsHeapNumber()) {
14082     double double_value = HeapNumber::cast(value)->value();
14083     cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
14084   } else {
14085     // Clamp undefined to zero (default). All other types have been
14086     // converted to a number type further up in the call chain.
14087     DCHECK(value->IsUndefined());
14088   }
14089   set(index, cast_value);
14090 }
14091
14092
14093 void ExternalFloat32Array::SetValue(uint32_t index, Object* value) {
14094   float cast_value = std::numeric_limits<float>::quiet_NaN();
14095   if (value->IsSmi()) {
14096     int int_value = Smi::cast(value)->value();
14097     cast_value = static_cast<float>(int_value);
14098   } else if (value->IsHeapNumber()) {
14099     double double_value = HeapNumber::cast(value)->value();
14100     cast_value = static_cast<float>(double_value);
14101   } else {
14102     // Clamp undefined to NaN (default). All other types have been
14103     // converted to a number type further up in the call chain.
14104     DCHECK(value->IsUndefined());
14105   }
14106   set(index, cast_value);
14107 }
14108
14109
14110 void ExternalFloat64Array::SetValue(uint32_t index, Object* value) {
14111   double double_value = std::numeric_limits<double>::quiet_NaN();
14112   if (value->IsNumber()) {
14113     double_value = value->Number();
14114   } else {
14115     // Clamp undefined to NaN (default). All other types have been
14116     // converted to a number type further up in the call chain.
14117     DCHECK(value->IsUndefined());
14118   }
14119   set(index, double_value);
14120 }
14121
14122
14123 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
14124                                           Handle<Name> name) {
14125   DCHECK(!global->HasFastProperties());
14126   auto dictionary = handle(global->global_dictionary());
14127   int entry = dictionary->FindEntry(name);
14128   if (entry == GlobalDictionary::kNotFound) return;
14129   PropertyCell::InvalidateEntry(dictionary, entry);
14130 }
14131
14132
14133 // TODO(ishell): rename to EnsureEmptyPropertyCell or something.
14134 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
14135     Handle<GlobalObject> global, Handle<Name> name) {
14136   DCHECK(!global->HasFastProperties());
14137   auto dictionary = handle(global->global_dictionary());
14138   int entry = dictionary->FindEntry(name);
14139   Handle<PropertyCell> cell;
14140   if (entry != GlobalDictionary::kNotFound) {
14141     // This call should be idempotent.
14142     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
14143     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
14144     DCHECK(cell->property_details().cell_type() ==
14145                PropertyCellType::kUninitialized ||
14146            cell->property_details().cell_type() ==
14147                PropertyCellType::kInvalidated);
14148     DCHECK(cell->value()->IsTheHole());
14149     return cell;
14150   }
14151   Isolate* isolate = global->GetIsolate();
14152   cell = isolate->factory()->NewPropertyCell();
14153   PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
14154   dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
14155   global->set_properties(*dictionary);
14156   return cell;
14157 }
14158
14159
14160 // This class is used for looking up two character strings in the string table.
14161 // If we don't have a hit we don't want to waste much time so we unroll the
14162 // string hash calculation loop here for speed.  Doesn't work if the two
14163 // characters form a decimal integer, since such strings have a different hash
14164 // algorithm.
14165 class TwoCharHashTableKey : public HashTableKey {
14166  public:
14167   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
14168     : c1_(c1), c2_(c2) {
14169     // Char 1.
14170     uint32_t hash = seed;
14171     hash += c1;
14172     hash += hash << 10;
14173     hash ^= hash >> 6;
14174     // Char 2.
14175     hash += c2;
14176     hash += hash << 10;
14177     hash ^= hash >> 6;
14178     // GetHash.
14179     hash += hash << 3;
14180     hash ^= hash >> 11;
14181     hash += hash << 15;
14182     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14183     hash_ = hash;
14184 #ifdef DEBUG
14185     // If this assert fails then we failed to reproduce the two-character
14186     // version of the string hashing algorithm above.  One reason could be
14187     // that we were passed two digits as characters, since the hash
14188     // algorithm is different in that case.
14189     uint16_t chars[2] = {c1, c2};
14190     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14191     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
14192     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14193 #endif
14194   }
14195
14196   bool IsMatch(Object* o) override {
14197     if (!o->IsString()) return false;
14198     String* other = String::cast(o);
14199     if (other->length() != 2) return false;
14200     if (other->Get(0) != c1_) return false;
14201     return other->Get(1) == c2_;
14202   }
14203
14204   uint32_t Hash() override { return hash_; }
14205   uint32_t HashForObject(Object* key) override {
14206     if (!key->IsString()) return 0;
14207     return String::cast(key)->Hash();
14208   }
14209
14210   Handle<Object> AsHandle(Isolate* isolate) override {
14211     // The TwoCharHashTableKey is only used for looking in the string
14212     // table, not for adding to it.
14213     UNREACHABLE();
14214     return MaybeHandle<Object>().ToHandleChecked();
14215   }
14216
14217  private:
14218   uint16_t c1_;
14219   uint16_t c2_;
14220   uint32_t hash_;
14221 };
14222
14223
14224 MaybeHandle<String> StringTable::InternalizeStringIfExists(
14225     Isolate* isolate,
14226     Handle<String> string) {
14227   if (string->IsInternalizedString()) {
14228     return string;
14229   }
14230   return LookupStringIfExists(isolate, string);
14231 }
14232
14233
14234 MaybeHandle<String> StringTable::LookupStringIfExists(
14235     Isolate* isolate,
14236     Handle<String> string) {
14237   Handle<StringTable> string_table = isolate->factory()->string_table();
14238   InternalizedStringKey key(string);
14239   int entry = string_table->FindEntry(&key);
14240   if (entry == kNotFound) {
14241     return MaybeHandle<String>();
14242   } else {
14243     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14244     DCHECK(StringShape(*result).IsInternalized());
14245     return result;
14246   }
14247 }
14248
14249
14250 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
14251     Isolate* isolate,
14252     uint16_t c1,
14253     uint16_t c2) {
14254   Handle<StringTable> string_table = isolate->factory()->string_table();
14255   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
14256   int entry = string_table->FindEntry(&key);
14257   if (entry == kNotFound) {
14258     return MaybeHandle<String>();
14259   } else {
14260     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14261     DCHECK(StringShape(*result).IsInternalized());
14262     return result;
14263   }
14264 }
14265
14266
14267 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
14268                                                    int expected) {
14269   Handle<StringTable> table = isolate->factory()->string_table();
14270   // We need a key instance for the virtual hash function.
14271   InternalizedStringKey dummy_key(Handle<String>::null());
14272   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
14273   isolate->factory()->set_string_table(table);
14274 }
14275
14276
14277 Handle<String> StringTable::LookupString(Isolate* isolate,
14278                                          Handle<String> string) {
14279   InternalizedStringKey key(string);
14280   return LookupKey(isolate, &key);
14281 }
14282
14283
14284 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
14285   Handle<StringTable> table = isolate->factory()->string_table();
14286   int entry = table->FindEntry(key);
14287
14288   // String already in table.
14289   if (entry != kNotFound) {
14290     return handle(String::cast(table->KeyAt(entry)), isolate);
14291   }
14292
14293   // Adding new string. Grow table if needed.
14294   table = StringTable::EnsureCapacity(table, 1, key);
14295
14296   // Create string object.
14297   Handle<Object> string = key->AsHandle(isolate);
14298   // There must be no attempts to internalize strings that could throw
14299   // InvalidStringLength error.
14300   CHECK(!string.is_null());
14301
14302   // Add the new string and return it along with the string table.
14303   entry = table->FindInsertionEntry(key->Hash());
14304   table->set(EntryToIndex(entry), *string);
14305   table->ElementAdded();
14306
14307   isolate->factory()->set_string_table(table);
14308   return Handle<String>::cast(string);
14309 }
14310
14311
14312 String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
14313   Handle<StringTable> table = isolate->factory()->string_table();
14314   int entry = table->FindEntry(key);
14315   if (entry != kNotFound) return String::cast(table->KeyAt(entry));
14316   return NULL;
14317 }
14318
14319
14320 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
14321                                              Handle<Context> context,
14322                                              LanguageMode language_mode) {
14323   Isolate* isolate = GetIsolate();
14324   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14325   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14326   int entry = FindEntry(&key);
14327   if (entry == kNotFound) return isolate->factory()->undefined_value();
14328   int index = EntryToIndex(entry);
14329   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14330   return Handle<Object>(get(index + 1), isolate);
14331 }
14332
14333
14334 Handle<Object> CompilationCacheTable::LookupEval(
14335     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
14336     LanguageMode language_mode, int scope_position) {
14337   Isolate* isolate = GetIsolate();
14338   // Cache key is the tuple (source, outer shared function info, scope position)
14339   // to unambiguously identify the context chain the cached eval code assumes.
14340   StringSharedKey key(src, outer_info, language_mode, scope_position);
14341   int entry = FindEntry(&key);
14342   if (entry == kNotFound) return isolate->factory()->undefined_value();
14343   int index = EntryToIndex(entry);
14344   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14345   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14346 }
14347
14348
14349 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
14350                                                    JSRegExp::Flags flags) {
14351   Isolate* isolate = GetIsolate();
14352   DisallowHeapAllocation no_allocation;
14353   RegExpKey key(src, flags);
14354   int entry = FindEntry(&key);
14355   if (entry == kNotFound) return isolate->factory()->undefined_value();
14356   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14357 }
14358
14359
14360 Handle<CompilationCacheTable> CompilationCacheTable::Put(
14361     Handle<CompilationCacheTable> cache, Handle<String> src,
14362     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
14363   Isolate* isolate = cache->GetIsolate();
14364   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14365   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14366   {
14367     Handle<Object> k = key.AsHandle(isolate);
14368     DisallowHeapAllocation no_allocation_scope;
14369     int entry = cache->FindEntry(&key);
14370     if (entry != kNotFound) {
14371       cache->set(EntryToIndex(entry), *k);
14372       cache->set(EntryToIndex(entry) + 1, *value);
14373       return cache;
14374     }
14375   }
14376
14377   cache = EnsureCapacity(cache, 1, &key);
14378   int entry = cache->FindInsertionEntry(key.Hash());
14379   Handle<Object> k =
14380       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14381   cache->set(EntryToIndex(entry), *k);
14382   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14383   cache->ElementAdded();
14384   return cache;
14385 }
14386
14387
14388 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
14389     Handle<CompilationCacheTable> cache, Handle<String> src,
14390     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
14391     int scope_position) {
14392   Isolate* isolate = cache->GetIsolate();
14393   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
14394   {
14395     Handle<Object> k = key.AsHandle(isolate);
14396     DisallowHeapAllocation no_allocation_scope;
14397     int entry = cache->FindEntry(&key);
14398     if (entry != kNotFound) {
14399       cache->set(EntryToIndex(entry), *k);
14400       cache->set(EntryToIndex(entry) + 1, *value);
14401       return cache;
14402     }
14403   }
14404
14405   cache = EnsureCapacity(cache, 1, &key);
14406   int entry = cache->FindInsertionEntry(key.Hash());
14407   Handle<Object> k =
14408       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14409   cache->set(EntryToIndex(entry), *k);
14410   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14411   cache->ElementAdded();
14412   return cache;
14413 }
14414
14415
14416 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
14417       Handle<CompilationCacheTable> cache, Handle<String> src,
14418       JSRegExp::Flags flags, Handle<FixedArray> value) {
14419   RegExpKey key(src, flags);
14420   cache = EnsureCapacity(cache, 1, &key);
14421   int entry = cache->FindInsertionEntry(key.Hash());
14422   // We store the value in the key slot, and compare the search key
14423   // to the stored value with a custon IsMatch function during lookups.
14424   cache->set(EntryToIndex(entry), *value);
14425   cache->set(EntryToIndex(entry) + 1, *value);
14426   cache->ElementAdded();
14427   return cache;
14428 }
14429
14430
14431 void CompilationCacheTable::Age() {
14432   DisallowHeapAllocation no_allocation;
14433   Object* the_hole_value = GetHeap()->the_hole_value();
14434   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14435     int entry_index = EntryToIndex(entry);
14436     int value_index = entry_index + 1;
14437
14438     if (get(entry_index)->IsNumber()) {
14439       Smi* count = Smi::cast(get(value_index));
14440       count = Smi::FromInt(count->value() - 1);
14441       if (count->value() == 0) {
14442         NoWriteBarrierSet(this, entry_index, the_hole_value);
14443         NoWriteBarrierSet(this, value_index, the_hole_value);
14444         ElementRemoved();
14445       } else {
14446         NoWriteBarrierSet(this, value_index, count);
14447       }
14448     } else if (get(entry_index)->IsFixedArray()) {
14449       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
14450       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
14451         NoWriteBarrierSet(this, entry_index, the_hole_value);
14452         NoWriteBarrierSet(this, value_index, the_hole_value);
14453         ElementRemoved();
14454       }
14455     }
14456   }
14457 }
14458
14459
14460 void CompilationCacheTable::Remove(Object* value) {
14461   DisallowHeapAllocation no_allocation;
14462   Object* the_hole_value = GetHeap()->the_hole_value();
14463   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14464     int entry_index = EntryToIndex(entry);
14465     int value_index = entry_index + 1;
14466     if (get(value_index) == value) {
14467       NoWriteBarrierSet(this, entry_index, the_hole_value);
14468       NoWriteBarrierSet(this, value_index, the_hole_value);
14469       ElementRemoved();
14470     }
14471   }
14472   return;
14473 }
14474
14475
14476 // StringsKey used for HashTable where key is array of internalized strings.
14477 class StringsKey : public HashTableKey {
14478  public:
14479   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
14480
14481   bool IsMatch(Object* strings) override {
14482     FixedArray* o = FixedArray::cast(strings);
14483     int len = strings_->length();
14484     if (o->length() != len) return false;
14485     for (int i = 0; i < len; i++) {
14486       if (o->get(i) != strings_->get(i)) return false;
14487     }
14488     return true;
14489   }
14490
14491   uint32_t Hash() override { return HashForObject(*strings_); }
14492
14493   uint32_t HashForObject(Object* obj) override {
14494     FixedArray* strings = FixedArray::cast(obj);
14495     int len = strings->length();
14496     uint32_t hash = 0;
14497     for (int i = 0; i < len; i++) {
14498       hash ^= String::cast(strings->get(i))->Hash();
14499     }
14500     return hash;
14501   }
14502
14503   Handle<Object> AsHandle(Isolate* isolate) override { return strings_; }
14504
14505  private:
14506   Handle<FixedArray> strings_;
14507 };
14508
14509
14510 template<typename Derived, typename Shape, typename Key>
14511 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
14512     Isolate* isolate,
14513     int at_least_space_for,
14514     PretenureFlag pretenure) {
14515   DCHECK(0 <= at_least_space_for);
14516   Handle<Derived> dict = DerivedHashTable::New(isolate,
14517                                                at_least_space_for,
14518                                                USE_DEFAULT_MINIMUM_CAPACITY,
14519                                                pretenure);
14520
14521   // Initialize the next enumeration index.
14522   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14523   return dict;
14524 }
14525
14526
14527 template <typename Derived, typename Shape, typename Key>
14528 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
14529     Handle<Derived> dictionary) {
14530   Factory* factory = dictionary->GetIsolate()->factory();
14531   int length = dictionary->NumberOfElements();
14532
14533   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
14534   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
14535
14536   // Fill both the iteration order array and the enumeration order array
14537   // with property details.
14538   int capacity = dictionary->Capacity();
14539   int pos = 0;
14540   for (int i = 0; i < capacity; i++) {
14541     if (dictionary->IsKey(dictionary->KeyAt(i))) {
14542       int index = dictionary->DetailsAt(i).dictionary_index();
14543       iteration_order->set(pos, Smi::FromInt(i));
14544       enumeration_order->set(pos, Smi::FromInt(index));
14545       pos++;
14546     }
14547   }
14548   DCHECK(pos == length);
14549
14550   // Sort the arrays wrt. enumeration order.
14551   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
14552   return iteration_order;
14553 }
14554
14555
14556 template <typename Derived, typename Shape, typename Key>
14557 Handle<FixedArray>
14558 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
14559     Handle<Derived> dictionary) {
14560   int length = dictionary->NumberOfElements();
14561
14562   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
14563   DCHECK(iteration_order->length() == length);
14564
14565   // Iterate over the dictionary using the enumeration order and update
14566   // the dictionary with new enumeration indices.
14567   for (int i = 0; i < length; i++) {
14568     int index = Smi::cast(iteration_order->get(i))->value();
14569     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
14570
14571     int enum_index = PropertyDetails::kInitialIndex + i;
14572
14573     PropertyDetails details = dictionary->DetailsAt(index);
14574     PropertyDetails new_details = details.set_index(enum_index);
14575     dictionary->DetailsAtPut(index, new_details);
14576   }
14577
14578   // Set the next enumeration index.
14579   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
14580   return iteration_order;
14581 }
14582
14583
14584 template<typename Derived, typename Shape, typename Key>
14585 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
14586     Handle<Derived> dictionary, int n, Key key) {
14587   // Check whether there are enough enumeration indices to add n elements.
14588   if (Shape::kIsEnumerable &&
14589       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
14590     // If not, we generate new indices for the properties.
14591     GenerateNewEnumerationIndices(dictionary);
14592   }
14593   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
14594 }
14595
14596
14597 template <typename Derived, typename Shape, typename Key>
14598 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
14599     Handle<Derived> dictionary, int entry) {
14600   Factory* factory = dictionary->GetIsolate()->factory();
14601   PropertyDetails details = dictionary->DetailsAt(entry);
14602   if (!details.IsConfigurable()) return factory->false_value();
14603
14604   dictionary->SetEntry(
14605       entry, factory->the_hole_value(), factory->the_hole_value());
14606   dictionary->ElementRemoved();
14607   return factory->true_value();
14608 }
14609
14610
14611 template<typename Derived, typename Shape, typename Key>
14612 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
14613     Handle<Derived> dictionary, Key key, Handle<Object> value) {
14614   int entry = dictionary->FindEntry(key);
14615
14616   // If the entry is present set the value;
14617   if (entry != Dictionary::kNotFound) {
14618     dictionary->ValueAtPut(entry, *value);
14619     return dictionary;
14620   }
14621
14622   // Check whether the dictionary should be extended.
14623   dictionary = EnsureCapacity(dictionary, 1, key);
14624 #ifdef DEBUG
14625   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
14626 #endif
14627   PropertyDetails details = PropertyDetails::Empty();
14628
14629   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14630   return dictionary;
14631 }
14632
14633
14634 template<typename Derived, typename Shape, typename Key>
14635 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
14636     Handle<Derived> dictionary,
14637     Key key,
14638     Handle<Object> value,
14639     PropertyDetails details) {
14640   // Valdate key is absent.
14641   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
14642   // Check whether the dictionary should be extended.
14643   dictionary = EnsureCapacity(dictionary, 1, key);
14644
14645   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14646   return dictionary;
14647 }
14648
14649
14650 // Add a key, value pair to the dictionary.
14651 template<typename Derived, typename Shape, typename Key>
14652 void Dictionary<Derived, Shape, Key>::AddEntry(
14653     Handle<Derived> dictionary,
14654     Key key,
14655     Handle<Object> value,
14656     PropertyDetails details,
14657     uint32_t hash) {
14658   // Compute the key object.
14659   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
14660
14661   uint32_t entry = dictionary->FindInsertionEntry(hash);
14662   // Insert element at empty or deleted entry
14663   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
14664     // Assign an enumeration index to the property and update
14665     // SetNextEnumerationIndex.
14666     int index = dictionary->NextEnumerationIndex();
14667     details = details.set_index(index);
14668     dictionary->SetNextEnumerationIndex(index + 1);
14669   }
14670   dictionary->SetEntry(entry, k, value, details);
14671   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
14672           dictionary->KeyAt(entry)->IsName()));
14673   dictionary->ElementAdded();
14674 }
14675
14676
14677 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
14678   DisallowHeapAllocation no_allocation;
14679   // If the dictionary requires slow elements an element has already
14680   // been added at a high index.
14681   if (requires_slow_elements()) return;
14682   // Check if this index is high enough that we should require slow
14683   // elements.
14684   if (key > kRequiresSlowElementsLimit) {
14685     // TODO(verwaest): Remove this hack.
14686     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
14687     set_requires_slow_elements();
14688     return;
14689   }
14690   // Update max key value.
14691   Object* max_index_object = get(kMaxNumberKeyIndex);
14692   if (!max_index_object->IsSmi() || max_number_key() < key) {
14693     FixedArray::set(kMaxNumberKeyIndex,
14694                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
14695   }
14696 }
14697
14698
14699 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
14700     Handle<SeededNumberDictionary> dictionary,
14701     uint32_t key,
14702     Handle<Object> value,
14703     PropertyDetails details) {
14704   dictionary->UpdateMaxNumberKey(key);
14705   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14706   return Add(dictionary, key, value, details);
14707 }
14708
14709
14710 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
14711     Handle<UnseededNumberDictionary> dictionary,
14712     uint32_t key,
14713     Handle<Object> value) {
14714   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14715   return Add(dictionary, key, value, PropertyDetails::Empty());
14716 }
14717
14718
14719 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
14720     Handle<SeededNumberDictionary> dictionary,
14721     uint32_t key,
14722     Handle<Object> value) {
14723   dictionary->UpdateMaxNumberKey(key);
14724   return AtPut(dictionary, key, value);
14725 }
14726
14727
14728 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
14729     Handle<UnseededNumberDictionary> dictionary,
14730     uint32_t key,
14731     Handle<Object> value) {
14732   return AtPut(dictionary, key, value);
14733 }
14734
14735
14736 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
14737     Handle<SeededNumberDictionary> dictionary,
14738     uint32_t key,
14739     Handle<Object> value,
14740     PropertyDetails details) {
14741   int entry = dictionary->FindEntry(key);
14742   if (entry == kNotFound) {
14743     return AddNumberEntry(dictionary, key, value, details);
14744   }
14745   // Preserve enumeration index.
14746   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
14747   Handle<Object> object_key =
14748       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14749   dictionary->SetEntry(entry, object_key, value, details);
14750   return dictionary;
14751 }
14752
14753
14754 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
14755     Handle<UnseededNumberDictionary> dictionary,
14756     uint32_t key,
14757     Handle<Object> value) {
14758   int entry = dictionary->FindEntry(key);
14759   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
14760   Handle<Object> object_key =
14761       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14762   dictionary->SetEntry(entry, object_key, value);
14763   return dictionary;
14764 }
14765
14766
14767 template <typename Derived, typename Shape, typename Key>
14768 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
14769     PropertyAttributes filter) {
14770   int capacity = this->Capacity();
14771   int result = 0;
14772   for (int i = 0; i < capacity; i++) {
14773     Object* k = this->KeyAt(i);
14774     if (this->IsKey(k) && !FilterKey(k, filter)) {
14775       if (this->IsDeleted(i)) continue;
14776       PropertyDetails details = this->DetailsAt(i);
14777       PropertyAttributes attr = details.attributes();
14778       if ((attr & filter) == 0) result++;
14779     }
14780   }
14781   return result;
14782 }
14783
14784
14785 template <typename Derived, typename Shape, typename Key>
14786 bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
14787   int capacity = this->Capacity();
14788   for (int i = 0; i < capacity; i++) {
14789     Object* k = this->KeyAt(i);
14790     if (this->IsKey(k) && !FilterKey(k, NONE)) {
14791       if (this->IsDeleted(i)) continue;
14792       PropertyDetails details = this->DetailsAt(i);
14793       if (details.type() == ACCESSOR_CONSTANT) return true;
14794       PropertyAttributes attr = details.attributes();
14795       if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true;
14796     }
14797   }
14798   return false;
14799 }
14800
14801
14802 template <typename Dictionary>
14803 struct EnumIndexComparator {
14804   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
14805   bool operator() (Smi* a, Smi* b) {
14806     PropertyDetails da(dict->DetailsAt(a->value()));
14807     PropertyDetails db(dict->DetailsAt(b->value()));
14808     return da.dictionary_index() < db.dictionary_index();
14809   }
14810   Dictionary* dict;
14811 };
14812
14813
14814 template <typename Derived, typename Shape, typename Key>
14815 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
14816   int length = storage->length();
14817   int capacity = this->Capacity();
14818   int properties = 0;
14819   for (int i = 0; i < capacity; i++) {
14820     Object* k = this->KeyAt(i);
14821     if (this->IsKey(k) && !k->IsSymbol()) {
14822       PropertyDetails details = this->DetailsAt(i);
14823       if (details.IsDontEnum() || this->IsDeleted(i)) continue;
14824       storage->set(properties, Smi::FromInt(i));
14825       properties++;
14826       if (properties == length) break;
14827     }
14828   }
14829   CHECK_EQ(length, properties);
14830   EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
14831   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
14832   std::sort(start, start + length, cmp);
14833   for (int i = 0; i < length; i++) {
14834     int index = Smi::cast(storage->get(i))->value();
14835     storage->set(i, this->KeyAt(index));
14836   }
14837 }
14838
14839
14840 template <typename Derived, typename Shape, typename Key>
14841 int Dictionary<Derived, Shape, Key>::CopyKeysTo(
14842     FixedArray* storage, int index, PropertyAttributes filter,
14843     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
14844   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
14845   int start_index = index;
14846   int capacity = this->Capacity();
14847   for (int i = 0; i < capacity; i++) {
14848     Object* k = this->KeyAt(i);
14849     if (this->IsKey(k) && !FilterKey(k, filter)) {
14850       if (this->IsDeleted(i)) continue;
14851       PropertyDetails details = this->DetailsAt(i);
14852       PropertyAttributes attr = details.attributes();
14853       if ((attr & filter) == 0) storage->set(index++, k);
14854     }
14855   }
14856   if (sort_mode == Dictionary::SORTED) {
14857     storage->SortPairs(storage, index);
14858   }
14859   DCHECK(storage->length() >= index);
14860   return index - start_index;
14861 }
14862
14863
14864 // Backwards lookup (slow).
14865 template<typename Derived, typename Shape, typename Key>
14866 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
14867   int capacity = this->Capacity();
14868   for (int i = 0; i < capacity; i++) {
14869     Object* k = this->KeyAt(i);
14870     if (this->IsKey(k)) {
14871       Object* e = this->ValueAt(i);
14872       // TODO(dcarney): this should be templatized.
14873       if (e->IsPropertyCell()) {
14874         e = PropertyCell::cast(e)->value();
14875       }
14876       if (e == value) return k;
14877     }
14878   }
14879   Heap* heap = Dictionary::GetHeap();
14880   return heap->undefined_value();
14881 }
14882
14883
14884 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
14885                                 int32_t hash) {
14886   DisallowHeapAllocation no_gc;
14887   DCHECK(IsKey(*key));
14888
14889   int entry = FindEntry(isolate, key, hash);
14890   if (entry == kNotFound) return isolate->heap()->the_hole_value();
14891   return get(EntryToIndex(entry) + 1);
14892 }
14893
14894
14895 Object* ObjectHashTable::Lookup(Handle<Object> key) {
14896   DisallowHeapAllocation no_gc;
14897   DCHECK(IsKey(*key));
14898
14899   Isolate* isolate = GetIsolate();
14900
14901   // If the object does not have an identity hash, it was never used as a key.
14902   Object* hash = key->GetHash();
14903   if (hash->IsUndefined()) {
14904     return isolate->heap()->the_hole_value();
14905   }
14906   return Lookup(isolate, key, Smi::cast(hash)->value());
14907 }
14908
14909
14910 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
14911   return Lookup(GetIsolate(), key, hash);
14912 }
14913
14914
14915 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14916                                              Handle<Object> key,
14917                                              Handle<Object> value) {
14918   DCHECK(table->IsKey(*key));
14919   DCHECK(!value->IsTheHole());
14920
14921   Isolate* isolate = table->GetIsolate();
14922   // Make sure the key object has an identity hash code.
14923   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
14924
14925   return Put(table, key, value, hash);
14926 }
14927
14928
14929 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14930                                              Handle<Object> key,
14931                                              Handle<Object> value,
14932                                              int32_t hash) {
14933   DCHECK(table->IsKey(*key));
14934   DCHECK(!value->IsTheHole());
14935
14936   Isolate* isolate = table->GetIsolate();
14937
14938   int entry = table->FindEntry(isolate, key, hash);
14939
14940   // Key is already in table, just overwrite value.
14941   if (entry != kNotFound) {
14942     table->set(EntryToIndex(entry) + 1, *value);
14943     return table;
14944   }
14945
14946   // Check whether the hash table should be extended.
14947   table = EnsureCapacity(table, 1, key);
14948   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
14949   return table;
14950 }
14951
14952
14953 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14954                                                 Handle<Object> key,
14955                                                 bool* was_present) {
14956   DCHECK(table->IsKey(*key));
14957
14958   Object* hash = key->GetHash();
14959   if (hash->IsUndefined()) {
14960     *was_present = false;
14961     return table;
14962   }
14963
14964   return Remove(table, key, was_present, Smi::cast(hash)->value());
14965 }
14966
14967
14968 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14969                                                 Handle<Object> key,
14970                                                 bool* was_present,
14971                                                 int32_t hash) {
14972   DCHECK(table->IsKey(*key));
14973
14974   int entry = table->FindEntry(table->GetIsolate(), key, hash);
14975   if (entry == kNotFound) {
14976     *was_present = false;
14977     return table;
14978   }
14979
14980   *was_present = true;
14981   table->RemoveEntry(entry);
14982   return Shrink(table, key);
14983 }
14984
14985
14986 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
14987   set(EntryToIndex(entry), key);
14988   set(EntryToIndex(entry) + 1, value);
14989   ElementAdded();
14990 }
14991
14992
14993 void ObjectHashTable::RemoveEntry(int entry) {
14994   set_the_hole(EntryToIndex(entry));
14995   set_the_hole(EntryToIndex(entry) + 1);
14996   ElementRemoved();
14997 }
14998
14999
15000 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
15001   DisallowHeapAllocation no_gc;
15002   DCHECK(IsKey(*key));
15003   int entry = FindEntry(key);
15004   if (entry == kNotFound) return GetHeap()->the_hole_value();
15005   return get(EntryToValueIndex(entry));
15006 }
15007
15008
15009 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
15010                                          Handle<HeapObject> key,
15011                                          Handle<HeapObject> value) {
15012   DCHECK(table->IsKey(*key));
15013   int entry = table->FindEntry(key);
15014   // Key is already in table, just overwrite value.
15015   if (entry != kNotFound) {
15016     table->set(EntryToValueIndex(entry), *value);
15017     return table;
15018   }
15019
15020   Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
15021
15022   // Check whether the hash table should be extended.
15023   table = EnsureCapacity(table, 1, key, TENURED);
15024
15025   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
15026   return table;
15027 }
15028
15029
15030 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
15031                              Handle<HeapObject> value) {
15032   DisallowHeapAllocation no_allocation;
15033   set(EntryToIndex(entry), *key_cell);
15034   set(EntryToValueIndex(entry), *value);
15035   ElementAdded();
15036 }
15037
15038
15039 #ifdef DEBUG
15040 Object* WeakValueHashTable::LookupWeak(Handle<Object> key) {
15041   Object* value = Lookup(key);
15042   if (value->IsWeakCell() && !WeakCell::cast(value)->cleared()) {
15043     value = WeakCell::cast(value)->value();
15044   }
15045   return value;
15046 }
15047 #endif  // DEBUG
15048
15049
15050 Handle<WeakValueHashTable> WeakValueHashTable::PutWeak(
15051     Handle<WeakValueHashTable> table, Handle<Object> key,
15052     Handle<HeapObject> value) {
15053   Handle<WeakCell> cell = value->GetIsolate()->factory()->NewWeakCell(value);
15054   return Handle<WeakValueHashTable>::cast(
15055       Put(Handle<ObjectHashTable>::cast(table), key, cell));
15056 }
15057
15058
15059 Handle<FixedArray> WeakValueHashTable::GetWeakValues(
15060     Handle<WeakValueHashTable> table) {
15061   Isolate* isolate = table->GetIsolate();
15062   uint32_t capacity = table->Capacity();
15063   Handle<FixedArray> results = isolate->factory()->NewFixedArray(capacity);
15064   int length = 0;
15065   for (uint32_t i = 0; i < capacity; i++) {
15066     uint32_t key_index = table->EntryToIndex(i);
15067     Object* key = table->get(key_index);
15068     if (!table->IsKey(key)) continue;
15069     uint32_t value_index = table->EntryToValueIndex(i);
15070     WeakCell* value_cell = WeakCell::cast(table->get(value_index));
15071     if (value_cell->cleared()) {
15072       table->RemoveEntry(i);
15073     } else {
15074       results->set(length++, value_cell->value());
15075     }
15076   }
15077   results->Shrink(length);
15078   return results;
15079 }
15080
15081
15082 template<class Derived, class Iterator, int entrysize>
15083 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
15084     Isolate* isolate, int capacity, PretenureFlag pretenure) {
15085   // Capacity must be a power of two, since we depend on being able
15086   // to divide and multiple by 2 (kLoadFactor) to derive capacity
15087   // from number of buckets. If we decide to change kLoadFactor
15088   // to something other than 2, capacity should be stored as another
15089   // field of this object.
15090   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
15091   if (capacity > kMaxCapacity) {
15092     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
15093   }
15094   int num_buckets = capacity / kLoadFactor;
15095   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
15096       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
15097   backing_store->set_map_no_write_barrier(
15098       isolate->heap()->ordered_hash_table_map());
15099   Handle<Derived> table = Handle<Derived>::cast(backing_store);
15100   for (int i = 0; i < num_buckets; ++i) {
15101     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
15102   }
15103   table->SetNumberOfBuckets(num_buckets);
15104   table->SetNumberOfElements(0);
15105   table->SetNumberOfDeletedElements(0);
15106   return table;
15107 }
15108
15109
15110 template<class Derived, class Iterator, int entrysize>
15111 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
15112     Handle<Derived> table) {
15113   DCHECK(!table->IsObsolete());
15114
15115   int nof = table->NumberOfElements();
15116   int nod = table->NumberOfDeletedElements();
15117   int capacity = table->Capacity();
15118   if ((nof + nod) < capacity) return table;
15119   // Don't need to grow if we can simply clear out deleted entries instead.
15120   // Note that we can't compact in place, though, so we always allocate
15121   // a new table.
15122   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
15123 }
15124
15125
15126 template<class Derived, class Iterator, int entrysize>
15127 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
15128     Handle<Derived> table) {
15129   DCHECK(!table->IsObsolete());
15130
15131   int nof = table->NumberOfElements();
15132   int capacity = table->Capacity();
15133   if (nof >= (capacity >> 2)) return table;
15134   return Rehash(table, capacity / 2);
15135 }
15136
15137
15138 template<class Derived, class Iterator, int entrysize>
15139 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
15140     Handle<Derived> table) {
15141   DCHECK(!table->IsObsolete());
15142
15143   Handle<Derived> new_table =
15144       Allocate(table->GetIsolate(),
15145                kMinCapacity,
15146                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15147
15148   table->SetNextTable(*new_table);
15149   table->SetNumberOfDeletedElements(kClearedTableSentinel);
15150
15151   return new_table;
15152 }
15153
15154
15155 template<class Derived, class Iterator, int entrysize>
15156 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15157     Handle<Derived> table, int new_capacity) {
15158   DCHECK(!table->IsObsolete());
15159
15160   Handle<Derived> new_table =
15161       Allocate(table->GetIsolate(),
15162                new_capacity,
15163                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15164   int nof = table->NumberOfElements();
15165   int nod = table->NumberOfDeletedElements();
15166   int new_buckets = new_table->NumberOfBuckets();
15167   int new_entry = 0;
15168   int removed_holes_index = 0;
15169
15170   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
15171     Object* key = table->KeyAt(old_entry);
15172     if (key->IsTheHole()) {
15173       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
15174       continue;
15175     }
15176
15177     Object* hash = key->GetHash();
15178     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
15179     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
15180     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15181     int new_index = new_table->EntryToIndex(new_entry);
15182     int old_index = table->EntryToIndex(old_entry);
15183     for (int i = 0; i < entrysize; ++i) {
15184       Object* value = table->get(old_index + i);
15185       new_table->set(new_index + i, value);
15186     }
15187     new_table->set(new_index + kChainOffset, chain_entry);
15188     ++new_entry;
15189   }
15190
15191   DCHECK_EQ(nod, removed_holes_index);
15192
15193   new_table->SetNumberOfElements(nof);
15194   table->SetNextTable(*new_table);
15195
15196   return new_table;
15197 }
15198
15199
15200 template Handle<OrderedHashSet>
15201 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
15202     Isolate* isolate, int capacity, PretenureFlag pretenure);
15203
15204 template Handle<OrderedHashSet>
15205 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
15206     Handle<OrderedHashSet> table);
15207
15208 template Handle<OrderedHashSet>
15209 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15210     Handle<OrderedHashSet> table);
15211
15212 template Handle<OrderedHashSet>
15213 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15214     Handle<OrderedHashSet> table);
15215
15216
15217 template Handle<OrderedHashMap>
15218 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15219     Isolate* isolate, int capacity, PretenureFlag pretenure);
15220
15221 template Handle<OrderedHashMap>
15222 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15223     Handle<OrderedHashMap> table);
15224
15225 template Handle<OrderedHashMap>
15226 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15227     Handle<OrderedHashMap> table);
15228
15229 template Handle<OrderedHashMap>
15230 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15231     Handle<OrderedHashMap> table);
15232
15233
15234 template<class Derived, class TableType>
15235 void OrderedHashTableIterator<Derived, TableType>::Transition() {
15236   DisallowHeapAllocation no_allocation;
15237   TableType* table = TableType::cast(this->table());
15238   if (!table->IsObsolete()) return;
15239
15240   int index = Smi::cast(this->index())->value();
15241   while (table->IsObsolete()) {
15242     TableType* next_table = table->NextTable();
15243
15244     if (index > 0) {
15245       int nod = table->NumberOfDeletedElements();
15246
15247       if (nod == TableType::kClearedTableSentinel) {
15248         index = 0;
15249       } else {
15250         int old_index = index;
15251         for (int i = 0; i < nod; ++i) {
15252           int removed_index = table->RemovedIndexAt(i);
15253           if (removed_index >= old_index) break;
15254           --index;
15255         }
15256       }
15257     }
15258
15259     table = next_table;
15260   }
15261
15262   set_table(table);
15263   set_index(Smi::FromInt(index));
15264 }
15265
15266
15267 template<class Derived, class TableType>
15268 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
15269   DisallowHeapAllocation no_allocation;
15270   if (this->table()->IsUndefined()) return false;
15271
15272   Transition();
15273
15274   TableType* table = TableType::cast(this->table());
15275   int index = Smi::cast(this->index())->value();
15276   int used_capacity = table->UsedCapacity();
15277
15278   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
15279     index++;
15280   }
15281
15282   set_index(Smi::FromInt(index));
15283
15284   if (index < used_capacity) return true;
15285
15286   set_table(GetHeap()->undefined_value());
15287   return false;
15288 }
15289
15290
15291 template<class Derived, class TableType>
15292 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
15293   DisallowHeapAllocation no_allocation;
15294   if (HasMore()) {
15295     FixedArray* array = FixedArray::cast(value_array->elements());
15296     static_cast<Derived*>(this)->PopulateValueArray(array);
15297     MoveNext();
15298     return Smi::cast(kind());
15299   }
15300   return Smi::FromInt(0);
15301 }
15302
15303
15304 template Smi*
15305 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
15306     JSArray* value_array);
15307
15308 template bool
15309 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
15310
15311 template void
15312 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
15313
15314 template Object*
15315 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
15316
15317 template void
15318 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
15319
15320
15321 template Smi*
15322 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
15323     JSArray* value_array);
15324
15325 template bool
15326 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
15327
15328 template void
15329 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
15330
15331 template Object*
15332 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
15333
15334 template void
15335 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
15336
15337
15338 // Check if there is a break point at this code position.
15339 bool DebugInfo::HasBreakPoint(int code_position) {
15340   // Get the break point info object for this code position.
15341   Object* break_point_info = GetBreakPointInfo(code_position);
15342
15343   // If there is no break point info object or no break points in the break
15344   // point info object there is no break point at this code position.
15345   if (break_point_info->IsUndefined()) return false;
15346   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
15347 }
15348
15349
15350 // Get the break point info object for this code position.
15351 Object* DebugInfo::GetBreakPointInfo(int code_position) {
15352   // Find the index of the break point info object for this code position.
15353   int index = GetBreakPointInfoIndex(code_position);
15354
15355   // Return the break point info object if any.
15356   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
15357   return BreakPointInfo::cast(break_points()->get(index));
15358 }
15359
15360
15361 // Clear a break point at the specified code position.
15362 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
15363                                 int code_position,
15364                                 Handle<Object> break_point_object) {
15365   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15366                                   debug_info->GetIsolate());
15367   if (break_point_info->IsUndefined()) return;
15368   BreakPointInfo::ClearBreakPoint(
15369       Handle<BreakPointInfo>::cast(break_point_info),
15370       break_point_object);
15371 }
15372
15373
15374 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
15375                               int code_position,
15376                               int source_position,
15377                               int statement_position,
15378                               Handle<Object> break_point_object) {
15379   Isolate* isolate = debug_info->GetIsolate();
15380   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15381                                   isolate);
15382   if (!break_point_info->IsUndefined()) {
15383     BreakPointInfo::SetBreakPoint(
15384         Handle<BreakPointInfo>::cast(break_point_info),
15385         break_point_object);
15386     return;
15387   }
15388
15389   // Adding a new break point for a code position which did not have any
15390   // break points before. Try to find a free slot.
15391   int index = kNoBreakPointInfo;
15392   for (int i = 0; i < debug_info->break_points()->length(); i++) {
15393     if (debug_info->break_points()->get(i)->IsUndefined()) {
15394       index = i;
15395       break;
15396     }
15397   }
15398   if (index == kNoBreakPointInfo) {
15399     // No free slot - extend break point info array.
15400     Handle<FixedArray> old_break_points =
15401         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
15402     Handle<FixedArray> new_break_points =
15403         isolate->factory()->NewFixedArray(
15404             old_break_points->length() +
15405             DebugInfo::kEstimatedNofBreakPointsInFunction);
15406
15407     debug_info->set_break_points(*new_break_points);
15408     for (int i = 0; i < old_break_points->length(); i++) {
15409       new_break_points->set(i, old_break_points->get(i));
15410     }
15411     index = old_break_points->length();
15412   }
15413   DCHECK(index != kNoBreakPointInfo);
15414
15415   // Allocate new BreakPointInfo object and set the break point.
15416   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
15417       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
15418   new_break_point_info->set_code_position(Smi::FromInt(code_position));
15419   new_break_point_info->set_source_position(Smi::FromInt(source_position));
15420   new_break_point_info->
15421       set_statement_position(Smi::FromInt(statement_position));
15422   new_break_point_info->set_break_point_objects(
15423       isolate->heap()->undefined_value());
15424   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
15425   debug_info->break_points()->set(index, *new_break_point_info);
15426 }
15427
15428
15429 // Get the break point objects for a code position.
15430 Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
15431   Object* break_point_info = GetBreakPointInfo(code_position);
15432   if (break_point_info->IsUndefined()) {
15433     return GetIsolate()->factory()->undefined_value();
15434   }
15435   return Handle<Object>(
15436       BreakPointInfo::cast(break_point_info)->break_point_objects(),
15437       GetIsolate());
15438 }
15439
15440
15441 // Get the total number of break points.
15442 int DebugInfo::GetBreakPointCount() {
15443   if (break_points()->IsUndefined()) return 0;
15444   int count = 0;
15445   for (int i = 0; i < break_points()->length(); i++) {
15446     if (!break_points()->get(i)->IsUndefined()) {
15447       BreakPointInfo* break_point_info =
15448           BreakPointInfo::cast(break_points()->get(i));
15449       count += break_point_info->GetBreakPointCount();
15450     }
15451   }
15452   return count;
15453 }
15454
15455
15456 Handle<Object> DebugInfo::FindBreakPointInfo(
15457     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
15458   Isolate* isolate = debug_info->GetIsolate();
15459   if (!debug_info->break_points()->IsUndefined()) {
15460     for (int i = 0; i < debug_info->break_points()->length(); i++) {
15461       if (!debug_info->break_points()->get(i)->IsUndefined()) {
15462         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
15463             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
15464         if (BreakPointInfo::HasBreakPointObject(break_point_info,
15465                                                 break_point_object)) {
15466           return break_point_info;
15467         }
15468       }
15469     }
15470   }
15471   return isolate->factory()->undefined_value();
15472 }
15473
15474
15475 // Find the index of the break point info object for the specified code
15476 // position.
15477 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
15478   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
15479   for (int i = 0; i < break_points()->length(); i++) {
15480     if (!break_points()->get(i)->IsUndefined()) {
15481       BreakPointInfo* break_point_info =
15482           BreakPointInfo::cast(break_points()->get(i));
15483       if (break_point_info->code_position()->value() == code_position) {
15484         return i;
15485       }
15486     }
15487   }
15488   return kNoBreakPointInfo;
15489 }
15490
15491
15492 // Remove the specified break point object.
15493 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
15494                                      Handle<Object> break_point_object) {
15495   Isolate* isolate = break_point_info->GetIsolate();
15496   // If there are no break points just ignore.
15497   if (break_point_info->break_point_objects()->IsUndefined()) return;
15498   // If there is a single break point clear it if it is the same.
15499   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15500     if (break_point_info->break_point_objects() == *break_point_object) {
15501       break_point_info->set_break_point_objects(
15502           isolate->heap()->undefined_value());
15503     }
15504     return;
15505   }
15506   // If there are multiple break points shrink the array
15507   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
15508   Handle<FixedArray> old_array =
15509       Handle<FixedArray>(
15510           FixedArray::cast(break_point_info->break_point_objects()));
15511   Handle<FixedArray> new_array =
15512       isolate->factory()->NewFixedArray(old_array->length() - 1);
15513   int found_count = 0;
15514   for (int i = 0; i < old_array->length(); i++) {
15515     if (old_array->get(i) == *break_point_object) {
15516       DCHECK(found_count == 0);
15517       found_count++;
15518     } else {
15519       new_array->set(i - found_count, old_array->get(i));
15520     }
15521   }
15522   // If the break point was found in the list change it.
15523   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
15524 }
15525
15526
15527 // Add the specified break point object.
15528 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
15529                                    Handle<Object> break_point_object) {
15530   Isolate* isolate = break_point_info->GetIsolate();
15531
15532   // If there was no break point objects before just set it.
15533   if (break_point_info->break_point_objects()->IsUndefined()) {
15534     break_point_info->set_break_point_objects(*break_point_object);
15535     return;
15536   }
15537   // If the break point object is the same as before just ignore.
15538   if (break_point_info->break_point_objects() == *break_point_object) return;
15539   // If there was one break point object before replace with array.
15540   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15541     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
15542     array->set(0, break_point_info->break_point_objects());
15543     array->set(1, *break_point_object);
15544     break_point_info->set_break_point_objects(*array);
15545     return;
15546   }
15547   // If there was more than one break point before extend array.
15548   Handle<FixedArray> old_array =
15549       Handle<FixedArray>(
15550           FixedArray::cast(break_point_info->break_point_objects()));
15551   Handle<FixedArray> new_array =
15552       isolate->factory()->NewFixedArray(old_array->length() + 1);
15553   for (int i = 0; i < old_array->length(); i++) {
15554     // If the break point was there before just ignore.
15555     if (old_array->get(i) == *break_point_object) return;
15556     new_array->set(i, old_array->get(i));
15557   }
15558   // Add the new break point.
15559   new_array->set(old_array->length(), *break_point_object);
15560   break_point_info->set_break_point_objects(*new_array);
15561 }
15562
15563
15564 bool BreakPointInfo::HasBreakPointObject(
15565     Handle<BreakPointInfo> break_point_info,
15566     Handle<Object> break_point_object) {
15567   // No break point.
15568   if (break_point_info->break_point_objects()->IsUndefined()) return false;
15569   // Single break point.
15570   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15571     return break_point_info->break_point_objects() == *break_point_object;
15572   }
15573   // Multiple break points.
15574   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
15575   for (int i = 0; i < array->length(); i++) {
15576     if (array->get(i) == *break_point_object) {
15577       return true;
15578     }
15579   }
15580   return false;
15581 }
15582
15583
15584 // Get the number of break points.
15585 int BreakPointInfo::GetBreakPointCount() {
15586   // No break point.
15587   if (break_point_objects()->IsUndefined()) return 0;
15588   // Single break point.
15589   if (!break_point_objects()->IsFixedArray()) return 1;
15590   // Multiple break points.
15591   return FixedArray::cast(break_point_objects())->length();
15592 }
15593
15594
15595 Object* JSDate::GetField(Object* object, Smi* index) {
15596   return JSDate::cast(object)->DoGetField(
15597       static_cast<FieldIndex>(index->value()));
15598 }
15599
15600
15601 Object* JSDate::DoGetField(FieldIndex index) {
15602   DCHECK(index != kDateValue);
15603
15604   DateCache* date_cache = GetIsolate()->date_cache();
15605
15606   if (index < kFirstUncachedField) {
15607     Object* stamp = cache_stamp();
15608     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
15609       // Since the stamp is not NaN, the value is also not NaN.
15610       int64_t local_time_ms =
15611           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
15612       SetCachedFields(local_time_ms, date_cache);
15613     }
15614     switch (index) {
15615       case kYear: return year();
15616       case kMonth: return month();
15617       case kDay: return day();
15618       case kWeekday: return weekday();
15619       case kHour: return hour();
15620       case kMinute: return min();
15621       case kSecond: return sec();
15622       default: UNREACHABLE();
15623     }
15624   }
15625
15626   if (index >= kFirstUTCField) {
15627     return GetUTCField(index, value()->Number(), date_cache);
15628   }
15629
15630   double time = value()->Number();
15631   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
15632
15633   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
15634   int days = DateCache::DaysFromTime(local_time_ms);
15635
15636   if (index == kDays) return Smi::FromInt(days);
15637
15638   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15639   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
15640   DCHECK(index == kTimeInDay);
15641   return Smi::FromInt(time_in_day_ms);
15642 }
15643
15644
15645 Object* JSDate::GetUTCField(FieldIndex index,
15646                             double value,
15647                             DateCache* date_cache) {
15648   DCHECK(index >= kFirstUTCField);
15649
15650   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
15651
15652   int64_t time_ms = static_cast<int64_t>(value);
15653
15654   if (index == kTimezoneOffset) {
15655     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
15656   }
15657
15658   int days = DateCache::DaysFromTime(time_ms);
15659
15660   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
15661
15662   if (index <= kDayUTC) {
15663     int year, month, day;
15664     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15665     if (index == kYearUTC) return Smi::FromInt(year);
15666     if (index == kMonthUTC) return Smi::FromInt(month);
15667     DCHECK(index == kDayUTC);
15668     return Smi::FromInt(day);
15669   }
15670
15671   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
15672   switch (index) {
15673     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
15674     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
15675     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
15676     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
15677     case kDaysUTC: return Smi::FromInt(days);
15678     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
15679     default: UNREACHABLE();
15680   }
15681
15682   UNREACHABLE();
15683   return NULL;
15684 }
15685
15686
15687 void JSDate::SetValue(Object* value, bool is_value_nan) {
15688   set_value(value);
15689   if (is_value_nan) {
15690     HeapNumber* nan = GetIsolate()->heap()->nan_value();
15691     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
15692     set_year(nan, SKIP_WRITE_BARRIER);
15693     set_month(nan, SKIP_WRITE_BARRIER);
15694     set_day(nan, SKIP_WRITE_BARRIER);
15695     set_hour(nan, SKIP_WRITE_BARRIER);
15696     set_min(nan, SKIP_WRITE_BARRIER);
15697     set_sec(nan, SKIP_WRITE_BARRIER);
15698     set_weekday(nan, SKIP_WRITE_BARRIER);
15699   } else {
15700     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
15701   }
15702 }
15703
15704
15705 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
15706   int days = DateCache::DaysFromTime(local_time_ms);
15707   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15708   int year, month, day;
15709   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15710   int weekday = date_cache->Weekday(days);
15711   int hour = time_in_day_ms / (60 * 60 * 1000);
15712   int min = (time_in_day_ms / (60 * 1000)) % 60;
15713   int sec = (time_in_day_ms / 1000) % 60;
15714   set_cache_stamp(date_cache->stamp());
15715   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15716   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15717   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15718   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15719   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15720   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15721   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15722 }
15723
15724
15725 void JSArrayBuffer::Neuter() {
15726   CHECK(is_neuterable());
15727   CHECK(is_external());
15728   set_backing_store(NULL);
15729   set_byte_length(Smi::FromInt(0));
15730   set_was_neutered(true);
15731 }
15732
15733
15734 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
15735   switch (elements_kind) {
15736 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
15737     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
15738
15739     TYPED_ARRAYS(TYPED_ARRAY_CASE)
15740 #undef TYPED_ARRAY_CASE
15741
15742     default:
15743       UNREACHABLE();
15744       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
15745   }
15746 }
15747
15748
15749 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
15750     Handle<JSTypedArray> typed_array) {
15751
15752   Handle<Map> map(typed_array->map());
15753   Isolate* isolate = typed_array->GetIsolate();
15754
15755   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
15756
15757   Handle<Map> new_map = Map::TransitionElementsTo(
15758           map,
15759           FixedToExternalElementsKind(map->elements_kind()));
15760
15761   Handle<FixedTypedArrayBase> fixed_typed_array(
15762       FixedTypedArrayBase::cast(typed_array->elements()));
15763
15764   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
15765                                isolate);
15766   void* backing_store =
15767       isolate->array_buffer_allocator()->AllocateUninitialized(
15768           fixed_typed_array->DataSize());
15769   buffer->set_backing_store(backing_store);
15770   buffer->set_is_external(false);
15771   isolate->heap()->RegisterNewArrayBuffer(isolate->heap()->InNewSpace(*buffer),
15772                                           backing_store,
15773                                           fixed_typed_array->DataSize());
15774   memcpy(buffer->backing_store(),
15775          fixed_typed_array->DataPtr(),
15776          fixed_typed_array->DataSize());
15777   Handle<ExternalArray> new_elements =
15778       isolate->factory()->NewExternalArray(
15779           fixed_typed_array->length(), typed_array->type(),
15780           static_cast<uint8_t*>(buffer->backing_store()));
15781
15782   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
15783
15784   return buffer;
15785 }
15786
15787
15788 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
15789   if (IsExternalArrayElementsKind(map()->elements_kind())) {
15790     Handle<Object> result(buffer(), GetIsolate());
15791     return Handle<JSArrayBuffer>::cast(result);
15792   }
15793   Handle<JSTypedArray> self(this);
15794   return MaterializeArrayBuffer(self);
15795 }
15796
15797
15798 Handle<PropertyCell> PropertyCell::InvalidateEntry(
15799     Handle<GlobalDictionary> dictionary, int entry) {
15800   Isolate* isolate = dictionary->GetIsolate();
15801   // Swap with a copy.
15802   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15803   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15804   auto new_cell = isolate->factory()->NewPropertyCell();
15805   new_cell->set_value(cell->value());
15806   dictionary->ValueAtPut(entry, *new_cell);
15807   bool is_the_hole = cell->value()->IsTheHole();
15808   // Cell is officially mutable henceforth.
15809   PropertyDetails details = cell->property_details();
15810   details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
15811                                               : PropertyCellType::kMutable);
15812   new_cell->set_property_details(details);
15813   // Old cell is ready for invalidation.
15814   if (is_the_hole) {
15815     cell->set_value(isolate->heap()->undefined_value());
15816   } else {
15817     cell->set_value(isolate->heap()->the_hole_value());
15818   }
15819   details = details.set_cell_type(PropertyCellType::kInvalidated);
15820   cell->set_property_details(details);
15821   cell->dependent_code()->DeoptimizeDependentCodeGroup(
15822       isolate, DependentCode::kPropertyCellChangedGroup);
15823   return new_cell;
15824 }
15825
15826
15827 PropertyCellConstantType PropertyCell::GetConstantType() {
15828   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
15829   return PropertyCellConstantType::kStableMap;
15830 }
15831
15832
15833 static bool RemainsConstantType(Handle<PropertyCell> cell,
15834                                 Handle<Object> value) {
15835   // TODO(dcarney): double->smi and smi->double transition from kConstant
15836   if (cell->value()->IsSmi() && value->IsSmi()) {
15837     return true;
15838   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
15839     return HeapObject::cast(cell->value())->map() ==
15840                HeapObject::cast(*value)->map() &&
15841            HeapObject::cast(*value)->map()->is_stable();
15842   }
15843   return false;
15844 }
15845
15846
15847 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
15848                                            Handle<Object> value,
15849                                            PropertyDetails details) {
15850   PropertyCellType type = details.cell_type();
15851   DCHECK(!value->IsTheHole());
15852   if (cell->value()->IsTheHole()) {
15853     switch (type) {
15854       // Only allow a cell to transition once into constant state.
15855       case PropertyCellType::kUninitialized:
15856         if (value->IsUndefined()) return PropertyCellType::kUndefined;
15857         return PropertyCellType::kConstant;
15858       case PropertyCellType::kInvalidated:
15859         return PropertyCellType::kMutable;
15860       default:
15861         UNREACHABLE();
15862         return PropertyCellType::kMutable;
15863     }
15864   }
15865   switch (type) {
15866     case PropertyCellType::kUndefined:
15867       return PropertyCellType::kConstant;
15868     case PropertyCellType::kConstant:
15869       if (*value == cell->value()) return PropertyCellType::kConstant;
15870     // Fall through.
15871     case PropertyCellType::kConstantType:
15872       if (RemainsConstantType(cell, value)) {
15873         return PropertyCellType::kConstantType;
15874       }
15875     // Fall through.
15876     case PropertyCellType::kMutable:
15877       return PropertyCellType::kMutable;
15878   }
15879   UNREACHABLE();
15880   return PropertyCellType::kMutable;
15881 }
15882
15883
15884 void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
15885                               Handle<Object> value, PropertyDetails details) {
15886   DCHECK(!value->IsTheHole());
15887   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15888   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15889   const PropertyDetails original_details = cell->property_details();
15890   // Data accesses could be cached in ics or optimized code.
15891   bool invalidate =
15892       original_details.kind() == kData && details.kind() == kAccessor;
15893   int index = original_details.dictionary_index();
15894   PropertyCellType old_type = original_details.cell_type();
15895   // Preserve the enumeration index unless the property was deleted or never
15896   // initialized.
15897   if (cell->value()->IsTheHole()) {
15898     index = dictionary->NextEnumerationIndex();
15899     dictionary->SetNextEnumerationIndex(index + 1);
15900     // Negative lookup cells must be invalidated.
15901     invalidate = true;
15902   }
15903   DCHECK(index > 0);
15904   details = details.set_index(index);
15905
15906   PropertyCellType new_type = UpdatedType(cell, value, original_details);
15907   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
15908
15909   // Install new property details and cell value.
15910   details = details.set_cell_type(new_type);
15911   cell->set_property_details(details);
15912   cell->set_value(*value);
15913
15914   // Deopt when transitioning from a constant type.
15915   if (!invalidate && (old_type != new_type ||
15916                       original_details.IsReadOnly() != details.IsReadOnly())) {
15917     Isolate* isolate = dictionary->GetIsolate();
15918     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15919         isolate, DependentCode::kPropertyCellChangedGroup);
15920   }
15921 }
15922
15923
15924 // static
15925 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
15926                                             Handle<Object> new_value) {
15927   if (cell->value() != *new_value) {
15928     cell->set_value(*new_value);
15929     Isolate* isolate = cell->GetIsolate();
15930     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15931         isolate, DependentCode::kPropertyCellChangedGroup);
15932   }
15933 }
15934
15935 }  // namespace internal
15936 }  // namespace v8