0eda4912e63902939c8efd1effdc71953670f307
[platform/upstream/nodejs.git] / deps / v8 / 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 <sstream>
6
7 #include "src/v8.h"
8
9 #include "src/accessors.h"
10 #include "src/allocation-site-scopes.h"
11 #include "src/api.h"
12 #include "src/arguments.h"
13 #include "src/base/bits.h"
14 #include "src/bootstrapper.h"
15 #include "src/code-stubs.h"
16 #include "src/codegen.h"
17 #include "src/cpu-profiler.h"
18 #include "src/date.h"
19 #include "src/debug.h"
20 #include "src/deoptimizer.h"
21 #include "src/elements.h"
22 #include "src/execution.h"
23 #include "src/field-index-inl.h"
24 #include "src/field-index.h"
25 #include "src/full-codegen.h"
26 #include "src/heap/mark-compact.h"
27 #include "src/heap/objects-visiting-inl.h"
28 #include "src/hydrogen.h"
29 #include "src/ic/ic.h"
30 #include "src/isolate-inl.h"
31 #include "src/log.h"
32 #include "src/lookup.h"
33 #include "src/macro-assembler.h"
34 #include "src/objects-inl.h"
35 #include "src/prototype.h"
36 #include "src/safepoint-table.h"
37 #include "src/string-search.h"
38 #include "src/string-stream.h"
39 #include "src/utils.h"
40
41 #ifdef ENABLE_DISASSEMBLER
42 #include "src/disasm.h"
43 #include "src/disassembler.h"
44 #endif
45
46 namespace v8 {
47 namespace internal {
48
49 Handle<HeapType> Object::OptimalType(Isolate* isolate,
50                                      Representation representation) {
51   if (representation.IsNone()) return HeapType::None(isolate);
52   if (FLAG_track_field_types) {
53     if (representation.IsHeapObject() && IsHeapObject()) {
54       // We can track only JavaScript objects with stable maps.
55       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
56       if (map->is_stable() &&
57           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
58           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
59         return HeapType::Class(map, isolate);
60       }
61     }
62   }
63   return HeapType::Any(isolate);
64 }
65
66
67 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
68                                          Handle<Object> object,
69                                          Handle<Context> native_context) {
70   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
71   Handle<JSFunction> constructor;
72   if (object->IsNumber()) {
73     constructor = handle(native_context->number_function(), isolate);
74   } else if (object->IsBoolean()) {
75     constructor = handle(native_context->boolean_function(), isolate);
76   } else if (object->IsString()) {
77     constructor = handle(native_context->string_function(), isolate);
78   } else if (object->IsSymbol()) {
79     constructor = handle(native_context->symbol_function(), isolate);
80   } else {
81     return MaybeHandle<JSReceiver>();
82   }
83   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
84   Handle<JSValue>::cast(result)->set_value(*object);
85   return result;
86 }
87
88
89 bool Object::BooleanValue() {
90   if (IsBoolean()) return IsTrue();
91   if (IsSmi()) return Smi::cast(this)->value() != 0;
92   if (IsUndefined() || IsNull()) return false;
93   if (IsUndetectableObject()) return false;   // Undetectable object is false.
94   if (IsString()) return String::cast(this)->length() != 0;
95   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
96   return true;
97 }
98
99
100 bool Object::IsCallable() const {
101   const Object* fun = this;
102   while (fun->IsJSFunctionProxy()) {
103     fun = JSFunctionProxy::cast(fun)->call_trap();
104   }
105   return fun->IsJSFunction() ||
106          (fun->IsHeapObject() &&
107           HeapObject::cast(fun)->map()->has_instance_call_handler());
108 }
109
110
111 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
112   for (; it->IsFound(); it->Next()) {
113     switch (it->state()) {
114       case LookupIterator::NOT_FOUND:
115       case LookupIterator::TRANSITION:
116         UNREACHABLE();
117       case LookupIterator::JSPROXY:
118         return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(),
119                                                it->GetReceiver(), it->name());
120       case LookupIterator::INTERCEPTOR: {
121         MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor(
122             it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
123         if (!maybe_result.is_null()) return maybe_result;
124         if (it->isolate()->has_pending_exception()) return maybe_result;
125         break;
126       }
127       case LookupIterator::ACCESS_CHECK:
128         if (it->HasAccess(v8::ACCESS_GET)) break;
129         return JSObject::GetPropertyWithFailedAccessCheck(it);
130       case LookupIterator::ACCESSOR:
131         return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
132                                        it->GetHolder<JSObject>(),
133                                        it->GetAccessors());
134       case LookupIterator::DATA:
135         return it->GetDataValue();
136     }
137   }
138   return it->factory()->undefined_value();
139 }
140
141
142 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
143                                          Handle<Name> key) {
144   LookupIterator it(object, key,
145                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
146   return GetDataProperty(&it);
147 }
148
149
150 Handle<Object> JSObject::GetDataProperty(LookupIterator* it) {
151   for (; it->IsFound(); it->Next()) {
152     switch (it->state()) {
153       case LookupIterator::INTERCEPTOR:
154       case LookupIterator::NOT_FOUND:
155       case LookupIterator::TRANSITION:
156         UNREACHABLE();
157       case LookupIterator::ACCESS_CHECK:
158         if (it->HasAccess(v8::ACCESS_GET)) continue;
159       // Fall through.
160       case LookupIterator::JSPROXY:
161         it->NotFound();
162         return it->isolate()->factory()->undefined_value();
163       case LookupIterator::ACCESSOR:
164         // TODO(verwaest): For now this doesn't call into
165         // ExecutableAccessorInfo, since clients don't need it. Update once
166         // relevant.
167         it->NotFound();
168         return it->isolate()->factory()->undefined_value();
169       case LookupIterator::DATA:
170         return it->GetDataValue();
171     }
172   }
173   return it->isolate()->factory()->undefined_value();
174 }
175
176
177 bool Object::ToInt32(int32_t* value) {
178   if (IsSmi()) {
179     *value = Smi::cast(this)->value();
180     return true;
181   }
182   if (IsHeapNumber()) {
183     double num = HeapNumber::cast(this)->value();
184     if (FastI2D(FastD2I(num)) == num) {
185       *value = FastD2I(num);
186       return true;
187     }
188   }
189   return false;
190 }
191
192
193 bool Object::ToUint32(uint32_t* value) {
194   if (IsSmi()) {
195     int num = Smi::cast(this)->value();
196     if (num >= 0) {
197       *value = static_cast<uint32_t>(num);
198       return true;
199     }
200   }
201   if (IsHeapNumber()) {
202     double num = HeapNumber::cast(this)->value();
203     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
204       *value = FastD2UI(num);
205       return true;
206     }
207   }
208   return false;
209 }
210
211
212 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
213   if (!object->IsHeapObject()) return false;
214   return IsTemplateFor(HeapObject::cast(object)->map());
215 }
216
217
218 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
219   // There is a constraint on the object; check.
220   if (!map->IsJSObjectMap()) return false;
221   // Fetch the constructor function of the object.
222   Object* cons_obj = map->constructor();
223   if (!cons_obj->IsJSFunction()) return false;
224   JSFunction* fun = JSFunction::cast(cons_obj);
225   // Iterate through the chain of inheriting function templates to
226   // see if the required one occurs.
227   for (Object* type = fun->shared()->function_data();
228        type->IsFunctionTemplateInfo();
229        type = FunctionTemplateInfo::cast(type)->parent_template()) {
230     if (type == this) return true;
231   }
232   // Didn't find the required type in the inheritance chain.
233   return false;
234 }
235
236
237 // TODO(dcarney): CallOptimization duplicates this logic, merge.
238 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
239                                                     Object* receiver) {
240   // API calls are only supported with JSObject receivers.
241   if (!receiver->IsJSObject()) return isolate->heap()->null_value();
242   Object* recv_type = this->signature();
243   // No signature, return holder.
244   if (recv_type->IsUndefined()) return receiver;
245   FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
246   // Check the receiver.
247   for (PrototypeIterator iter(isolate, receiver,
248                               PrototypeIterator::START_AT_RECEIVER);
249        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
250     if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
251   }
252   return isolate->heap()->null_value();
253 }
254
255
256 Handle<FixedArray> JSObject::EnsureWritableFastElements(
257     Handle<JSObject> object) {
258   DCHECK(object->HasFastSmiOrObjectElements());
259   Isolate* isolate = object->GetIsolate();
260   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
261   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
262   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
263       elems, isolate->factory()->fixed_array_map());
264   object->set_elements(*writable_elems);
265   isolate->counters()->cow_arrays_converted()->Increment();
266   return writable_elems;
267 }
268
269
270 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
271                                                     Handle<Object> receiver,
272                                                     Handle<Name> name) {
273   Isolate* isolate = proxy->GetIsolate();
274
275   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
276   if (name->IsSymbol()) return isolate->factory()->undefined_value();
277
278   Handle<Object> args[] = { receiver, name };
279   return CallTrap(
280       proxy, "get",  isolate->derived_get_trap(), arraysize(args), args);
281 }
282
283
284 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
285                                                     Handle<Name> name,
286                                                     Handle<JSObject> holder,
287                                                     Handle<Object> structure) {
288   Isolate* isolate = name->GetIsolate();
289   DCHECK(!structure->IsForeign());
290   // api style callbacks.
291   if (structure->IsAccessorInfo()) {
292     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
293     if (!info->IsCompatibleReceiver(*receiver)) {
294       Handle<Object> args[] = {name, receiver};
295       THROW_NEW_ERROR(isolate,
296                       NewTypeError("incompatible_method_receiver",
297                                    HandleVector(args, arraysize(args))),
298                       Object);
299     }
300
301     Handle<ExecutableAccessorInfo> data =
302         Handle<ExecutableAccessorInfo>::cast(structure);
303     v8::AccessorNameGetterCallback call_fun =
304         v8::ToCData<v8::AccessorNameGetterCallback>(data->getter());
305     if (call_fun == NULL) return isolate->factory()->undefined_value();
306
307     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
308     PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
309     v8::Handle<v8::Value> result =
310         args.Call(call_fun, v8::Utils::ToLocal(name));
311     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
312     if (result.IsEmpty()) {
313       return isolate->factory()->undefined_value();
314     }
315     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
316     return_value->VerifyApiCallResultType();
317     // Rebox handle before return.
318     return handle(*return_value, isolate);
319   }
320
321   // __defineGetter__ callback
322   Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
323                         isolate);
324   if (getter->IsSpecFunction()) {
325     // TODO(rossberg): nicer would be to cast to some JSCallable here...
326     return Object::GetPropertyWithDefinedGetter(
327         receiver, Handle<JSReceiver>::cast(getter));
328   }
329   // Getter is not a function.
330   return isolate->factory()->undefined_value();
331 }
332
333
334 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
335                                            Handle<AccessorInfo> info,
336                                            Handle<Map> map) {
337   if (!info->HasExpectedReceiverType()) return true;
338   if (!map->IsJSObjectMap()) return false;
339   return FunctionTemplateInfo::cast(info->expected_receiver_type())
340       ->IsTemplateFor(*map);
341 }
342
343
344 MaybeHandle<Object> Object::SetPropertyWithAccessor(
345     Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
346     Handle<JSObject> holder, Handle<Object> structure,
347     LanguageMode language_mode) {
348   Isolate* isolate = name->GetIsolate();
349
350   // We should never get here to initialize a const with the hole
351   // value since a const declaration would conflict with the setter.
352   DCHECK(!structure->IsForeign());
353   if (structure->IsExecutableAccessorInfo()) {
354     // Don't call executable accessor setters with non-JSObject receivers.
355     if (!receiver->IsJSObject()) return value;
356     // api style callbacks
357     ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
358     if (!info->IsCompatibleReceiver(*receiver)) {
359       Handle<Object> args[] = {name, receiver};
360       THROW_NEW_ERROR(isolate,
361                       NewTypeError("incompatible_method_receiver",
362                                    HandleVector(args, arraysize(args))),
363                       Object);
364     }
365     Object* call_obj = info->setter();
366     v8::AccessorNameSetterCallback call_fun =
367         v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
368     if (call_fun == NULL) return value;
369     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
370     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
371     args.Call(call_fun,
372               v8::Utils::ToLocal(name),
373               v8::Utils::ToLocal(value));
374     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
375     return value;
376   }
377
378   if (structure->IsAccessorPair()) {
379     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
380     if (setter->IsSpecFunction()) {
381       // TODO(rossberg): nicer would be to cast to some JSCallable here...
382       return SetPropertyWithDefinedSetter(
383           receiver, Handle<JSReceiver>::cast(setter), value);
384     } else {
385       if (is_sloppy(language_mode)) return value;
386       Handle<Object> args[] = {name, holder};
387       THROW_NEW_ERROR(isolate,
388                       NewTypeError("no_setter_in_callback",
389                                    HandleVector(args, arraysize(args))),
390                       Object);
391     }
392   }
393
394   UNREACHABLE();
395   return MaybeHandle<Object>();
396 }
397
398
399 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
400     Handle<Object> receiver,
401     Handle<JSReceiver> getter) {
402   Isolate* isolate = getter->GetIsolate();
403   Debug* debug = isolate->debug();
404   // Handle stepping into a getter if step into is active.
405   // TODO(rossberg): should this apply to getters that are function proxies?
406   if (debug->is_active()) {
407     debug->HandleStepIn(getter, Handle<Object>::null(), 0, false);
408   }
409
410   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
411 }
412
413
414 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
415     Handle<Object> receiver,
416     Handle<JSReceiver> setter,
417     Handle<Object> value) {
418   Isolate* isolate = setter->GetIsolate();
419
420   Debug* debug = isolate->debug();
421   // Handle stepping into a setter if step into is active.
422   // TODO(rossberg): should this apply to getters that are function proxies?
423   if (debug->is_active()) {
424     debug->HandleStepIn(setter, Handle<Object>::null(), 0, false);
425   }
426
427   Handle<Object> argv[] = { value };
428   RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
429                                                arraysize(argv), argv, true),
430                       Object);
431   return value;
432 }
433
434
435 static bool FindAllCanReadHolder(LookupIterator* it) {
436   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
437   // which have already been checked.
438   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
439          it->state() == LookupIterator::INTERCEPTOR);
440   for (it->Next(); it->IsFound(); it->Next()) {
441     if (it->state() == LookupIterator::ACCESSOR) {
442       auto accessors = it->GetAccessors();
443       if (accessors->IsAccessorInfo()) {
444         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
445       }
446     } else if (it->state() == LookupIterator::INTERCEPTOR) {
447       auto holder = it->GetHolder<JSObject>();
448       if (holder->GetNamedInterceptor()->all_can_read()) return true;
449     }
450   }
451   return false;
452 }
453
454
455 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
456     LookupIterator* it) {
457   Handle<JSObject> checked = it->GetHolder<JSObject>();
458   while (FindAllCanReadHolder(it)) {
459     if (it->state() == LookupIterator::ACCESSOR) {
460       return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
461                                      it->GetHolder<JSObject>(),
462                                      it->GetAccessors());
463     }
464     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
465     auto receiver = Handle<JSObject>::cast(it->GetReceiver());
466     auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
467                                              receiver, it->name());
468     if (it->isolate()->has_scheduled_exception()) break;
469     if (!result.is_null()) return result;
470   }
471   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
472   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
473   return it->factory()->undefined_value();
474 }
475
476
477 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
478     LookupIterator* it) {
479   Handle<JSObject> checked = it->GetHolder<JSObject>();
480   while (FindAllCanReadHolder(it)) {
481     if (it->state() == LookupIterator::ACCESSOR) {
482       return maybe(it->property_details().attributes());
483     }
484     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
485     auto result = GetPropertyAttributesWithInterceptor(
486         it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
487     if (it->isolate()->has_scheduled_exception()) break;
488     if (result.has_value && result.value != ABSENT) return result;
489   }
490   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
491   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
492                                       Maybe<PropertyAttributes>());
493   return maybe(ABSENT);
494 }
495
496
497 static bool FindAllCanWriteHolder(LookupIterator* it) {
498   for (; it->IsFound(); it->Next()) {
499     if (it->state() == LookupIterator::ACCESSOR) {
500       Handle<Object> accessors = it->GetAccessors();
501       if (accessors->IsAccessorInfo()) {
502         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
503       }
504     }
505   }
506   return false;
507 }
508
509
510 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
511     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
512   Handle<JSObject> checked = it->GetHolder<JSObject>();
513   if (FindAllCanWriteHolder(it)) {
514     return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
515                                    it->GetHolder<JSObject>(),
516                                    it->GetAccessors(), language_mode);
517   }
518
519   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
520   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
521   return value;
522 }
523
524
525 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
526                                      Handle<Name> name,
527                                      Handle<Object> value,
528                                      PropertyDetails details) {
529   DCHECK(!object->HasFastProperties());
530   Handle<NameDictionary> property_dictionary(object->property_dictionary());
531
532   if (!name->IsUniqueName()) {
533     name = object->GetIsolate()->factory()->InternalizeString(
534         Handle<String>::cast(name));
535   }
536
537   int entry = property_dictionary->FindEntry(name);
538   if (entry == NameDictionary::kNotFound) {
539     Handle<Object> store_value = value;
540     if (object->IsGlobalObject()) {
541       store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
542     }
543
544     property_dictionary = NameDictionary::Add(
545         property_dictionary, name, store_value, details);
546     object->set_properties(*property_dictionary);
547     return;
548   }
549
550   PropertyDetails original_details = property_dictionary->DetailsAt(entry);
551   int enumeration_index;
552   // Preserve the enumeration index unless the property was deleted.
553   if (original_details.IsDeleted()) {
554     enumeration_index = property_dictionary->NextEnumerationIndex();
555     property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
556   } else {
557     enumeration_index = original_details.dictionary_index();
558     DCHECK(enumeration_index > 0);
559   }
560
561   details = PropertyDetails(
562       details.attributes(), details.type(), enumeration_index);
563
564   if (object->IsGlobalObject()) {
565     Handle<PropertyCell> cell(
566         PropertyCell::cast(property_dictionary->ValueAt(entry)));
567     PropertyCell::SetValueInferType(cell, value);
568     // Please note we have to update the property details.
569     property_dictionary->DetailsAtPut(entry, details);
570   } else {
571     property_dictionary->SetEntry(entry, name, value, details);
572   }
573 }
574
575
576 static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
577     Isolate* isolate, Handle<JSObject> js_object,
578     PrototypeIterator::WhereToStart where_to_start) {
579   for (PrototypeIterator iter(isolate, js_object, where_to_start);
580        !iter.IsAtEnd(); iter.Advance()) {
581     auto curr = PrototypeIterator::GetCurrent(iter);
582     if (!curr->IsJSObject()) break;
583     auto obj = Handle<JSObject>::cast(curr);
584     if (!obj->HasIndexedInterceptor()) continue;
585     if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
586   }
587   return MaybeHandle<JSObject>();
588 }
589
590
591 MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
592     Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
593     uint32_t index) {
594   Handle<JSObject> holder = object;
595   PrototypeIterator::WhereToStart where_to_start =
596       PrototypeIterator::START_AT_RECEIVER;
597   while (true) {
598     auto all_can_read_holder =
599         FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
600     if (!all_can_read_holder.ToHandle(&holder)) break;
601     auto result =
602         JSObject::GetElementWithInterceptor(holder, receiver, index, false);
603     if (isolate->has_scheduled_exception()) break;
604     if (!result.is_null()) return result;
605     where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
606   }
607   isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
608   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
609   return isolate->factory()->undefined_value();
610 }
611
612
613 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
614     Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
615     uint32_t index) {
616   Handle<JSObject> holder = object;
617   PrototypeIterator::WhereToStart where_to_start =
618       PrototypeIterator::START_AT_RECEIVER;
619   while (true) {
620     auto all_can_read_holder =
621         FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
622     if (!all_can_read_holder.ToHandle(&holder)) break;
623     auto result =
624         JSObject::GetElementAttributeFromInterceptor(object, receiver, index);
625     if (isolate->has_scheduled_exception()) break;
626     if (result.has_value && result.value != ABSENT) return result;
627     where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
628   }
629   isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
630   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
631   return maybe(ABSENT);
632 }
633
634
635 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
636                                                    Handle<Object> object,
637                                                    Handle<Object> receiver,
638                                                    uint32_t index) {
639   if (object->IsUndefined()) {
640     // TODO(verwaest): Why is this check here?
641     UNREACHABLE();
642     return isolate->factory()->undefined_value();
643   }
644
645   // Iterate up the prototype chain until an element is found or the null
646   // prototype is encountered.
647   for (PrototypeIterator iter(isolate, object,
648                               object->IsJSProxy() || object->IsJSObject()
649                                   ? PrototypeIterator::START_AT_RECEIVER
650                                   : PrototypeIterator::START_AT_PROTOTYPE);
651        !iter.IsAtEnd(); iter.Advance()) {
652     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
653       return JSProxy::GetElementWithHandler(
654           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
655           index);
656     }
657
658     // Inline the case for JSObjects. Doing so significantly improves the
659     // performance of fetching elements where checking the prototype chain is
660     // necessary.
661     Handle<JSObject> js_object =
662         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
663
664     // Check access rights if needed.
665     if (js_object->IsAccessCheckNeeded()) {
666       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
667         return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
668                                                          receiver, index);
669       }
670     }
671
672     if (js_object->HasIndexedInterceptor()) {
673       return JSObject::GetElementWithInterceptor(js_object, receiver, index,
674                                                  true);
675     }
676
677     if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
678       Handle<Object> result;
679       ASSIGN_RETURN_ON_EXCEPTION(
680           isolate, result,
681           js_object->GetElementsAccessor()->Get(receiver, js_object, index),
682           Object);
683       if (!result->IsTheHole()) return result;
684     }
685   }
686
687   return isolate->factory()->undefined_value();
688 }
689
690
691 MaybeHandle<Object> Object::SetElementWithReceiver(
692     Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
693     uint32_t index, Handle<Object> value, LanguageMode language_mode) {
694   // Iterate up the prototype chain until an element is found or the null
695   // prototype is encountered.
696   bool done = false;
697   for (PrototypeIterator iter(isolate, object,
698                               object->IsJSProxy() || object->IsJSObject()
699                                   ? PrototypeIterator::START_AT_RECEIVER
700                                   : PrototypeIterator::START_AT_PROTOTYPE);
701        !iter.IsAtEnd() && !done; iter.Advance()) {
702     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
703       // TODO(dslomov): implement.
704       isolate->ThrowIllegalOperation();
705       return MaybeHandle<Object>();
706     }
707
708     Handle<JSObject> js_object =
709         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
710
711     // Check access rights if needed.
712     if (js_object->IsAccessCheckNeeded()) {
713       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_SET)) {
714         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_SET);
715         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
716         return isolate->factory()->undefined_value();
717       }
718     }
719
720     if (js_object->HasIndexedInterceptor()) {
721       Maybe<PropertyAttributes> from_interceptor =
722           JSObject::GetElementAttributeFromInterceptor(js_object, receiver,
723                                                        index);
724       if (!from_interceptor.has_value) return MaybeHandle<Object>();
725       if ((from_interceptor.value & READ_ONLY) != 0) {
726         return WriteToReadOnlyElement(isolate, receiver, index, value,
727                                       language_mode);
728       }
729       done = from_interceptor.value != ABSENT;
730     }
731
732     if (!done &&
733         js_object->elements() != isolate->heap()->empty_fixed_array()) {
734       ElementsAccessor* accessor = js_object->GetElementsAccessor();
735       PropertyAttributes attrs = accessor->GetAttributes(js_object, index);
736       if ((attrs & READ_ONLY) != 0) {
737         return WriteToReadOnlyElement(isolate, receiver, index, value,
738                                       language_mode);
739       }
740       Handle<AccessorPair> pair;
741       if (accessor->GetAccessorPair(js_object, index).ToHandle(&pair)) {
742         return JSObject::SetElementWithCallback(receiver, pair, index, value,
743                                                 js_object, language_mode);
744       } else {
745         done = attrs != ABSENT;
746       }
747     }
748   }
749
750   if (!receiver->IsJSObject()) {
751     return WriteToReadOnlyElement(isolate, receiver, index, value,
752                                   language_mode);
753   }
754   Handle<JSObject> target = Handle<JSObject>::cast(receiver);
755   ElementsAccessor* accessor = target->GetElementsAccessor();
756   PropertyAttributes attrs = accessor->GetAttributes(target, index);
757   if (attrs == ABSENT) {
758     return JSObject::SetElement(target, index, value, NONE, language_mode,
759                                 false);
760   }
761   return JSObject::SetElement(target, index, value, attrs, language_mode, false,
762                               DEFINE_PROPERTY);
763 }
764
765
766 Map* Object::GetRootMap(Isolate* isolate) {
767   DisallowHeapAllocation no_alloc;
768   if (IsSmi()) {
769     Context* context = isolate->context()->native_context();
770     return context->number_function()->initial_map();
771   }
772
773   HeapObject* heap_object = HeapObject::cast(this);
774
775   // The object is either a number, a string, a boolean,
776   // a real JS object, or a Harmony proxy.
777   if (heap_object->IsJSReceiver()) {
778     return heap_object->map();
779   }
780   Context* context = isolate->context()->native_context();
781
782   if (heap_object->IsHeapNumber()) {
783     return context->number_function()->initial_map();
784   }
785   if (heap_object->IsString()) {
786     return context->string_function()->initial_map();
787   }
788   if (heap_object->IsSymbol()) {
789     return context->symbol_function()->initial_map();
790   }
791   if (heap_object->IsBoolean()) {
792     return context->boolean_function()->initial_map();
793   }
794   return isolate->heap()->null_value()->map();
795 }
796
797
798 Object* Object::GetHash() {
799   // The object is either a number, a name, an odd-ball,
800   // a real JS object, or a Harmony proxy.
801   if (IsNumber()) {
802     uint32_t hash = std::isnan(Number())
803                         ? Smi::kMaxValue
804                         : ComputeLongHash(double_to_uint64(Number()));
805     return Smi::FromInt(hash & Smi::kMaxValue);
806   }
807   if (IsName()) {
808     uint32_t hash = Name::cast(this)->Hash();
809     return Smi::FromInt(hash);
810   }
811   if (IsOddball()) {
812     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
813     return Smi::FromInt(hash);
814   }
815
816   DCHECK(IsJSReceiver());
817   return JSReceiver::cast(this)->GetIdentityHash();
818 }
819
820
821 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
822   Handle<Object> hash(object->GetHash(), isolate);
823   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
824
825   DCHECK(object->IsJSReceiver());
826   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
827 }
828
829
830 bool Object::SameValue(Object* other) {
831   if (other == this) return true;
832
833   // The object is either a number, a name, an odd-ball,
834   // a real JS object, or a Harmony proxy.
835   if (IsNumber() && other->IsNumber()) {
836     double this_value = Number();
837     double other_value = other->Number();
838     bool equal = this_value == other_value;
839     // SameValue(NaN, NaN) is true.
840     if (!equal) return std::isnan(this_value) && std::isnan(other_value);
841     // SameValue(0.0, -0.0) is false.
842     return (this_value != 0) || ((1 / this_value) == (1 / other_value));
843   }
844   if (IsString() && other->IsString()) {
845     return String::cast(this)->Equals(String::cast(other));
846   }
847   return false;
848 }
849
850
851 bool Object::SameValueZero(Object* other) {
852   if (other == this) return true;
853
854   // The object is either a number, a name, an odd-ball,
855   // a real JS object, or a Harmony proxy.
856   if (IsNumber() && other->IsNumber()) {
857     double this_value = Number();
858     double other_value = other->Number();
859     // +0 == -0 is true
860     return this_value == other_value
861         || (std::isnan(this_value) && std::isnan(other_value));
862   }
863   if (IsString() && other->IsString()) {
864     return String::cast(this)->Equals(String::cast(other));
865   }
866   return false;
867 }
868
869
870 void Object::ShortPrint(FILE* out) {
871   OFStream os(out);
872   os << Brief(this);
873 }
874
875
876 void Object::ShortPrint(StringStream* accumulator) {
877   std::ostringstream os;
878   os << Brief(this);
879   accumulator->Add(os.str().c_str());
880 }
881
882
883 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
884
885
886 std::ostream& operator<<(std::ostream& os, const Brief& v) {
887   if (v.value->IsSmi()) {
888     Smi::cast(v.value)->SmiPrint(os);
889   } else {
890     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
891     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
892     obj->HeapObjectShortPrint(os);
893   }
894   return os;
895 }
896
897
898 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
899   os << value();
900 }
901
902
903 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
904 // English?  Returns false for non-ASCII or words that don't start with
905 // a capital letter.  The a/an rule follows pronunciation in English.
906 // We don't use the BBC's overcorrect "an historic occasion" though if
907 // you speak a dialect you may well say "an 'istoric occasion".
908 static bool AnWord(String* str) {
909   if (str->length() == 0) return false;  // A nothing.
910   int c0 = str->Get(0);
911   int c1 = str->length() > 1 ? str->Get(1) : 0;
912   if (c0 == 'U') {
913     if (c1 > 'Z') {
914       return true;  // An Umpire, but a UTF8String, a U.
915     }
916   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
917     return true;    // An Ape, an ABCBook.
918   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
919            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
920             c0 == 'S' || c0 == 'X')) {
921     return true;    // An MP3File, an M.
922   }
923   return false;
924 }
925
926
927 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
928                                    PretenureFlag pretenure) {
929   DCHECK(AllowHeapAllocation::IsAllowed());
930   DCHECK(cons->second()->length() != 0);
931   Isolate* isolate = cons->GetIsolate();
932   int length = cons->length();
933   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
934                                                             : TENURED;
935   Handle<SeqString> result;
936   if (cons->IsOneByteRepresentation()) {
937     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
938         length, tenure).ToHandleChecked();
939     DisallowHeapAllocation no_gc;
940     WriteToFlat(*cons, flat->GetChars(), 0, length);
941     result = flat;
942   } else {
943     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
944         length, tenure).ToHandleChecked();
945     DisallowHeapAllocation no_gc;
946     WriteToFlat(*cons, flat->GetChars(), 0, length);
947     result = flat;
948   }
949   cons->set_first(*result);
950   cons->set_second(isolate->heap()->empty_string());
951   DCHECK(result->IsFlat());
952   return result;
953 }
954
955
956
957 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
958   // Externalizing twice leaks the external resource, so it's
959   // prohibited by the API.
960   DCHECK(!this->IsExternalString());
961 #ifdef ENABLE_SLOW_DCHECKS
962   if (FLAG_enable_slow_asserts) {
963     // Assert that the resource and the string are equivalent.
964     DCHECK(static_cast<size_t>(this->length()) == resource->length());
965     ScopedVector<uc16> smart_chars(this->length());
966     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
967     DCHECK(memcmp(smart_chars.start(),
968                   resource->data(),
969                   resource->length() * sizeof(smart_chars[0])) == 0);
970   }
971 #endif  // DEBUG
972   int size = this->Size();  // Byte size of the original string.
973   // Abort if size does not allow in-place conversion.
974   if (size < ExternalString::kShortSize) return false;
975   Heap* heap = GetHeap();
976   bool is_one_byte = this->IsOneByteRepresentation();
977   bool is_internalized = this->IsInternalizedString();
978
979   // Morph the string to an external string by replacing the map and
980   // reinitializing the fields.  This won't work if the space the existing
981   // string occupies is too small for a regular  external string.
982   // Instead, we resort to a short external string instead, omitting
983   // the field caching the address of the backing store.  When we encounter
984   // short external strings in generated code, we need to bailout to runtime.
985   Map* new_map;
986   if (size < ExternalString::kSize) {
987     new_map = is_internalized
988         ? (is_one_byte
989            ? heap->short_external_internalized_string_with_one_byte_data_map()
990            : heap->short_external_internalized_string_map())
991         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
992                        : heap->short_external_string_map());
993   } else {
994     new_map = is_internalized
995         ? (is_one_byte
996            ? heap->external_internalized_string_with_one_byte_data_map()
997            : heap->external_internalized_string_map())
998         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
999                        : heap->external_string_map());
1000   }
1001
1002   // Byte size of the external String object.
1003   int new_size = this->SizeFromMap(new_map);
1004   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1005
1006   // We are storing the new map using release store after creating a filler for
1007   // the left-over space to avoid races with the sweeper thread.
1008   this->synchronized_set_map(new_map);
1009
1010   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1011   self->set_resource(resource);
1012   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1013
1014   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1015   return true;
1016 }
1017
1018
1019 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
1020   // Externalizing twice leaks the external resource, so it's
1021   // prohibited by the API.
1022   DCHECK(!this->IsExternalString());
1023 #ifdef ENABLE_SLOW_DCHECKS
1024   if (FLAG_enable_slow_asserts) {
1025     // Assert that the resource and the string are equivalent.
1026     DCHECK(static_cast<size_t>(this->length()) == resource->length());
1027     if (this->IsTwoByteRepresentation()) {
1028       ScopedVector<uint16_t> smart_chars(this->length());
1029       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1030       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
1031     }
1032     ScopedVector<char> smart_chars(this->length());
1033     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1034     DCHECK(memcmp(smart_chars.start(),
1035                   resource->data(),
1036                   resource->length() * sizeof(smart_chars[0])) == 0);
1037   }
1038 #endif  // DEBUG
1039   int size = this->Size();  // Byte size of the original string.
1040   // Abort if size does not allow in-place conversion.
1041   if (size < ExternalString::kShortSize) return false;
1042   Heap* heap = GetHeap();
1043   bool is_internalized = this->IsInternalizedString();
1044
1045   // Morph the string to an external string by replacing the map and
1046   // reinitializing the fields.  This won't work if the space the existing
1047   // string occupies is too small for a regular  external string.
1048   // Instead, we resort to a short external string instead, omitting
1049   // the field caching the address of the backing store.  When we encounter
1050   // short external strings in generated code, we need to bailout to runtime.
1051   Map* new_map;
1052   if (size < ExternalString::kSize) {
1053     new_map = is_internalized
1054                   ? heap->short_external_one_byte_internalized_string_map()
1055                   : heap->short_external_one_byte_string_map();
1056   } else {
1057     new_map = is_internalized
1058                   ? heap->external_one_byte_internalized_string_map()
1059                   : heap->external_one_byte_string_map();
1060   }
1061
1062   // Byte size of the external String object.
1063   int new_size = this->SizeFromMap(new_map);
1064   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1065
1066   // We are storing the new map using release store after creating a filler for
1067   // the left-over space to avoid races with the sweeper thread.
1068   this->synchronized_set_map(new_map);
1069
1070   ExternalOneByteString* self = ExternalOneByteString::cast(this);
1071   self->set_resource(resource);
1072   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1073
1074   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1075   return true;
1076 }
1077
1078
1079 void String::StringShortPrint(StringStream* accumulator) {
1080   int len = length();
1081   if (len > kMaxShortPrintLength) {
1082     accumulator->Add("<Very long string[%u]>", len);
1083     return;
1084   }
1085
1086   if (!LooksValid()) {
1087     accumulator->Add("<Invalid String>");
1088     return;
1089   }
1090
1091   StringCharacterStream stream(this);
1092
1093   bool truncated = false;
1094   if (len > kMaxShortPrintLength) {
1095     len = kMaxShortPrintLength;
1096     truncated = true;
1097   }
1098   bool one_byte = true;
1099   for (int i = 0; i < len; i++) {
1100     uint16_t c = stream.GetNext();
1101
1102     if (c < 32 || c >= 127) {
1103       one_byte = false;
1104     }
1105   }
1106   stream.Reset(this);
1107   if (one_byte) {
1108     accumulator->Add("<String[%u]: ", length());
1109     for (int i = 0; i < len; i++) {
1110       accumulator->Put(static_cast<char>(stream.GetNext()));
1111     }
1112     accumulator->Put('>');
1113   } else {
1114     // Backslash indicates that the string contains control
1115     // characters and that backslashes are therefore escaped.
1116     accumulator->Add("<String[%u]\\: ", length());
1117     for (int i = 0; i < len; i++) {
1118       uint16_t c = stream.GetNext();
1119       if (c == '\n') {
1120         accumulator->Add("\\n");
1121       } else if (c == '\r') {
1122         accumulator->Add("\\r");
1123       } else if (c == '\\') {
1124         accumulator->Add("\\\\");
1125       } else if (c < 32 || c > 126) {
1126         accumulator->Add("\\x%02x", c);
1127       } else {
1128         accumulator->Put(static_cast<char>(c));
1129       }
1130     }
1131     if (truncated) {
1132       accumulator->Put('.');
1133       accumulator->Put('.');
1134       accumulator->Put('.');
1135     }
1136     accumulator->Put('>');
1137   }
1138   return;
1139 }
1140
1141
1142 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
1143   if (end < 0) end = length();
1144   StringCharacterStream stream(this, start);
1145   for (int i = start; i < end && stream.HasMore(); i++) {
1146     os << AsUC16(stream.GetNext());
1147   }
1148 }
1149
1150
1151 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1152   switch (map()->instance_type()) {
1153     case JS_ARRAY_TYPE: {
1154       double length = JSArray::cast(this)->length()->IsUndefined()
1155           ? 0
1156           : JSArray::cast(this)->length()->Number();
1157       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1158       break;
1159     }
1160     case JS_WEAK_MAP_TYPE: {
1161       accumulator->Add("<JS WeakMap>");
1162       break;
1163     }
1164     case JS_WEAK_SET_TYPE: {
1165       accumulator->Add("<JS WeakSet>");
1166       break;
1167     }
1168     case JS_REGEXP_TYPE: {
1169       accumulator->Add("<JS RegExp>");
1170       break;
1171     }
1172     case JS_FUNCTION_TYPE: {
1173       JSFunction* function = JSFunction::cast(this);
1174       Object* fun_name = function->shared()->DebugName();
1175       bool printed = false;
1176       if (fun_name->IsString()) {
1177         String* str = String::cast(fun_name);
1178         if (str->length() > 0) {
1179           accumulator->Add("<JS Function ");
1180           accumulator->Put(str);
1181           printed = true;
1182         }
1183       }
1184       if (!printed) {
1185         accumulator->Add("<JS Function");
1186       }
1187       accumulator->Add(" (SharedFunctionInfo %p)",
1188                        reinterpret_cast<void*>(function->shared()));
1189       accumulator->Put('>');
1190       break;
1191     }
1192     case JS_GENERATOR_OBJECT_TYPE: {
1193       accumulator->Add("<JS Generator>");
1194       break;
1195     }
1196     case JS_MODULE_TYPE: {
1197       accumulator->Add("<JS Module>");
1198       break;
1199     }
1200     // All other JSObjects are rather similar to each other (JSObject,
1201     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1202     default: {
1203       Map* map_of_this = map();
1204       Heap* heap = GetHeap();
1205       Object* constructor = map_of_this->constructor();
1206       bool printed = false;
1207       if (constructor->IsHeapObject() &&
1208           !heap->Contains(HeapObject::cast(constructor))) {
1209         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1210       } else {
1211         bool global_object = IsJSGlobalProxy();
1212         if (constructor->IsJSFunction()) {
1213           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1214             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1215           } else {
1216             Object* constructor_name =
1217                 JSFunction::cast(constructor)->shared()->name();
1218             if (constructor_name->IsString()) {
1219               String* str = String::cast(constructor_name);
1220               if (str->length() > 0) {
1221                 bool vowel = AnWord(str);
1222                 accumulator->Add("<%sa%s ",
1223                        global_object ? "Global Object: " : "",
1224                        vowel ? "n" : "");
1225                 accumulator->Put(str);
1226                 accumulator->Add(" with %smap %p",
1227                     map_of_this->is_deprecated() ? "deprecated " : "",
1228                     map_of_this);
1229                 printed = true;
1230               }
1231             }
1232           }
1233         }
1234         if (!printed) {
1235           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1236         }
1237       }
1238       if (IsJSValue()) {
1239         accumulator->Add(" value = ");
1240         JSValue::cast(this)->value()->ShortPrint(accumulator);
1241       }
1242       accumulator->Put('>');
1243       break;
1244     }
1245   }
1246 }
1247
1248
1249 void JSObject::PrintElementsTransition(
1250     FILE* file, Handle<JSObject> object,
1251     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1252     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1253   if (from_kind != to_kind) {
1254     OFStream os(file);
1255     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1256        << ElementsKindToString(to_kind) << "] in ";
1257     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1258     PrintF(file, " for ");
1259     object->ShortPrint(file);
1260     PrintF(file, " from ");
1261     from_elements->ShortPrint(file);
1262     PrintF(file, " to ");
1263     to_elements->ShortPrint(file);
1264     PrintF(file, "\n");
1265   }
1266 }
1267
1268
1269 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
1270                                PropertyAttributes attributes) {
1271   OFStream os(file);
1272   os << "[reconfiguring ";
1273   constructor_name()->PrintOn(file);
1274   os << "] ";
1275   Name* name = instance_descriptors()->GetKey(modify_index);
1276   if (name->IsString()) {
1277     String::cast(name)->PrintOn(file);
1278   } else {
1279     os << "{symbol " << static_cast<void*>(name) << "}";
1280   }
1281   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
1282   os << attributes << " [";
1283   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1284   os << "]\n";
1285 }
1286
1287
1288 void Map::PrintGeneralization(FILE* file,
1289                               const char* reason,
1290                               int modify_index,
1291                               int split,
1292                               int descriptors,
1293                               bool constant_to_field,
1294                               Representation old_representation,
1295                               Representation new_representation,
1296                               HeapType* old_field_type,
1297                               HeapType* new_field_type) {
1298   OFStream os(file);
1299   os << "[generalizing ";
1300   constructor_name()->PrintOn(file);
1301   os << "] ";
1302   Name* name = instance_descriptors()->GetKey(modify_index);
1303   if (name->IsString()) {
1304     String::cast(name)->PrintOn(file);
1305   } else {
1306     os << "{symbol " << static_cast<void*>(name) << "}";
1307   }
1308   os << ":";
1309   if (constant_to_field) {
1310     os << "c";
1311   } else {
1312     os << old_representation.Mnemonic() << "{";
1313     old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1314     os << "}";
1315   }
1316   os << "->" << new_representation.Mnemonic() << "{";
1317   new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1318   os << "} (";
1319   if (strlen(reason) > 0) {
1320     os << reason;
1321   } else {
1322     os << "+" << (descriptors - split) << " maps";
1323   }
1324   os << ") [";
1325   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1326   os << "]\n";
1327 }
1328
1329
1330 void JSObject::PrintInstanceMigration(FILE* file,
1331                                       Map* original_map,
1332                                       Map* new_map) {
1333   PrintF(file, "[migrating ");
1334   map()->constructor_name()->PrintOn(file);
1335   PrintF(file, "] ");
1336   DescriptorArray* o = original_map->instance_descriptors();
1337   DescriptorArray* n = new_map->instance_descriptors();
1338   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1339     Representation o_r = o->GetDetails(i).representation();
1340     Representation n_r = n->GetDetails(i).representation();
1341     if (!o_r.Equals(n_r)) {
1342       String::cast(o->GetKey(i))->PrintOn(file);
1343       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1344     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
1345                n->GetDetails(i).type() == DATA) {
1346       Name* name = o->GetKey(i);
1347       if (name->IsString()) {
1348         String::cast(name)->PrintOn(file);
1349       } else {
1350         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1351       }
1352       PrintF(file, " ");
1353     }
1354   }
1355   PrintF(file, "\n");
1356 }
1357
1358
1359 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
1360   Heap* heap = GetHeap();
1361   if (!heap->Contains(this)) {
1362     os << "!!!INVALID POINTER!!!";
1363     return;
1364   }
1365   if (!heap->Contains(map())) {
1366     os << "!!!INVALID MAP!!!";
1367     return;
1368   }
1369
1370   os << this << " ";
1371
1372   if (IsString()) {
1373     HeapStringAllocator allocator;
1374     StringStream accumulator(&allocator);
1375     String::cast(this)->StringShortPrint(&accumulator);
1376     os << accumulator.ToCString().get();
1377     return;
1378   }
1379   if (IsJSObject()) {
1380     HeapStringAllocator allocator;
1381     StringStream accumulator(&allocator);
1382     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1383     os << accumulator.ToCString().get();
1384     return;
1385   }
1386   switch (map()->instance_type()) {
1387     case MAP_TYPE:
1388       os << "<Map(elements=" << Map::cast(this)->elements_kind() << ")>";
1389       break;
1390     case FIXED_ARRAY_TYPE:
1391       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1392       break;
1393     case FIXED_DOUBLE_ARRAY_TYPE:
1394       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1395          << "]>";
1396       break;
1397     case BYTE_ARRAY_TYPE:
1398       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1399       break;
1400     case FREE_SPACE_TYPE:
1401       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1402       break;
1403 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1404   case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1405     os << "<External" #Type "Array["                                          \
1406        << External##Type##Array::cast(this)->length() << "]>";                \
1407     break;                                                                    \
1408   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1409     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1410        << "]>";                                                               \
1411     break;
1412
1413     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1414 #undef TYPED_ARRAY_SHORT_PRINT
1415
1416     case SHARED_FUNCTION_INFO_TYPE: {
1417       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1418       SmartArrayPointer<char> debug_name =
1419           shared->DebugName()->ToCString();
1420       if (debug_name[0] != 0) {
1421         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1422       } else {
1423         os << "<SharedFunctionInfo>";
1424       }
1425       break;
1426     }
1427     case JS_MESSAGE_OBJECT_TYPE:
1428       os << "<JSMessageObject>";
1429       break;
1430 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1431   case NAME##_TYPE:                        \
1432     os << "<" #Name ">";                   \
1433     break;
1434   STRUCT_LIST(MAKE_STRUCT_CASE)
1435 #undef MAKE_STRUCT_CASE
1436     case CODE_TYPE: {
1437       Code* code = Code::cast(this);
1438       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1439       break;
1440     }
1441     case ODDBALL_TYPE: {
1442       if (IsUndefined()) {
1443         os << "<undefined>";
1444       } else if (IsTheHole()) {
1445         os << "<the hole>";
1446       } else if (IsNull()) {
1447         os << "<null>";
1448       } else if (IsTrue()) {
1449         os << "<true>";
1450       } else if (IsFalse()) {
1451         os << "<false>";
1452       } else {
1453         os << "<Odd Oddball>";
1454       }
1455       break;
1456     }
1457     case SYMBOL_TYPE: {
1458       Symbol* symbol = Symbol::cast(this);
1459       symbol->SymbolShortPrint(os);
1460       break;
1461     }
1462     case HEAP_NUMBER_TYPE: {
1463       os << "<Number: ";
1464       HeapNumber::cast(this)->HeapNumberPrint(os);
1465       os << ">";
1466       break;
1467     }
1468     case MUTABLE_HEAP_NUMBER_TYPE: {
1469       os << "<MutableNumber: ";
1470       HeapNumber::cast(this)->HeapNumberPrint(os);
1471       os << '>';
1472       break;
1473     }
1474     case JS_PROXY_TYPE:
1475       os << "<JSProxy>";
1476       break;
1477     case JS_FUNCTION_PROXY_TYPE:
1478       os << "<JSFunctionProxy>";
1479       break;
1480     case FOREIGN_TYPE:
1481       os << "<Foreign>";
1482       break;
1483     case CELL_TYPE: {
1484       os << "Cell for ";
1485       HeapStringAllocator allocator;
1486       StringStream accumulator(&allocator);
1487       Cell::cast(this)->value()->ShortPrint(&accumulator);
1488       os << accumulator.ToCString().get();
1489       break;
1490     }
1491     case PROPERTY_CELL_TYPE: {
1492       os << "PropertyCell for ";
1493       HeapStringAllocator allocator;
1494       StringStream accumulator(&allocator);
1495       PropertyCell::cast(this)->value()->ShortPrint(&accumulator);
1496       os << accumulator.ToCString().get();
1497       break;
1498     }
1499     case WEAK_CELL_TYPE: {
1500       os << "WeakCell for ";
1501       HeapStringAllocator allocator;
1502       StringStream accumulator(&allocator);
1503       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
1504       os << accumulator.ToCString().get();
1505       break;
1506     }
1507     default:
1508       os << "<Other heap object (" << map()->instance_type() << ")>";
1509       break;
1510   }
1511 }
1512
1513
1514 void HeapObject::Iterate(ObjectVisitor* v) {
1515   // Handle header
1516   IteratePointer(v, kMapOffset);
1517   // Handle object body
1518   Map* m = map();
1519   IterateBody(m->instance_type(), SizeFromMap(m), v);
1520 }
1521
1522
1523 void HeapObject::IterateBody(InstanceType type, int object_size,
1524                              ObjectVisitor* v) {
1525   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1526   // During GC, the map pointer field is encoded.
1527   if (type < FIRST_NONSTRING_TYPE) {
1528     switch (type & kStringRepresentationMask) {
1529       case kSeqStringTag:
1530         break;
1531       case kConsStringTag:
1532         ConsString::BodyDescriptor::IterateBody(this, v);
1533         break;
1534       case kSlicedStringTag:
1535         SlicedString::BodyDescriptor::IterateBody(this, v);
1536         break;
1537       case kExternalStringTag:
1538         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1539           reinterpret_cast<ExternalOneByteString*>(this)
1540               ->ExternalOneByteStringIterateBody(v);
1541         } else {
1542           reinterpret_cast<ExternalTwoByteString*>(this)->
1543               ExternalTwoByteStringIterateBody(v);
1544         }
1545         break;
1546     }
1547     return;
1548   }
1549
1550   switch (type) {
1551     case FIXED_ARRAY_TYPE:
1552       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1553       break;
1554     case CONSTANT_POOL_ARRAY_TYPE:
1555       reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1556       break;
1557     case FIXED_DOUBLE_ARRAY_TYPE:
1558       break;
1559     case JS_OBJECT_TYPE:
1560     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1561     case JS_GENERATOR_OBJECT_TYPE:
1562     case JS_MODULE_TYPE:
1563     case JS_VALUE_TYPE:
1564     case JS_DATE_TYPE:
1565     case JS_ARRAY_TYPE:
1566     case JS_ARRAY_BUFFER_TYPE:
1567     case JS_TYPED_ARRAY_TYPE:
1568     case JS_DATA_VIEW_TYPE:
1569     case JS_SET_TYPE:
1570     case JS_MAP_TYPE:
1571     case JS_SET_ITERATOR_TYPE:
1572     case JS_MAP_ITERATOR_TYPE:
1573     case JS_WEAK_MAP_TYPE:
1574     case JS_WEAK_SET_TYPE:
1575     case JS_REGEXP_TYPE:
1576     case JS_GLOBAL_PROXY_TYPE:
1577     case JS_GLOBAL_OBJECT_TYPE:
1578     case JS_BUILTINS_OBJECT_TYPE:
1579     case JS_MESSAGE_OBJECT_TYPE:
1580       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1581       break;
1582     case JS_FUNCTION_TYPE:
1583       reinterpret_cast<JSFunction*>(this)
1584           ->JSFunctionIterateBody(object_size, v);
1585       break;
1586     case ODDBALL_TYPE:
1587       Oddball::BodyDescriptor::IterateBody(this, v);
1588       break;
1589     case JS_PROXY_TYPE:
1590       JSProxy::BodyDescriptor::IterateBody(this, v);
1591       break;
1592     case JS_FUNCTION_PROXY_TYPE:
1593       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1594       break;
1595     case FOREIGN_TYPE:
1596       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1597       break;
1598     case MAP_TYPE:
1599       Map::BodyDescriptor::IterateBody(this, v);
1600       break;
1601     case CODE_TYPE:
1602       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1603       break;
1604     case CELL_TYPE:
1605       Cell::BodyDescriptor::IterateBody(this, v);
1606       break;
1607     case PROPERTY_CELL_TYPE:
1608       PropertyCell::BodyDescriptor::IterateBody(this, v);
1609       break;
1610     case WEAK_CELL_TYPE:
1611       WeakCell::BodyDescriptor::IterateBody(this, v);
1612       break;
1613     case SYMBOL_TYPE:
1614       Symbol::BodyDescriptor::IterateBody(this, v);
1615       break;
1616
1617     case HEAP_NUMBER_TYPE:
1618     case MUTABLE_HEAP_NUMBER_TYPE:
1619     case FILLER_TYPE:
1620     case BYTE_ARRAY_TYPE:
1621     case FREE_SPACE_TYPE:
1622       break;
1623
1624 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1625     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1626     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1627       break;
1628
1629     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1630 #undef TYPED_ARRAY_CASE
1631
1632     case SHARED_FUNCTION_INFO_TYPE: {
1633       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1634       break;
1635     }
1636
1637 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1638         case NAME##_TYPE:
1639       STRUCT_LIST(MAKE_STRUCT_CASE)
1640 #undef MAKE_STRUCT_CASE
1641       if (type == ALLOCATION_SITE_TYPE) {
1642         AllocationSite::BodyDescriptor::IterateBody(this, v);
1643       } else {
1644         StructBodyDescriptor::IterateBody(this, object_size, v);
1645       }
1646       break;
1647     default:
1648       PrintF("Unknown type: %d\n", type);
1649       UNREACHABLE();
1650   }
1651 }
1652
1653
1654 bool HeapNumber::HeapNumberBooleanValue() {
1655   return DoubleToBoolean(value());
1656 }
1657
1658
1659 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
1660   os << value();
1661 }
1662
1663
1664 String* JSReceiver::class_name() {
1665   if (IsJSFunction() || IsJSFunctionProxy()) {
1666     return GetHeap()->Function_string();
1667   }
1668   if (map()->constructor()->IsJSFunction()) {
1669     JSFunction* constructor = JSFunction::cast(map()->constructor());
1670     return String::cast(constructor->shared()->instance_class_name());
1671   }
1672   // If the constructor is not present, return "Object".
1673   return GetHeap()->Object_string();
1674 }
1675
1676
1677 String* Map::constructor_name() {
1678   if (constructor()->IsJSFunction()) {
1679     JSFunction* constructor = JSFunction::cast(this->constructor());
1680     String* name = String::cast(constructor->shared()->name());
1681     if (name->length() > 0) return name;
1682     String* inferred_name = constructor->shared()->inferred_name();
1683     if (inferred_name->length() > 0) return inferred_name;
1684     Object* proto = prototype();
1685     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1686   }
1687   // TODO(rossberg): what about proxies?
1688   // If the constructor is not present, return "Object".
1689   return GetHeap()->Object_string();
1690 }
1691
1692
1693 String* JSReceiver::constructor_name() {
1694   return map()->constructor_name();
1695 }
1696
1697
1698 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1699                                     Handle<Name> name,
1700                                     Handle<HeapType> type,
1701                                     PropertyAttributes attributes,
1702                                     Representation representation,
1703                                     TransitionFlag flag) {
1704   DCHECK(DescriptorArray::kNotFound ==
1705          map->instance_descriptors()->Search(
1706              *name, map->NumberOfOwnDescriptors()));
1707
1708   // Ensure the descriptor array does not get too big.
1709   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1710     return MaybeHandle<Map>();
1711   }
1712
1713   Isolate* isolate = map->GetIsolate();
1714
1715   // Compute the new index for new field.
1716   int index = map->NextFreePropertyIndex();
1717
1718   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1719     representation = Representation::Tagged();
1720     type = HeapType::Any(isolate);
1721   }
1722
1723   DataDescriptor new_field_desc(name, index, type, attributes, representation);
1724   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1725   int unused_property_fields = new_map->unused_property_fields() - 1;
1726   if (unused_property_fields < 0) {
1727     unused_property_fields += JSObject::kFieldsAdded;
1728   }
1729   new_map->set_unused_property_fields(unused_property_fields);
1730   return new_map;
1731 }
1732
1733
1734 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1735                                        Handle<Name> name,
1736                                        Handle<Object> constant,
1737                                        PropertyAttributes attributes,
1738                                        TransitionFlag flag) {
1739   // Ensure the descriptor array does not get too big.
1740   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1741     return MaybeHandle<Map>();
1742   }
1743
1744   // Allocate new instance descriptors with (name, constant) added.
1745   DataConstantDescriptor new_constant_desc(name, constant, attributes);
1746   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1747 }
1748
1749
1750 void JSObject::AddSlowProperty(Handle<JSObject> object,
1751                                Handle<Name> name,
1752                                Handle<Object> value,
1753                                PropertyAttributes attributes) {
1754   DCHECK(!object->HasFastProperties());
1755   Isolate* isolate = object->GetIsolate();
1756   Handle<NameDictionary> dict(object->property_dictionary());
1757   if (object->IsGlobalObject()) {
1758     // In case name is an orphaned property reuse the cell.
1759     int entry = dict->FindEntry(name);
1760     if (entry != NameDictionary::kNotFound) {
1761       Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
1762       PropertyCell::SetValueInferType(cell, value);
1763       // Assign an enumeration index to the property and update
1764       // SetNextEnumerationIndex.
1765       int index = dict->NextEnumerationIndex();
1766       PropertyDetails details(attributes, DATA, index);
1767       dict->SetNextEnumerationIndex(index + 1);
1768       dict->SetEntry(entry, name, cell, details);
1769       return;
1770     }
1771     value = isolate->factory()->NewPropertyCell(value);
1772   }
1773   PropertyDetails details(attributes, DATA, 0);
1774   Handle<NameDictionary> result =
1775       NameDictionary::Add(dict, name, value, details);
1776   if (*dict != *result) object->set_properties(*result);
1777 }
1778
1779
1780 Context* JSObject::GetCreationContext() {
1781   Object* constructor = this->map()->constructor();
1782   JSFunction* function;
1783   if (!constructor->IsJSFunction()) {
1784     // Functions have null as a constructor,
1785     // but any JSFunction knows its context immediately.
1786     function = JSFunction::cast(this);
1787   } else {
1788     function = JSFunction::cast(constructor);
1789   }
1790
1791   return function->context()->native_context();
1792 }
1793
1794
1795 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1796                                                   const char* type_str,
1797                                                   Handle<Name> name,
1798                                                   Handle<Object> old_value) {
1799   DCHECK(!object->IsJSGlobalProxy());
1800   DCHECK(!object->IsJSGlobalObject());
1801   Isolate* isolate = object->GetIsolate();
1802   HandleScope scope(isolate);
1803   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1804   Handle<Object> args[] = { type, object, name, old_value };
1805   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1806
1807   return Execution::Call(isolate,
1808                          Handle<JSFunction>(isolate->observers_notify_change()),
1809                          isolate->factory()->undefined_value(), argc, args);
1810 }
1811
1812
1813 const char* Representation::Mnemonic() const {
1814   switch (kind_) {
1815     case kNone: return "v";
1816     case kTagged: return "t";
1817     case kSmi: return "s";
1818     case kDouble: return "d";
1819     case kInteger32: return "i";
1820     case kHeapObject: return "h";
1821     case kExternal: return "x";
1822     default:
1823       UNREACHABLE();
1824       return NULL;
1825   }
1826 }
1827
1828
1829 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1830                                  int target_inobject, int target_unused,
1831                                  int* old_number_of_fields) {
1832   // If fields were added (or removed), rewrite the instance.
1833   *old_number_of_fields = NumberOfFields();
1834   DCHECK(target_number_of_fields >= *old_number_of_fields);
1835   if (target_number_of_fields != *old_number_of_fields) return true;
1836
1837   // If smi descriptors were replaced by double descriptors, rewrite.
1838   DescriptorArray* old_desc = instance_descriptors();
1839   DescriptorArray* new_desc = target->instance_descriptors();
1840   int limit = NumberOfOwnDescriptors();
1841   for (int i = 0; i < limit; i++) {
1842     if (new_desc->GetDetails(i).representation().IsDouble() !=
1843         old_desc->GetDetails(i).representation().IsDouble()) {
1844       return true;
1845     }
1846   }
1847
1848   // If no fields were added, and no inobject properties were removed, setting
1849   // the map is sufficient.
1850   if (target_inobject == inobject_properties()) return false;
1851   // In-object slack tracking may have reduced the object size of the new map.
1852   // In that case, succeed if all existing fields were inobject, and they still
1853   // fit within the new inobject size.
1854   DCHECK(target_inobject < inobject_properties());
1855   if (target_number_of_fields <= target_inobject) {
1856     DCHECK(target_number_of_fields + target_unused == target_inobject);
1857     return false;
1858   }
1859   // Otherwise, properties will need to be moved to the backing store.
1860   return true;
1861 }
1862
1863
1864 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
1865   Isolate* isolate = parent->GetIsolate();
1866   Handle<Name> name = isolate->factory()->elements_transition_symbol();
1867   ConnectTransition(parent, child, name, SPECIAL_TRANSITION);
1868 }
1869
1870
1871 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
1872   if (object->map() == *new_map) return;
1873   if (object->HasFastProperties()) {
1874     if (!new_map->is_dictionary_map()) {
1875       Handle<Map> old_map(object->map());
1876       MigrateFastToFast(object, new_map);
1877       if (old_map->is_prototype_map()) {
1878         // Clear out the old descriptor array to avoid problems to sharing
1879         // the descriptor array without using an explicit.
1880         old_map->InitializeDescriptors(
1881             old_map->GetHeap()->empty_descriptor_array(),
1882             LayoutDescriptor::FastPointerLayout());
1883         // Ensure that no transition was inserted for prototype migrations.
1884         DCHECK(!old_map->HasTransitionArray());
1885         DCHECK(new_map->GetBackPointer()->IsUndefined());
1886       }
1887     } else {
1888       MigrateFastToSlow(object, new_map, 0);
1889     }
1890   } else {
1891     // For slow-to-fast migrations JSObject::TransformToFastProperties()
1892     // must be used instead.
1893     CHECK(new_map->is_dictionary_map());
1894
1895     // Slow-to-slow migration is trivial.
1896     object->set_map(*new_map);
1897   }
1898 }
1899
1900
1901 // To migrate a fast instance to a fast map:
1902 // - First check whether the instance needs to be rewritten. If not, simply
1903 //   change the map.
1904 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1905 //   addition to unused space.
1906 // - Copy all existing properties in, in the following order: backing store
1907 //   properties, unused fields, inobject properties.
1908 // - If all allocation succeeded, commit the state atomically:
1909 //   * Copy inobject properties from the backing store back into the object.
1910 //   * Trim the difference in instance size of the object. This also cleanly
1911 //     frees inobject properties that moved to the backing store.
1912 //   * If there are properties left in the backing store, trim of the space used
1913 //     to temporarily store the inobject properties.
1914 //   * If there are properties left in the backing store, install the backing
1915 //     store.
1916 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1917   Isolate* isolate = object->GetIsolate();
1918   Handle<Map> old_map(object->map());
1919   int old_number_of_fields;
1920   int number_of_fields = new_map->NumberOfFields();
1921   int inobject = new_map->inobject_properties();
1922   int unused = new_map->unused_property_fields();
1923
1924   // Nothing to do if no functions were converted to fields and no smis were
1925   // converted to doubles.
1926   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1927                                        unused, &old_number_of_fields)) {
1928     object->synchronized_set_map(*new_map);
1929     return;
1930   }
1931
1932   int total_size = number_of_fields + unused;
1933   int external = total_size - inobject;
1934
1935   if (number_of_fields != old_number_of_fields &&
1936       new_map->GetBackPointer() == *old_map) {
1937     PropertyDetails details = new_map->GetLastDescriptorDetails();
1938
1939     if (old_map->unused_property_fields() > 0) {
1940       if (details.representation().IsDouble()) {
1941         FieldIndex index =
1942             FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1943         if (new_map->IsUnboxedDoubleField(index)) {
1944           object->RawFastDoublePropertyAtPut(index, 0);
1945         } else {
1946           Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1947           object->RawFastPropertyAtPut(index, *value);
1948         }
1949       }
1950       object->synchronized_set_map(*new_map);
1951       return;
1952     }
1953
1954     DCHECK(number_of_fields == old_number_of_fields + 1);
1955     // This migration is a transition from a map that has run out of property
1956     // space. Therefore it could be done by extending the backing store.
1957     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1958     Handle<FixedArray> new_storage =
1959         FixedArray::CopySize(old_storage, external);
1960
1961     // Properly initialize newly added property.
1962     Handle<Object> value;
1963     if (details.representation().IsDouble()) {
1964       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1965     } else {
1966       value = isolate->factory()->uninitialized_value();
1967     }
1968     DCHECK(details.type() == DATA);
1969     int target_index = details.field_index() - inobject;
1970     DCHECK(target_index >= 0);  // Must be a backing store index.
1971     new_storage->set(target_index, *value);
1972
1973     // From here on we cannot fail and we shouldn't GC anymore.
1974     DisallowHeapAllocation no_allocation;
1975
1976     // Set the new property value and do the map transition.
1977     object->set_properties(*new_storage);
1978     object->synchronized_set_map(*new_map);
1979     return;
1980   }
1981   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
1982
1983   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
1984   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
1985   int old_nof = old_map->NumberOfOwnDescriptors();
1986   int new_nof = new_map->NumberOfOwnDescriptors();
1987
1988   // This method only supports generalizing instances to at least the same
1989   // number of properties.
1990   DCHECK(old_nof <= new_nof);
1991
1992   for (int i = 0; i < old_nof; i++) {
1993     PropertyDetails details = new_descriptors->GetDetails(i);
1994     if (details.type() != DATA) continue;
1995     PropertyDetails old_details = old_descriptors->GetDetails(i);
1996     Representation old_representation = old_details.representation();
1997     Representation representation = details.representation();
1998     Handle<Object> value;
1999     if (old_details.type() == ACCESSOR_CONSTANT) {
2000       // In case of kAccessor -> kData property reconfiguration, the property
2001       // must already be prepared for data or certain type.
2002       DCHECK(!details.representation().IsNone());
2003       if (details.representation().IsDouble()) {
2004         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2005       } else {
2006         value = isolate->factory()->uninitialized_value();
2007       }
2008     } else if (old_details.type() == DATA_CONSTANT) {
2009       value = handle(old_descriptors->GetValue(i), isolate);
2010       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
2011     } else {
2012       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
2013       if (object->IsUnboxedDoubleField(index)) {
2014         double old = object->RawFastDoublePropertyAt(index);
2015         value = isolate->factory()->NewHeapNumber(
2016             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
2017
2018       } else {
2019         value = handle(object->RawFastPropertyAt(index), isolate);
2020         if (!old_representation.IsDouble() && representation.IsDouble()) {
2021           if (old_representation.IsNone()) {
2022             value = handle(Smi::FromInt(0), isolate);
2023           }
2024           value = Object::NewStorageFor(isolate, value, representation);
2025         } else if (old_representation.IsDouble() &&
2026                    !representation.IsDouble()) {
2027           value = Object::WrapForRead(isolate, value, old_representation);
2028         }
2029       }
2030     }
2031     DCHECK(!(representation.IsDouble() && value->IsSmi()));
2032     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2033     if (target_index < 0) target_index += total_size;
2034     array->set(target_index, *value);
2035   }
2036
2037   for (int i = old_nof; i < new_nof; i++) {
2038     PropertyDetails details = new_descriptors->GetDetails(i);
2039     if (details.type() != DATA) continue;
2040     Handle<Object> value;
2041     if (details.representation().IsDouble()) {
2042       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2043     } else {
2044       value = isolate->factory()->uninitialized_value();
2045     }
2046     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2047     if (target_index < 0) target_index += total_size;
2048     array->set(target_index, *value);
2049   }
2050
2051   // From here on we cannot fail and we shouldn't GC anymore.
2052   DisallowHeapAllocation no_allocation;
2053
2054   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2055   // avoid overwriting |one_pointer_filler_map|.
2056   int limit = Min(inobject, number_of_fields);
2057   for (int i = 0; i < limit; i++) {
2058     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2059     Object* value = array->get(external + i);
2060     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
2061     // yet.
2062     if (new_map->IsUnboxedDoubleField(index)) {
2063       DCHECK(value->IsMutableHeapNumber());
2064       object->RawFastDoublePropertyAtPut(index,
2065                                          HeapNumber::cast(value)->value());
2066     } else {
2067       object->RawFastPropertyAtPut(index, value);
2068     }
2069   }
2070
2071   Heap* heap = isolate->heap();
2072
2073   // If there are properties in the new backing store, trim it to the correct
2074   // size and install the backing store into the object.
2075   if (external > 0) {
2076     heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject);
2077     object->set_properties(*array);
2078   }
2079
2080   // Create filler object past the new instance size.
2081   int new_instance_size = new_map->instance_size();
2082   int instance_size_delta = old_map->instance_size() - new_instance_size;
2083   DCHECK(instance_size_delta >= 0);
2084
2085   if (instance_size_delta > 0) {
2086     Address address = object->address();
2087     heap->CreateFillerObjectAt(
2088         address + new_instance_size, instance_size_delta);
2089     heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
2090   }
2091
2092   // We are storing the new map using release store after creating a filler for
2093   // the left-over space to avoid races with the sweeper thread.
2094   object->synchronized_set_map(*new_map);
2095 }
2096
2097
2098 int Map::NumberOfFields() {
2099   DescriptorArray* descriptors = instance_descriptors();
2100   int result = 0;
2101   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2102     if (descriptors->GetDetails(i).location() == kField) result++;
2103   }
2104   return result;
2105 }
2106
2107
2108 Handle<Map> Map::CopyGeneralizeAllRepresentations(
2109     Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
2110     PropertyAttributes attributes, const char* reason) {
2111   Isolate* isolate = map->GetIsolate();
2112   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2113   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2114   Handle<DescriptorArray> descriptors =
2115       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
2116
2117   for (int i = 0; i < number_of_own_descriptors; i++) {
2118     descriptors->SetRepresentation(i, Representation::Tagged());
2119     if (descriptors->GetDetails(i).type() == DATA) {
2120       descriptors->SetValue(i, HeapType::Any());
2121     }
2122   }
2123
2124   Handle<LayoutDescriptor> new_layout_descriptor(
2125       LayoutDescriptor::FastPointerLayout(), isolate);
2126   Handle<Map> new_map = CopyReplaceDescriptors(
2127       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
2128       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
2129
2130   // Unless the instance is being migrated, ensure that modify_index is a field.
2131   if (modify_index >= 0) {
2132     PropertyDetails details = descriptors->GetDetails(modify_index);
2133     if (store_mode == FORCE_FIELD &&
2134         (details.type() != DATA || details.attributes() != attributes)) {
2135       int field_index = details.type() == DATA ? details.field_index()
2136                                                : new_map->NumberOfFields();
2137       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2138                        field_index, attributes, Representation::Tagged());
2139       descriptors->Replace(modify_index, &d);
2140       if (details.type() != DATA) {
2141         int unused_property_fields = new_map->unused_property_fields() - 1;
2142         if (unused_property_fields < 0) {
2143           unused_property_fields += JSObject::kFieldsAdded;
2144         }
2145         new_map->set_unused_property_fields(unused_property_fields);
2146       }
2147     } else {
2148       DCHECK(details.attributes() == attributes);
2149     }
2150
2151     if (FLAG_trace_generalization) {
2152       HeapType* field_type =
2153           (details.type() == DATA)
2154               ? map->instance_descriptors()->GetFieldType(modify_index)
2155               : NULL;
2156       map->PrintGeneralization(
2157           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
2158           new_map->NumberOfOwnDescriptors(),
2159           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
2160           details.representation(), Representation::Tagged(), field_type,
2161           HeapType::Any());
2162     }
2163   }
2164   return new_map;
2165 }
2166
2167
2168 void Map::DeprecateTransitionTree() {
2169   if (is_deprecated()) return;
2170   if (HasTransitionArray()) {
2171     TransitionArray* transitions = this->transitions();
2172     for (int i = 0; i < transitions->number_of_transitions(); i++) {
2173       transitions->GetTarget(i)->DeprecateTransitionTree();
2174     }
2175   }
2176   deprecate();
2177   dependent_code()->DeoptimizeDependentCodeGroup(
2178       GetIsolate(), DependentCode::kTransitionGroup);
2179   NotifyLeafMapLayoutChange();
2180 }
2181
2182
2183 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2184   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
2185   // TODO(ishell): compare AccessorPairs.
2186   return false;
2187 }
2188
2189
2190 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2191 // the current instance_descriptors to ensure proper sharing of descriptor
2192 // arrays.
2193 // Returns true if the transition target at given key was deprecated.
2194 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2195                           PropertyAttributes attributes,
2196                           DescriptorArray* new_descriptors,
2197                           LayoutDescriptor* new_layout_descriptor) {
2198   bool transition_target_deprecated = false;
2199   if (HasTransitionArray()) {
2200     TransitionArray* transitions = this->transitions();
2201     int transition = transitions->Search(kind, key, attributes);
2202     if (transition != TransitionArray::kNotFound) {
2203       transitions->GetTarget(transition)->DeprecateTransitionTree();
2204       transition_target_deprecated = true;
2205     }
2206   }
2207
2208   // Don't overwrite the empty descriptor array.
2209   if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
2210
2211   DescriptorArray* to_replace = instance_descriptors();
2212   Map* current = this;
2213   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2214   while (current->instance_descriptors() == to_replace) {
2215     current->SetEnumLength(kInvalidEnumCacheSentinel);
2216     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2217     Object* next = current->GetBackPointer();
2218     if (next->IsUndefined()) break;
2219     current = Map::cast(next);
2220   }
2221
2222   set_owns_descriptors(false);
2223   return transition_target_deprecated;
2224 }
2225
2226
2227 Map* Map::FindRootMap() {
2228   Map* result = this;
2229   while (true) {
2230     Object* back = result->GetBackPointer();
2231     if (back->IsUndefined()) return result;
2232     result = Map::cast(back);
2233   }
2234 }
2235
2236
2237 Map* Map::FindLastMatchMap(int verbatim,
2238                            int length,
2239                            DescriptorArray* descriptors) {
2240   DisallowHeapAllocation no_allocation;
2241
2242   // This can only be called on roots of transition trees.
2243   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
2244
2245   Map* current = this;
2246
2247   for (int i = verbatim; i < length; i++) {
2248     if (!current->HasTransitionArray()) break;
2249     Name* name = descriptors->GetKey(i);
2250     PropertyDetails details = descriptors->GetDetails(i);
2251     TransitionArray* transitions = current->transitions();
2252     int transition =
2253         transitions->Search(details.kind(), name, details.attributes());
2254     if (transition == TransitionArray::kNotFound) break;
2255
2256     Map* next = transitions->GetTarget(transition);
2257     DescriptorArray* next_descriptors = next->instance_descriptors();
2258
2259     PropertyDetails next_details = next_descriptors->GetDetails(i);
2260     DCHECK_EQ(details.kind(), next_details.kind());
2261     DCHECK_EQ(details.attributes(), next_details.attributes());
2262     if (details.location() != next_details.location()) break;
2263     if (!details.representation().Equals(next_details.representation())) break;
2264
2265     if (next_details.location() == kField) {
2266       HeapType* next_field_type = next_descriptors->GetFieldType(i);
2267       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
2268         break;
2269       }
2270     } else {
2271       if (!EqualImmutableValues(descriptors->GetValue(i),
2272                                 next_descriptors->GetValue(i))) {
2273         break;
2274       }
2275     }
2276     current = next;
2277   }
2278   return current;
2279 }
2280
2281
2282 Map* Map::FindFieldOwner(int descriptor) {
2283   DisallowHeapAllocation no_allocation;
2284   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
2285   Map* result = this;
2286   while (true) {
2287     Object* back = result->GetBackPointer();
2288     if (back->IsUndefined()) break;
2289     Map* parent = Map::cast(back);
2290     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2291     result = parent;
2292   }
2293   return result;
2294 }
2295
2296
2297 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2298                           Representation new_representation,
2299                           Handle<HeapType> new_type) {
2300   DisallowHeapAllocation no_allocation;
2301   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2302   if (details.type() != DATA) return;
2303   if (HasTransitionArray()) {
2304     TransitionArray* transitions = this->transitions();
2305     for (int i = 0; i < transitions->number_of_transitions(); ++i) {
2306       transitions->GetTarget(i)
2307           ->UpdateFieldType(descriptor, name, new_representation, new_type);
2308     }
2309   }
2310   // It is allowed to change representation here only from None to something.
2311   DCHECK(details.representation().Equals(new_representation) ||
2312          details.representation().IsNone());
2313
2314   // Skip if already updated the shared descriptor.
2315   if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
2316   DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2317                    new_type, details.attributes(), new_representation);
2318   instance_descriptors()->Replace(descriptor, &d);
2319 }
2320
2321
2322 // static
2323 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2324                                           Handle<HeapType> type2,
2325                                           Isolate* isolate) {
2326   if (type1->NowIs(type2)) return type2;
2327   if (type2->NowIs(type1)) return type1;
2328   return HeapType::Any(isolate);
2329 }
2330
2331
2332 // static
2333 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
2334                               Representation new_representation,
2335                               Handle<HeapType> new_field_type) {
2336   Isolate* isolate = map->GetIsolate();
2337
2338   // Check if we actually need to generalize the field type at all.
2339   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2340   Representation old_representation =
2341       old_descriptors->GetDetails(modify_index).representation();
2342   Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
2343                                   isolate);
2344
2345   if (old_representation.Equals(new_representation) &&
2346       new_field_type->NowIs(old_field_type)) {
2347     DCHECK(Map::GeneralizeFieldType(old_field_type,
2348                                     new_field_type,
2349                                     isolate)->NowIs(old_field_type));
2350     return;
2351   }
2352
2353   // Determine the field owner.
2354   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2355   Handle<DescriptorArray> descriptors(
2356       field_owner->instance_descriptors(), isolate);
2357   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2358
2359   // Determine the generalized new field type.
2360   new_field_type = Map::GeneralizeFieldType(
2361       old_field_type, new_field_type, isolate);
2362
2363   PropertyDetails details = descriptors->GetDetails(modify_index);
2364   Handle<Name> name(descriptors->GetKey(modify_index));
2365   field_owner->UpdateFieldType(modify_index, name, new_representation,
2366                                new_field_type);
2367   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2368       isolate, DependentCode::kFieldTypeGroup);
2369
2370   if (FLAG_trace_generalization) {
2371     map->PrintGeneralization(
2372         stdout, "field type generalization",
2373         modify_index, map->NumberOfOwnDescriptors(),
2374         map->NumberOfOwnDescriptors(), false,
2375         details.representation(), details.representation(),
2376         *old_field_type, *new_field_type);
2377   }
2378 }
2379
2380
2381 static inline Handle<HeapType> GetFieldType(Isolate* isolate,
2382                                             Handle<DescriptorArray> descriptors,
2383                                             int descriptor,
2384                                             PropertyLocation location,
2385                                             Representation representation) {
2386 #ifdef DEBUG
2387   PropertyDetails details = descriptors->GetDetails(descriptor);
2388   DCHECK_EQ(kData, details.kind());
2389   DCHECK_EQ(details.location(), location);
2390 #endif
2391   if (location == kField) {
2392     return handle(descriptors->GetFieldType(descriptor), isolate);
2393   } else {
2394     return descriptors->GetValue(descriptor)
2395         ->OptimalType(isolate, representation);
2396   }
2397 }
2398
2399
2400 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
2401 // |store_mode| and/or |new_representation|/|new_field_type|.
2402 // If |modify_index| is negative then no properties are reconfigured but the
2403 // map is migrated to the up-to-date non-deprecated state.
2404 //
2405 // This method rewrites or completes the transition tree to reflect the new
2406 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
2407 // on every rewrite the new type is deduced by merging the current type with
2408 // any potential new (partial) version of the type in the transition tree.
2409 // To do this, on each rewrite:
2410 // - Search the root of the transition tree using FindRootMap.
2411 // - Find |target_map|, the newest matching version of this map using the
2412 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
2413 //   |modify_index| is considered to be of |new_kind| and having
2414 //   |new_attributes|) to walk the transition tree.
2415 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
2416 //   descriptor array of the |target_map|.
2417 // - Generalize the |modify_index| descriptor using |new_representation| and
2418 //   |new_field_type|.
2419 // - Walk the tree again starting from the root towards |target_map|. Stop at
2420 //   |split_map|, the first map who's descriptor array does not match the merged
2421 //   descriptor array.
2422 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2423 //   Return it.
2424 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2425 //   replace its transition tree with a new branch for the updated descriptors.
2426 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2427                                      PropertyKind new_kind,
2428                                      PropertyAttributes new_attributes,
2429                                      Representation new_representation,
2430                                      Handle<HeapType> new_field_type,
2431                                      StoreMode store_mode) {
2432   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
2433   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2434   Isolate* isolate = old_map->GetIsolate();
2435
2436   Handle<DescriptorArray> old_descriptors(
2437       old_map->instance_descriptors(), isolate);
2438   int old_nof = old_map->NumberOfOwnDescriptors();
2439
2440   // If it's just a representation generalization case (i.e. property kind and
2441   // attributes stays unchanged) it's fine to transition from None to anything
2442   // but double without any modification to the object, because the default
2443   // uninitialized value for representation None can be overwritten by both
2444   // smi and tagged values. Doubles, however, would require a box allocation.
2445   if (modify_index >= 0 && !new_representation.IsNone() &&
2446       !new_representation.IsDouble()) {
2447     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2448     Representation old_representation = old_details.representation();
2449
2450     if (old_representation.IsNone()) {
2451       DCHECK_EQ(new_kind, old_details.kind());
2452       DCHECK_EQ(new_attributes, old_details.attributes());
2453       DCHECK_EQ(DATA, old_details.type());
2454       if (FLAG_trace_generalization) {
2455         old_map->PrintGeneralization(
2456             stdout, "uninitialized field", modify_index,
2457             old_map->NumberOfOwnDescriptors(),
2458             old_map->NumberOfOwnDescriptors(), false, old_representation,
2459             new_representation, old_descriptors->GetFieldType(modify_index),
2460             *new_field_type);
2461       }
2462       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2463
2464       GeneralizeFieldType(field_owner, modify_index, new_representation,
2465                           new_field_type);
2466       DCHECK(old_descriptors->GetDetails(modify_index)
2467                  .representation()
2468                  .Equals(new_representation));
2469       DCHECK(
2470           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2471       return old_map;
2472     }
2473   }
2474
2475   // Check the state of the root map.
2476   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2477   if (!old_map->EquivalentToForTransition(*root_map)) {
2478     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2479                                             new_kind, new_attributes,
2480                                             "GenAll_NotEquivalent");
2481   }
2482
2483   ElementsKind from_kind = root_map->elements_kind();
2484   ElementsKind to_kind = old_map->elements_kind();
2485   if (from_kind != to_kind &&
2486       !(IsTransitionableFastElementsKind(from_kind) &&
2487         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2488     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2489                                             new_kind, new_attributes,
2490                                             "GenAll_InvalidElementsTransition");
2491   }
2492   int root_nof = root_map->NumberOfOwnDescriptors();
2493   if (modify_index >= 0 && modify_index < root_nof) {
2494     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2495     if (old_details.kind() != new_kind ||
2496         old_details.attributes() != new_attributes) {
2497       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2498                                               new_kind, new_attributes,
2499                                               "GenAll_RootModification1");
2500     }
2501     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2502         (old_details.type() == DATA &&
2503          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2504           !new_representation.fits_into(old_details.representation())))) {
2505       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2506                                               new_kind, new_attributes,
2507                                               "GenAll_RootModification2");
2508     }
2509   }
2510
2511   // From here on, use the map with correct elements kind as root map.
2512   if (from_kind != to_kind) {
2513     root_map = Map::AsElementsKind(root_map, to_kind);
2514   }
2515
2516   Handle<Map> target_map = root_map;
2517   for (int i = root_nof; i < old_nof; ++i) {
2518     PropertyDetails old_details = old_descriptors->GetDetails(i);
2519     PropertyKind next_kind;
2520     PropertyLocation next_location;
2521     PropertyAttributes next_attributes;
2522     Representation next_representation;
2523     bool property_kind_reconfiguration = false;
2524
2525     if (modify_index == i) {
2526       DCHECK_EQ(FORCE_FIELD, store_mode);
2527       property_kind_reconfiguration = old_details.kind() != new_kind;
2528
2529       next_kind = new_kind;
2530       next_location = kField;
2531       next_attributes = new_attributes;
2532       // If property kind is not reconfigured merge the result with
2533       // representation/field type from the old descriptor.
2534       next_representation = new_representation;
2535       if (!property_kind_reconfiguration) {
2536         next_representation =
2537             next_representation.generalize(old_details.representation());
2538       }
2539
2540     } else {
2541       next_kind = old_details.kind();
2542       next_location = old_details.location();
2543       next_attributes = old_details.attributes();
2544       next_representation = old_details.representation();
2545     }
2546     int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i),
2547                                          next_attributes);
2548     if (j == TransitionArray::kNotFound) break;
2549     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2550     Handle<DescriptorArray> tmp_descriptors = handle(
2551         tmp_map->instance_descriptors(), isolate);
2552
2553     // Check if target map is incompatible.
2554     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2555     DCHECK_EQ(next_kind, tmp_details.kind());
2556     DCHECK_EQ(next_attributes, tmp_details.attributes());
2557     if (next_kind == kAccessor &&
2558         !EqualImmutableValues(old_descriptors->GetValue(i),
2559                               tmp_descriptors->GetValue(i))) {
2560       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2561                                               new_kind, new_attributes,
2562                                               "GenAll_Incompatible");
2563     }
2564     if (next_location == kField && tmp_details.location() == kDescriptor) break;
2565
2566     Representation tmp_representation = tmp_details.representation();
2567     if (!next_representation.fits_into(tmp_representation)) break;
2568
2569     PropertyLocation old_location = old_details.location();
2570     PropertyLocation tmp_location = tmp_details.location();
2571     if (tmp_location == kField) {
2572       if (next_kind == kData) {
2573         Handle<HeapType> next_field_type;
2574         if (modify_index == i) {
2575           next_field_type = new_field_type;
2576           if (!property_kind_reconfiguration) {
2577             Handle<HeapType> old_field_type =
2578                 GetFieldType(isolate, old_descriptors, i,
2579                              old_details.location(), tmp_representation);
2580             next_field_type =
2581                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2582           }
2583         } else {
2584           Handle<HeapType> old_field_type =
2585               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2586                            tmp_representation);
2587           next_field_type = old_field_type;
2588         }
2589         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
2590       }
2591     } else if (old_location == kField ||
2592                !EqualImmutableValues(old_descriptors->GetValue(i),
2593                                      tmp_descriptors->GetValue(i))) {
2594       break;
2595     }
2596     DCHECK(!tmp_map->is_deprecated());
2597     target_map = tmp_map;
2598   }
2599
2600   // Directly change the map if the target map is more general.
2601   Handle<DescriptorArray> target_descriptors(
2602       target_map->instance_descriptors(), isolate);
2603   int target_nof = target_map->NumberOfOwnDescriptors();
2604   if (target_nof == old_nof &&
2605       (store_mode != FORCE_FIELD ||
2606        (modify_index >= 0 &&
2607         target_descriptors->GetDetails(modify_index).location() == kField))) {
2608 #ifdef DEBUG
2609     if (modify_index >= 0) {
2610       PropertyDetails details = target_descriptors->GetDetails(modify_index);
2611       DCHECK_EQ(new_kind, details.kind());
2612       DCHECK_EQ(new_attributes, details.attributes());
2613       DCHECK(new_representation.fits_into(details.representation()));
2614       DCHECK(details.location() != kField ||
2615              new_field_type->NowIs(
2616                  target_descriptors->GetFieldType(modify_index)));
2617     }
2618 #endif
2619     return target_map;
2620   }
2621
2622   // Find the last compatible target map in the transition tree.
2623   for (int i = target_nof; i < old_nof; ++i) {
2624     PropertyDetails old_details = old_descriptors->GetDetails(i);
2625     PropertyKind next_kind;
2626     PropertyAttributes next_attributes;
2627     if (modify_index == i) {
2628       next_kind = new_kind;
2629       next_attributes = new_attributes;
2630     } else {
2631       next_kind = old_details.kind();
2632       next_attributes = old_details.attributes();
2633     }
2634     int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i),
2635                                          next_attributes);
2636     if (j == TransitionArray::kNotFound) break;
2637     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2638     Handle<DescriptorArray> tmp_descriptors(
2639         tmp_map->instance_descriptors(), isolate);
2640
2641     // Check if target map is compatible.
2642 #ifdef DEBUG
2643     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2644     DCHECK_EQ(next_kind, tmp_details.kind());
2645     DCHECK_EQ(next_attributes, tmp_details.attributes());
2646 #endif
2647     if (next_kind == kAccessor &&
2648         !EqualImmutableValues(old_descriptors->GetValue(i),
2649                               tmp_descriptors->GetValue(i))) {
2650       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2651                                               new_kind, new_attributes,
2652                                               "GenAll_Incompatible");
2653     }
2654     DCHECK(!tmp_map->is_deprecated());
2655     target_map = tmp_map;
2656   }
2657   target_nof = target_map->NumberOfOwnDescriptors();
2658   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2659
2660   // Allocate a new descriptor array large enough to hold the required
2661   // descriptors, with minimally the exact same size as the old descriptor
2662   // array.
2663   int new_slack = Max(
2664       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2665   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2666       isolate, old_nof, new_slack);
2667   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2668          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2669          new_descriptors->number_of_descriptors() ==
2670          old_descriptors->number_of_descriptors());
2671   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2672
2673   // 0 -> |root_nof|
2674   int current_offset = 0;
2675   for (int i = 0; i < root_nof; ++i) {
2676     PropertyDetails old_details = old_descriptors->GetDetails(i);
2677     if (old_details.location() == kField) {
2678       current_offset += old_details.field_width_in_words();
2679     }
2680     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2681                  handle(old_descriptors->GetValue(i), isolate),
2682                  old_details);
2683     new_descriptors->Set(i, &d);
2684   }
2685
2686   // |root_nof| -> |target_nof|
2687   for (int i = root_nof; i < target_nof; ++i) {
2688     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2689     PropertyDetails old_details = old_descriptors->GetDetails(i);
2690     PropertyDetails target_details = target_descriptors->GetDetails(i);
2691
2692     PropertyKind next_kind;
2693     PropertyAttributes next_attributes;
2694     PropertyLocation next_location;
2695     Representation next_representation;
2696     bool property_kind_reconfiguration = false;
2697
2698     if (modify_index == i) {
2699       DCHECK_EQ(FORCE_FIELD, store_mode);
2700       property_kind_reconfiguration = old_details.kind() != new_kind;
2701
2702       next_kind = new_kind;
2703       next_attributes = new_attributes;
2704       next_location = kField;
2705
2706       // Merge new representation/field type with ones from the target
2707       // descriptor. If property kind is not reconfigured merge the result with
2708       // representation/field type from the old descriptor.
2709       next_representation =
2710           new_representation.generalize(target_details.representation());
2711       if (!property_kind_reconfiguration) {
2712         next_representation =
2713             next_representation.generalize(old_details.representation());
2714       }
2715     } else {
2716       // Merge old_descriptor and target_descriptor entries.
2717       DCHECK_EQ(target_details.kind(), old_details.kind());
2718       next_kind = target_details.kind();
2719       next_attributes = target_details.attributes();
2720       next_location =
2721           old_details.location() == kField ||
2722                   target_details.location() == kField ||
2723                   !EqualImmutableValues(target_descriptors->GetValue(i),
2724                                         old_descriptors->GetValue(i))
2725               ? kField
2726               : kDescriptor;
2727
2728       next_representation = old_details.representation().generalize(
2729           target_details.representation());
2730     }
2731     DCHECK_EQ(next_kind, target_details.kind());
2732     DCHECK_EQ(next_attributes, target_details.attributes());
2733
2734     if (next_location == kField) {
2735       if (next_kind == kData) {
2736         Handle<HeapType> target_field_type =
2737             GetFieldType(isolate, target_descriptors, i,
2738                          target_details.location(), next_representation);
2739
2740         Handle<HeapType> next_field_type;
2741         if (modify_index == i) {
2742           next_field_type =
2743               GeneralizeFieldType(target_field_type, new_field_type, isolate);
2744           if (!property_kind_reconfiguration) {
2745             Handle<HeapType> old_field_type =
2746                 GetFieldType(isolate, old_descriptors, i,
2747                              old_details.location(), next_representation);
2748             next_field_type =
2749                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2750           }
2751         } else {
2752           Handle<HeapType> old_field_type =
2753               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2754                            next_representation);
2755           next_field_type =
2756               GeneralizeFieldType(target_field_type, old_field_type, isolate);
2757         }
2758         DataDescriptor d(target_key, current_offset, next_field_type,
2759                          next_attributes, next_representation);
2760         current_offset += d.GetDetails().field_width_in_words();
2761         new_descriptors->Set(i, &d);
2762       } else {
2763         UNIMPLEMENTED();  // TODO(ishell): implement.
2764       }
2765     } else {
2766       PropertyDetails details(next_attributes, next_kind, next_location,
2767                               next_representation);
2768       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
2769                    details);
2770       new_descriptors->Set(i, &d);
2771     }
2772   }
2773
2774   // |target_nof| -> |old_nof|
2775   for (int i = target_nof; i < old_nof; ++i) {
2776     PropertyDetails old_details = old_descriptors->GetDetails(i);
2777     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2778
2779     // Merge old_descriptor entry and modified details together.
2780     PropertyKind next_kind;
2781     PropertyAttributes next_attributes;
2782     PropertyLocation next_location;
2783     Representation next_representation;
2784     bool property_kind_reconfiguration = false;
2785
2786     if (modify_index == i) {
2787       DCHECK_EQ(FORCE_FIELD, store_mode);
2788       // In case of property kind reconfiguration it is not necessary to
2789       // take into account representation/field type of the old descriptor.
2790       property_kind_reconfiguration = old_details.kind() != new_kind;
2791
2792       next_kind = new_kind;
2793       next_attributes = new_attributes;
2794       next_location = kField;
2795       next_representation = new_representation;
2796       if (!property_kind_reconfiguration) {
2797         next_representation =
2798             next_representation.generalize(old_details.representation());
2799       }
2800     } else {
2801       next_kind = old_details.kind();
2802       next_attributes = old_details.attributes();
2803       next_location = old_details.location();
2804       next_representation = old_details.representation();
2805     }
2806
2807     if (next_location == kField) {
2808       if (next_kind == kData) {
2809         Handle<HeapType> next_field_type;
2810         if (modify_index == i) {
2811           next_field_type = new_field_type;
2812           if (!property_kind_reconfiguration) {
2813             Handle<HeapType> old_field_type =
2814                 GetFieldType(isolate, old_descriptors, i,
2815                              old_details.location(), next_representation);
2816             next_field_type =
2817                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2818           }
2819         } else {
2820           Handle<HeapType> old_field_type =
2821               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2822                            next_representation);
2823           next_field_type = old_field_type;
2824         }
2825
2826         DataDescriptor d(old_key, current_offset, next_field_type,
2827                          next_attributes, next_representation);
2828         current_offset += d.GetDetails().field_width_in_words();
2829         new_descriptors->Set(i, &d);
2830       } else {
2831         UNIMPLEMENTED();  // TODO(ishell): implement.
2832       }
2833     } else {
2834       PropertyDetails details(next_attributes, next_kind, next_location,
2835                               next_representation);
2836       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
2837                    details);
2838       new_descriptors->Set(i, &d);
2839     }
2840   }
2841
2842   new_descriptors->Sort();
2843
2844   DCHECK(store_mode != FORCE_FIELD ||
2845          new_descriptors->GetDetails(modify_index).location() == kField);
2846
2847   Handle<Map> split_map(root_map->FindLastMatchMap(
2848           root_nof, old_nof, *new_descriptors), isolate);
2849   int split_nof = split_map->NumberOfOwnDescriptors();
2850   DCHECK_NE(old_nof, split_nof);
2851
2852   Handle<LayoutDescriptor> new_layout_descriptor =
2853       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
2854
2855   PropertyKind split_kind;
2856   PropertyAttributes split_attributes;
2857   if (modify_index == split_nof) {
2858     split_kind = new_kind;
2859     split_attributes = new_attributes;
2860   } else {
2861     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
2862     split_kind = split_prop_details.kind();
2863     split_attributes = split_prop_details.attributes();
2864   }
2865   bool transition_target_deprecated = split_map->DeprecateTarget(
2866       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2867       *new_descriptors, *new_layout_descriptor);
2868
2869   // If |transition_target_deprecated| is true then the transition array
2870   // already contains entry for given descriptor. This means that the transition
2871   // could be inserted regardless of whether transitions array is full or not.
2872   if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) {
2873     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2874                                             new_kind, new_attributes,
2875                                             "GenAll_CantHaveMoreTransitions");
2876   }
2877
2878   if (FLAG_trace_generalization && modify_index >= 0) {
2879     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2880     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2881     Handle<HeapType> old_field_type =
2882         (old_details.type() == DATA)
2883             ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2884             : HeapType::Constant(
2885                   handle(old_descriptors->GetValue(modify_index), isolate),
2886                   isolate);
2887     Handle<HeapType> new_field_type =
2888         (new_details.type() == DATA)
2889             ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2890             : HeapType::Constant(
2891                   handle(new_descriptors->GetValue(modify_index), isolate),
2892                   isolate);
2893     old_map->PrintGeneralization(
2894         stdout, "", modify_index, split_nof, old_nof,
2895         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2896         old_details.representation(), new_details.representation(),
2897         *old_field_type, *new_field_type);
2898   }
2899
2900   // Add missing transitions.
2901   Handle<Map> new_map = split_map;
2902   for (int i = split_nof; i < old_nof; ++i) {
2903     new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2904                                      new_layout_descriptor);
2905   }
2906   new_map->set_owns_descriptors(true);
2907   return new_map;
2908 }
2909
2910
2911 // Generalize the representation of all DATA descriptors.
2912 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2913     Handle<Map> map) {
2914   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2915   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2916     PropertyDetails details = descriptors->GetDetails(i);
2917     if (details.type() == DATA) {
2918       map = ReconfigureProperty(map, i, kData, details.attributes(),
2919                                 Representation::Tagged(),
2920                                 HeapType::Any(map->GetIsolate()), FORCE_FIELD);
2921     }
2922   }
2923   return map;
2924 }
2925
2926
2927 // static
2928 MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) {
2929   Handle<Map> proto_map(map);
2930   while (proto_map->prototype()->IsJSObject()) {
2931     Handle<JSObject> holder(JSObject::cast(proto_map->prototype()));
2932     proto_map = Handle<Map>(holder->map());
2933     if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) {
2934       proto_map = Handle<Map>(holder->map());
2935     }
2936   }
2937   return TryUpdateInternal(map);
2938 }
2939
2940
2941 // static
2942 Handle<Map> Map::Update(Handle<Map> map) {
2943   if (!map->is_deprecated()) return map;
2944   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
2945                              HeapType::None(map->GetIsolate()),
2946                              ALLOW_IN_DESCRIPTOR);
2947 }
2948
2949
2950 // static
2951 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) {
2952   DisallowHeapAllocation no_allocation;
2953   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2954
2955   if (!old_map->is_deprecated()) return old_map;
2956
2957   // Check the state of the root map.
2958   Map* root_map = old_map->FindRootMap();
2959   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2960   int root_nof = root_map->NumberOfOwnDescriptors();
2961
2962   int old_nof = old_map->NumberOfOwnDescriptors();
2963   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2964
2965   Map* new_map = root_map;
2966   for (int i = root_nof; i < old_nof; ++i) {
2967     PropertyDetails old_details = old_descriptors->GetDetails(i);
2968     int j = new_map->SearchTransition(old_details.kind(),
2969                                       old_descriptors->GetKey(i),
2970                                       old_details.attributes());
2971     if (j == TransitionArray::kNotFound) return MaybeHandle<Map>();
2972     new_map = new_map->GetTransition(j);
2973     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2974
2975     PropertyDetails new_details = new_descriptors->GetDetails(i);
2976     DCHECK_EQ(old_details.kind(), new_details.kind());
2977     DCHECK_EQ(old_details.attributes(), new_details.attributes());
2978     if (!old_details.representation().fits_into(new_details.representation())) {
2979       return MaybeHandle<Map>();
2980     }
2981     Object* new_value = new_descriptors->GetValue(i);
2982     Object* old_value = old_descriptors->GetValue(i);
2983     switch (new_details.type()) {
2984       case DATA: {
2985         PropertyType old_type = old_details.type();
2986         if (old_type == DATA) {
2987           if (!HeapType::cast(old_value)->NowIs(HeapType::cast(new_value))) {
2988             return MaybeHandle<Map>();
2989           }
2990         } else {
2991           DCHECK(old_type == DATA_CONSTANT);
2992           if (!HeapType::cast(new_value)->NowContains(old_value)) {
2993             return MaybeHandle<Map>();
2994           }
2995         }
2996         break;
2997       }
2998       case ACCESSOR:
2999         DCHECK(HeapType::Any()->Is(HeapType::cast(new_value)));
3000         break;
3001
3002       case DATA_CONSTANT:
3003       case ACCESSOR_CONSTANT:
3004         if (old_details.location() == kField || old_value != new_value) {
3005           return MaybeHandle<Map>();
3006         }
3007         break;
3008     }
3009   }
3010   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
3011   return handle(new_map);
3012 }
3013
3014
3015 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
3016                                                          Handle<Object> value) {
3017   Handle<Name> name = it->name();
3018   Handle<JSObject> holder = it->GetHolder<JSObject>();
3019   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
3020   if (interceptor->setter()->IsUndefined() ||
3021       (name->IsSymbol() && !interceptor->can_intercept_symbols())) {
3022     return MaybeHandle<Object>();
3023   }
3024
3025   LOG(it->isolate(),
3026       ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3027   PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
3028                                  *holder);
3029   v8::GenericNamedPropertySetterCallback setter =
3030       v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3031           interceptor->setter());
3032   v8::Handle<v8::Value> result =
3033       args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3034   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3035   if (!result.IsEmpty()) return value;
3036
3037   return MaybeHandle<Object>();
3038 }
3039
3040
3041 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3042                                         Handle<Name> name, Handle<Object> value,
3043                                         LanguageMode language_mode,
3044                                         StoreFromKeyed store_mode) {
3045   LookupIterator it(object, name);
3046   return SetProperty(&it, value, language_mode, store_mode);
3047 }
3048
3049
3050 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
3051                                                 Handle<Object> value,
3052                                                 LanguageMode language_mode,
3053                                                 StoreFromKeyed store_mode,
3054                                                 bool* found) {
3055   // Make sure that the top context does not change when doing callbacks or
3056   // interceptor calls.
3057   AssertNoContextChange ncc(it->isolate());
3058
3059   *found = true;
3060
3061   bool done = false;
3062   for (; it->IsFound(); it->Next()) {
3063     switch (it->state()) {
3064       case LookupIterator::NOT_FOUND:
3065         UNREACHABLE();
3066
3067       case LookupIterator::ACCESS_CHECK:
3068         // TODO(verwaest): Remove the distinction. This is mostly bogus since we
3069         // don't know whether we'll want to fetch attributes or call a setter
3070         // until we find the property.
3071         if (it->HasAccess(v8::ACCESS_SET)) break;
3072         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3073                                                           language_mode);
3074
3075       case LookupIterator::JSPROXY:
3076         if (it->HolderIsReceiverOrHiddenPrototype()) {
3077           return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
3078                                                  it->GetReceiver(), it->name(),
3079                                                  value, language_mode);
3080         } else {
3081           // TODO(verwaest): Use the MaybeHandle to indicate result.
3082           bool has_result = false;
3083           MaybeHandle<Object> maybe_result =
3084               JSProxy::SetPropertyViaPrototypesWithHandler(
3085                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->name(),
3086                   value, language_mode, &has_result);
3087           if (has_result) return maybe_result;
3088           done = true;
3089         }
3090         break;
3091
3092       case LookupIterator::INTERCEPTOR:
3093         if (it->HolderIsReceiverOrHiddenPrototype()) {
3094           MaybeHandle<Object> maybe_result =
3095               JSObject::SetPropertyWithInterceptor(it, value);
3096           if (!maybe_result.is_null()) return maybe_result;
3097           if (it->isolate()->has_pending_exception()) return maybe_result;
3098         } else {
3099           Maybe<PropertyAttributes> maybe_attributes =
3100               JSObject::GetPropertyAttributesWithInterceptor(
3101                   it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
3102           if (!maybe_attributes.has_value) return MaybeHandle<Object>();
3103           done = maybe_attributes.value != ABSENT;
3104           if (done && (maybe_attributes.value & READ_ONLY) != 0) {
3105             return WriteToReadOnlyProperty(it, value, language_mode);
3106           }
3107         }
3108         break;
3109
3110       case LookupIterator::ACCESSOR:
3111         if (it->property_details().IsReadOnly()) {
3112           return WriteToReadOnlyProperty(it, value, language_mode);
3113         }
3114         return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
3115                                        it->GetHolder<JSObject>(),
3116                                        it->GetAccessors(), language_mode);
3117
3118       case LookupIterator::DATA:
3119         if (it->property_details().IsReadOnly()) {
3120           return WriteToReadOnlyProperty(it, value, language_mode);
3121         }
3122         if (it->HolderIsReceiverOrHiddenPrototype()) {
3123           return SetDataProperty(it, value);
3124         }
3125         done = true;
3126         break;
3127
3128       case LookupIterator::TRANSITION:
3129         done = true;
3130         break;
3131     }
3132
3133     if (done) break;
3134   }
3135
3136   // If the receiver is the JSGlobalObject, the store was contextual. In case
3137   // the property did not exist yet on the global object itself, we have to
3138   // throw a reference error in strict mode.
3139   if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
3140     Handle<Object> args[] = {it->name()};
3141     THROW_NEW_ERROR(
3142         it->isolate(),
3143         NewReferenceError("not_defined", HandleVector(args, arraysize(args))),
3144         Object);
3145   }
3146
3147   *found = false;
3148   return MaybeHandle<Object>();
3149 }
3150
3151
3152 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3153                                         Handle<Object> value,
3154                                         LanguageMode language_mode,
3155                                         StoreFromKeyed store_mode) {
3156   bool found = false;
3157   MaybeHandle<Object> result =
3158       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3159   if (found) return result;
3160   return AddDataProperty(it, value, NONE, language_mode, store_mode);
3161 }
3162
3163
3164 MaybeHandle<Object> Object::SetSuperProperty(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
3173   LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN);
3174
3175   switch (own_lookup.state()) {
3176     case LookupIterator::NOT_FOUND:
3177       return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3178                                        store_mode);
3179
3180     case LookupIterator::DATA: {
3181       PropertyDetails details = own_lookup.property_details();
3182       if (details.IsConfigurable() || !details.IsReadOnly()) {
3183         return JSObject::SetOwnPropertyIgnoreAttributes(
3184             Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
3185             details.attributes());
3186       }
3187       return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3188     }
3189
3190     case LookupIterator::ACCESSOR: {
3191       PropertyDetails details = own_lookup.property_details();
3192       if (details.IsConfigurable()) {
3193         return JSObject::SetOwnPropertyIgnoreAttributes(
3194             Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
3195             details.attributes());
3196       }
3197
3198       return RedefineNonconfigurableProperty(it->isolate(), it->name(), value,
3199                                              language_mode);
3200     }
3201
3202     case LookupIterator::TRANSITION:
3203       UNREACHABLE();
3204       break;
3205
3206     case LookupIterator::INTERCEPTOR:
3207     case LookupIterator::JSPROXY:
3208     case LookupIterator::ACCESS_CHECK: {
3209       bool found = false;
3210       MaybeHandle<Object> result = SetPropertyInternal(
3211           &own_lookup, value, language_mode, store_mode, &found);
3212       if (found) return result;
3213       return SetDataProperty(&own_lookup, value);
3214     }
3215   }
3216
3217   UNREACHABLE();
3218   return MaybeHandle<Object>();
3219 }
3220
3221
3222 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3223     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3224   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(),
3225                                  value, language_mode);
3226 }
3227
3228
3229 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3230     Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3231     Handle<Object> value, LanguageMode language_mode) {
3232   if (is_sloppy(language_mode)) return value;
3233   Handle<Object> args[] = {name, receiver};
3234   THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
3235                                         HandleVector(args, arraysize(args))),
3236                   Object);
3237 }
3238
3239
3240 MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
3241                                                    Handle<Object> receiver,
3242                                                    uint32_t index,
3243                                                    Handle<Object> value,
3244                                                    LanguageMode language_mode) {
3245   return WriteToReadOnlyProperty(isolate, receiver,
3246                                  isolate->factory()->NewNumberFromUint(index),
3247                                  value, language_mode);
3248 }
3249
3250
3251 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
3252     Isolate* isolate, Handle<Object> name, Handle<Object> value,
3253     LanguageMode language_mode) {
3254   if (is_sloppy(language_mode)) return value;
3255   Handle<Object> args[] = {name};
3256   THROW_NEW_ERROR(isolate, NewTypeError("redefine_disallowed",
3257                                         HandleVector(args, arraysize(args))),
3258                   Object);
3259 }
3260
3261
3262 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3263                                             Handle<Object> value) {
3264   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3265   // have own properties.
3266   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3267
3268   // Store on the holder which may be hidden behind the receiver.
3269   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3270
3271   // Old value for the observation change record.
3272   // Fetch before transforming the object since the encoding may become
3273   // incompatible with what's cached in |it|.
3274   bool is_observed = receiver->map()->is_observed() &&
3275                      !it->isolate()->IsInternallyUsedPropertyName(it->name());
3276   MaybeHandle<Object> maybe_old;
3277   if (is_observed) maybe_old = it->GetDataValue();
3278
3279   // Possibly migrate to the most up-to-date map that will be able to store
3280   // |value| under it->name().
3281   it->PrepareForDataProperty(value);
3282
3283   // Write the property value.
3284   value = it->WriteDataValue(value);
3285
3286   // Send the change record if there are observers.
3287   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3288     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3289                                            receiver, "update", it->name(),
3290                                            maybe_old.ToHandleChecked()),
3291                         Object);
3292   }
3293
3294   return value;
3295 }
3296
3297
3298 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3299                                             Handle<Object> value,
3300                                             PropertyAttributes attributes,
3301                                             LanguageMode language_mode,
3302                                             StoreFromKeyed store_mode) {
3303   DCHECK(!it->GetReceiver()->IsJSProxy());
3304   if (!it->GetReceiver()->IsJSObject()) {
3305     // TODO(verwaest): Throw a TypeError with a more specific message.
3306     return WriteToReadOnlyProperty(it, value, language_mode);
3307   }
3308
3309   Handle<JSObject> receiver = it->GetStoreTarget();
3310
3311   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3312   // instead. If the prototype is Null, the proxy is detached.
3313   if (receiver->IsJSGlobalProxy()) return value;
3314
3315   // If the receiver is Indexed Exotic object (currently only typed arrays),
3316   // disallow adding properties with numeric names.
3317   if (it->IsSpecialNumericIndex()) return value;
3318
3319   // Possibly migrate to the most up-to-date map that will be able to store
3320   // |value| under it->name() with |attributes|.
3321   it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3322   if (it->state() != LookupIterator::TRANSITION) {
3323     if (is_sloppy(language_mode)) return value;
3324
3325     Handle<Object> args[] = {it->name()};
3326     THROW_NEW_ERROR(it->isolate(),
3327                     NewTypeError("object_not_extensible",
3328                                  HandleVector(args, arraysize(args))),
3329                     Object);
3330   }
3331   it->ApplyTransitionToDataProperty();
3332
3333   // TODO(verwaest): Encapsulate dictionary handling better.
3334   if (receiver->map()->is_dictionary_map()) {
3335     // TODO(verwaest): Probably should ensure this is done beforehand.
3336     it->InternalizeName();
3337     // TODO(dcarney): just populate TransitionPropertyCell here?
3338     JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3339   } else {
3340     // Write the property value.
3341     value = it->WriteDataValue(value);
3342   }
3343
3344   // Send the change record if there are observers.
3345   if (receiver->map()->is_observed() &&
3346       !it->isolate()->IsInternallyUsedPropertyName(it->name())) {
3347     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3348                                            receiver, "add", it->name(),
3349                                            it->factory()->the_hole_value()),
3350                         Object);
3351   }
3352
3353   return value;
3354 }
3355
3356
3357 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3358     Handle<JSObject> object, uint32_t index, Handle<Object> value, bool* found,
3359     LanguageMode language_mode) {
3360   Isolate* isolate = object->GetIsolate();
3361   for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3362        iter.Advance()) {
3363     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3364       return JSProxy::SetPropertyViaPrototypesWithHandler(
3365           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3366           isolate->factory()->Uint32ToString(index),  // name
3367           value, language_mode, found);
3368     }
3369     Handle<JSObject> js_proto =
3370         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3371
3372     if (js_proto->IsAccessCheckNeeded()) {
3373       if (!isolate->MayIndexedAccess(js_proto, index, v8::ACCESS_SET)) {
3374         *found = true;
3375         isolate->ReportFailedAccessCheck(js_proto, v8::ACCESS_SET);
3376         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3377         return MaybeHandle<Object>();
3378       }
3379     }
3380
3381     if (!js_proto->HasDictionaryElements()) {
3382       continue;
3383     }
3384
3385     Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3386     int entry = dictionary->FindEntry(index);
3387     if (entry != SeededNumberDictionary::kNotFound) {
3388       PropertyDetails details = dictionary->DetailsAt(entry);
3389       if (details.type() == ACCESSOR_CONSTANT) {
3390         *found = true;
3391         Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3392         return SetElementWithCallback(object, structure, index, value, js_proto,
3393                                       language_mode);
3394       }
3395     }
3396   }
3397   *found = false;
3398   return isolate->factory()->the_hole_value();
3399 }
3400
3401
3402 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3403   // Only supports adding slack to owned descriptors.
3404   DCHECK(map->owns_descriptors());
3405
3406   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3407   int old_size = map->NumberOfOwnDescriptors();
3408   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3409
3410   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3411       descriptors, old_size, slack);
3412
3413   DisallowHeapAllocation no_allocation;
3414   // The descriptors are still the same, so keep the layout descriptor.
3415   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
3416
3417   if (old_size == 0) {
3418     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3419     return;
3420   }
3421
3422   // If the source descriptors had an enum cache we copy it. This ensures
3423   // that the maps to which we push the new descriptor array back can rely
3424   // on a cache always being available once it is set. If the map has more
3425   // enumerated descriptors than available in the original cache, the cache
3426   // will be lazily replaced by the extended cache when needed.
3427   if (descriptors->HasEnumCache()) {
3428     new_descriptors->CopyEnumCacheFrom(*descriptors);
3429   }
3430
3431   // Replace descriptors by new_descriptors in all maps that share it.
3432   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3433
3434   Map* walk_map;
3435   for (Object* current = map->GetBackPointer();
3436        !current->IsUndefined();
3437        current = walk_map->GetBackPointer()) {
3438     walk_map = Map::cast(current);
3439     if (walk_map->instance_descriptors() != *descriptors) break;
3440     walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3441   }
3442
3443   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3444 }
3445
3446
3447 template<class T>
3448 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3449                                  Handle<typename T::Array> array,
3450                                  int valid_descriptors) {
3451   int nof_callbacks = callbacks->length();
3452
3453   Isolate* isolate = array->GetIsolate();
3454   // Ensure the keys are unique names before writing them into the
3455   // instance descriptor. Since it may cause a GC, it has to be done before we
3456   // temporarily put the heap in an invalid state while appending descriptors.
3457   for (int i = 0; i < nof_callbacks; ++i) {
3458     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3459     if (entry->name()->IsUniqueName()) continue;
3460     Handle<String> key =
3461         isolate->factory()->InternalizeString(
3462             Handle<String>(String::cast(entry->name())));
3463     entry->set_name(*key);
3464   }
3465
3466   // Fill in new callback descriptors.  Process the callbacks from
3467   // back to front so that the last callback with a given name takes
3468   // precedence over previously added callbacks with that name.
3469   for (int i = nof_callbacks - 1; i >= 0; i--) {
3470     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3471     Handle<Name> key(Name::cast(entry->name()));
3472     // Check if a descriptor with this name already exists before writing.
3473     if (!T::Contains(key, entry, valid_descriptors, array)) {
3474       T::Insert(key, entry, valid_descriptors, array);
3475       valid_descriptors++;
3476     }
3477   }
3478
3479   return valid_descriptors;
3480 }
3481
3482 struct DescriptorArrayAppender {
3483   typedef DescriptorArray Array;
3484   static bool Contains(Handle<Name> key,
3485                        Handle<AccessorInfo> entry,
3486                        int valid_descriptors,
3487                        Handle<DescriptorArray> array) {
3488     DisallowHeapAllocation no_gc;
3489     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3490   }
3491   static void Insert(Handle<Name> key,
3492                      Handle<AccessorInfo> entry,
3493                      int valid_descriptors,
3494                      Handle<DescriptorArray> array) {
3495     DisallowHeapAllocation no_gc;
3496     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
3497     array->Append(&desc);
3498   }
3499 };
3500
3501
3502 struct FixedArrayAppender {
3503   typedef FixedArray Array;
3504   static bool Contains(Handle<Name> key,
3505                        Handle<AccessorInfo> entry,
3506                        int valid_descriptors,
3507                        Handle<FixedArray> array) {
3508     for (int i = 0; i < valid_descriptors; i++) {
3509       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3510     }
3511     return false;
3512   }
3513   static void Insert(Handle<Name> key,
3514                      Handle<AccessorInfo> entry,
3515                      int valid_descriptors,
3516                      Handle<FixedArray> array) {
3517     DisallowHeapAllocation no_gc;
3518     array->set(valid_descriptors, *entry);
3519   }
3520 };
3521
3522
3523 void Map::AppendCallbackDescriptors(Handle<Map> map,
3524                                     Handle<Object> descriptors) {
3525   int nof = map->NumberOfOwnDescriptors();
3526   Handle<DescriptorArray> array(map->instance_descriptors());
3527   NeanderArray callbacks(descriptors);
3528   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3529   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3530   map->SetNumberOfOwnDescriptors(nof);
3531 }
3532
3533
3534 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3535                                Handle<FixedArray> array,
3536                                int valid_descriptors) {
3537   NeanderArray callbacks(descriptors);
3538   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3539   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3540                                                    array,
3541                                                    valid_descriptors);
3542 }
3543
3544
3545 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3546   DCHECK(!map.is_null());
3547   for (int i = 0; i < maps->length(); ++i) {
3548     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3549   }
3550   return false;
3551 }
3552
3553
3554 template <class T>
3555 static Handle<T> MaybeNull(T* p) {
3556   if (p == NULL) return Handle<T>::null();
3557   return Handle<T>(p);
3558 }
3559
3560
3561 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3562   ElementsKind kind = elements_kind();
3563   Handle<Map> transitioned_map = Handle<Map>::null();
3564   Handle<Map> current_map(this);
3565   bool packed = IsFastPackedElementsKind(kind);
3566   if (IsTransitionableFastElementsKind(kind)) {
3567     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3568       kind = GetNextMoreGeneralFastElementsKind(kind, false);
3569       Handle<Map> maybe_transitioned_map =
3570           MaybeNull(current_map->LookupElementsTransitionMap(kind));
3571       if (maybe_transitioned_map.is_null()) break;
3572       if (ContainsMap(candidates, maybe_transitioned_map) &&
3573           (packed || !IsFastPackedElementsKind(kind))) {
3574         transitioned_map = maybe_transitioned_map;
3575         if (!IsFastPackedElementsKind(kind)) packed = false;
3576       }
3577       current_map = maybe_transitioned_map;
3578     }
3579   }
3580   return transitioned_map;
3581 }
3582
3583
3584 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3585   Map* current_map = map;
3586   int target_kind =
3587       IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3588       ? to_kind
3589       : TERMINAL_FAST_ELEMENTS_KIND;
3590
3591   // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3592   // allows to change elements from arbitrary kind to any ExternalArray
3593   // elements kind. Satisfy its requirements, checking whether we already
3594   // have the cached transition.
3595   if (IsExternalArrayElementsKind(to_kind) &&
3596       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3597     if (map->HasElementsTransition()) {
3598         Map* next_map = map->elements_transition_map();
3599         if (next_map->elements_kind() == to_kind) return next_map;
3600     }
3601     return map;
3602   }
3603
3604   ElementsKind kind = map->elements_kind();
3605   while (kind != target_kind) {
3606     kind = GetNextTransitionElementsKind(kind);
3607     if (!current_map->HasElementsTransition()) return current_map;
3608     current_map = current_map->elements_transition_map();
3609   }
3610
3611   if (to_kind != kind && current_map->HasElementsTransition()) {
3612     DCHECK(to_kind == DICTIONARY_ELEMENTS);
3613     Map* next_map = current_map->elements_transition_map();
3614     if (next_map->elements_kind() == to_kind) return next_map;
3615   }
3616
3617   DCHECK(current_map->elements_kind() == target_kind);
3618   return current_map;
3619 }
3620
3621
3622 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3623   Map* to_map = FindClosestElementsTransition(this, to_kind);
3624   if (to_map->elements_kind() == to_kind) return to_map;
3625   return NULL;
3626 }
3627
3628
3629 bool Map::IsMapInArrayPrototypeChain() {
3630   Isolate* isolate = GetIsolate();
3631   if (isolate->initial_array_prototype()->map() == this) {
3632     return true;
3633   }
3634
3635   if (isolate->initial_object_prototype()->map() == this) {
3636     return true;
3637   }
3638
3639   return false;
3640 }
3641
3642
3643 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
3644   Isolate* isolate = map->GetIsolate();
3645   if (map->code_cache()->IsFixedArray()) {
3646     return isolate->factory()->NewWeakCell(map);
3647   }
3648   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
3649   if (code_cache->weak_cell_cache()->IsWeakCell()) {
3650     return Handle<WeakCell>(WeakCell::cast(code_cache->weak_cell_cache()));
3651   }
3652   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
3653   code_cache->set_weak_cell_cache(*weak_cell);
3654   return weak_cell;
3655 }
3656
3657
3658 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3659                                                  ElementsKind to_kind) {
3660   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3661
3662   Handle<Map> current_map = map;
3663
3664   ElementsKind kind = map->elements_kind();
3665   TransitionFlag flag;
3666   if (map->is_prototype_map()) {
3667     flag = OMIT_TRANSITION;
3668   } else {
3669     flag = INSERT_TRANSITION;
3670     while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3671       kind = GetNextTransitionElementsKind(kind);
3672       current_map = Map::CopyAsElementsKind(current_map, kind, flag);
3673     }
3674   }
3675
3676   // In case we are exiting the fast elements kind system, just add the map in
3677   // the end.
3678   if (kind != to_kind) {
3679     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
3680   }
3681
3682   DCHECK(current_map->elements_kind() == to_kind);
3683   return current_map;
3684 }
3685
3686
3687 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3688                                       ElementsKind to_kind) {
3689   ElementsKind from_kind = map->elements_kind();
3690   if (from_kind == to_kind) return map;
3691
3692   Isolate* isolate = map->GetIsolate();
3693   Context* native_context = isolate->context()->native_context();
3694   Object* maybe_array_maps = native_context->js_array_maps();
3695   if (maybe_array_maps->IsFixedArray()) {
3696     DisallowHeapAllocation no_gc;
3697     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3698     if (array_maps->get(from_kind) == *map) {
3699       Object* maybe_transitioned_map = array_maps->get(to_kind);
3700       if (maybe_transitioned_map->IsMap()) {
3701         return handle(Map::cast(maybe_transitioned_map));
3702       }
3703     }
3704   }
3705
3706   return TransitionElementsToSlow(map, to_kind);
3707 }
3708
3709
3710 Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
3711                                           ElementsKind to_kind) {
3712   ElementsKind from_kind = map->elements_kind();
3713
3714   if (from_kind == to_kind) {
3715     return map;
3716   }
3717
3718   bool allow_store_transition =
3719       // Only remember the map transition if there is not an already existing
3720       // non-matching element transition.
3721       !map->IsUndefined() && !map->is_dictionary_map() &&
3722       IsTransitionElementsKind(from_kind);
3723
3724   // Only store fast element maps in ascending generality.
3725   if (IsFastElementsKind(to_kind)) {
3726     allow_store_transition &=
3727         IsTransitionableFastElementsKind(from_kind) &&
3728         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3729   }
3730
3731   if (!allow_store_transition) {
3732     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3733   }
3734
3735   return Map::AsElementsKind(map, to_kind);
3736 }
3737
3738
3739 // static
3740 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3741   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3742
3743   if (closest_map->elements_kind() == kind) {
3744     return closest_map;
3745   }
3746
3747   return AddMissingElementsTransitions(closest_map, kind);
3748 }
3749
3750
3751 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3752                                                ElementsKind to_kind) {
3753   Handle<Map> map(object->map());
3754   return Map::TransitionElementsTo(map, to_kind);
3755 }
3756
3757
3758 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3759                                             Handle<Name> name) {
3760   Isolate* isolate = proxy->GetIsolate();
3761
3762   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3763   if (name->IsSymbol()) return maybe(false);
3764
3765   Handle<Object> args[] = { name };
3766   Handle<Object> result;
3767   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3768       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3769                                 arraysize(args), args),
3770       Maybe<bool>());
3771
3772   return maybe(result->BooleanValue());
3773 }
3774
3775
3776 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3777     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3778     Handle<Object> value, LanguageMode language_mode) {
3779   Isolate* isolate = proxy->GetIsolate();
3780
3781   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3782   if (name->IsSymbol()) return value;
3783
3784   Handle<Object> args[] = { receiver, name, value };
3785   RETURN_ON_EXCEPTION(
3786       isolate,
3787       CallTrap(proxy,
3788                "set",
3789                isolate->derived_set_trap(),
3790                arraysize(args),
3791                args),
3792       Object);
3793
3794   return value;
3795 }
3796
3797
3798 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3799     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3800     Handle<Object> value, LanguageMode language_mode, bool* done) {
3801   Isolate* isolate = proxy->GetIsolate();
3802   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3803
3804   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3805   if (name->IsSymbol()) {
3806     *done = false;
3807     return isolate->factory()->the_hole_value();
3808   }
3809
3810   *done = true;  // except where redefined...
3811   Handle<Object> args[] = { name };
3812   Handle<Object> result;
3813   ASSIGN_RETURN_ON_EXCEPTION(
3814       isolate, result,
3815       CallTrap(proxy,
3816                "getPropertyDescriptor",
3817                Handle<Object>(),
3818                arraysize(args),
3819                args),
3820       Object);
3821
3822   if (result->IsUndefined()) {
3823     *done = false;
3824     return isolate->factory()->the_hole_value();
3825   }
3826
3827   // Emulate [[GetProperty]] semantics for proxies.
3828   Handle<Object> argv[] = { result };
3829   Handle<Object> desc;
3830   ASSIGN_RETURN_ON_EXCEPTION(
3831       isolate, desc,
3832       Execution::Call(isolate,
3833                       isolate->to_complete_property_descriptor(),
3834                       result,
3835                       arraysize(argv),
3836                       argv),
3837       Object);
3838
3839   // [[GetProperty]] requires to check that all properties are configurable.
3840   Handle<String> configurable_name =
3841       isolate->factory()->InternalizeOneByteString(
3842           STATIC_CHAR_VECTOR("configurable_"));
3843   Handle<Object> configurable =
3844       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3845   DCHECK(configurable->IsBoolean());
3846   if (configurable->IsFalse()) {
3847     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3848         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3849     Handle<Object> args[] = { handler, trap, name };
3850     THROW_NEW_ERROR(isolate, NewTypeError("proxy_prop_not_configurable",
3851                                           HandleVector(args, arraysize(args))),
3852                     Object);
3853   }
3854   DCHECK(configurable->IsTrue());
3855
3856   // Check for DataDescriptor.
3857   Handle<String> hasWritable_name =
3858       isolate->factory()->InternalizeOneByteString(
3859           STATIC_CHAR_VECTOR("hasWritable_"));
3860   Handle<Object> hasWritable =
3861       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3862   DCHECK(hasWritable->IsBoolean());
3863   if (hasWritable->IsTrue()) {
3864     Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3865         STATIC_CHAR_VECTOR("writable_"));
3866     Handle<Object> writable =
3867         Object::GetProperty(desc, writable_name).ToHandleChecked();
3868     DCHECK(writable->IsBoolean());
3869     *done = writable->IsFalse();
3870     if (!*done) return isolate->factory()->the_hole_value();
3871     return WriteToReadOnlyProperty(isolate, receiver, name, value,
3872                                    language_mode);
3873   }
3874
3875   // We have an AccessorDescriptor.
3876   Handle<String> set_name =
3877       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3878   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3879   if (!setter->IsUndefined()) {
3880     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3881     return SetPropertyWithDefinedSetter(
3882         receiver, Handle<JSReceiver>::cast(setter), value);
3883   }
3884
3885   if (is_sloppy(language_mode)) return value;
3886   Handle<Object> args2[] = { name, proxy };
3887   THROW_NEW_ERROR(isolate, NewTypeError("no_setter_in_callback",
3888                                         HandleVector(args2, arraysize(args2))),
3889                   Object);
3890 }
3891
3892
3893 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3894     Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) {
3895   Isolate* isolate = proxy->GetIsolate();
3896
3897   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3898   if (name->IsSymbol()) return isolate->factory()->false_value();
3899
3900   Handle<Object> args[] = { name };
3901   Handle<Object> result;
3902   ASSIGN_RETURN_ON_EXCEPTION(
3903       isolate, result,
3904       CallTrap(proxy,
3905                "delete",
3906                Handle<Object>(),
3907                arraysize(args),
3908                args),
3909       Object);
3910
3911   bool result_bool = result->BooleanValue();
3912   if (is_strict(language_mode) && !result_bool) {
3913     Handle<Object> handler(proxy->handler(), isolate);
3914     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3915         STATIC_CHAR_VECTOR("delete"));
3916     Handle<Object> args[] = { handler, trap_name };
3917     THROW_NEW_ERROR(isolate, NewTypeError("handler_failed",
3918                                           HandleVector(args, arraysize(args))),
3919                     Object);
3920   }
3921   return isolate->factory()->ToBoolean(result_bool);
3922 }
3923
3924
3925 MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
3926     Handle<JSProxy> proxy, uint32_t index, LanguageMode language_mode) {
3927   Isolate* isolate = proxy->GetIsolate();
3928   Handle<String> name = isolate->factory()->Uint32ToString(index);
3929   return JSProxy::DeletePropertyWithHandler(proxy, name, language_mode);
3930 }
3931
3932
3933 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3934     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3935   Isolate* isolate = proxy->GetIsolate();
3936   HandleScope scope(isolate);
3937
3938   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3939   if (name->IsSymbol()) return maybe(ABSENT);
3940
3941   Handle<Object> args[] = { name };
3942   Handle<Object> result;
3943   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3944       isolate, result,
3945       proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(),
3946                       arraysize(args), args),
3947       Maybe<PropertyAttributes>());
3948
3949   if (result->IsUndefined()) return maybe(ABSENT);
3950
3951   Handle<Object> argv[] = { result };
3952   Handle<Object> desc;
3953   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3954       isolate, desc,
3955       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3956                       result, arraysize(argv), argv),
3957       Maybe<PropertyAttributes>());
3958
3959   // Convert result to PropertyAttributes.
3960   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3961       STATIC_CHAR_VECTOR("enumerable_"));
3962   Handle<Object> enumerable;
3963   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3964                                    Object::GetProperty(desc, enum_n),
3965                                    Maybe<PropertyAttributes>());
3966   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3967       STATIC_CHAR_VECTOR("configurable_"));
3968   Handle<Object> configurable;
3969   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3970                                    Object::GetProperty(desc, conf_n),
3971                                    Maybe<PropertyAttributes>());
3972   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3973       STATIC_CHAR_VECTOR("writable_"));
3974   Handle<Object> writable;
3975   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3976                                    Object::GetProperty(desc, writ_n),
3977                                    Maybe<PropertyAttributes>());
3978   if (!writable->BooleanValue()) {
3979     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3980         STATIC_CHAR_VECTOR("set_"));
3981     Handle<Object> setter;
3982     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
3983                                      Object::GetProperty(desc, set_n),
3984                                      Maybe<PropertyAttributes>());
3985     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3986   }
3987
3988   if (configurable->IsFalse()) {
3989     Handle<Object> handler(proxy->handler(), isolate);
3990     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3991         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3992     Handle<Object> args[] = { handler, trap, name };
3993     Handle<Object> error;
3994     MaybeHandle<Object> maybe_error = isolate->factory()->NewTypeError(
3995         "proxy_prop_not_configurable", HandleVector(args, arraysize(args)));
3996     if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
3997     return maybe(NONE);
3998   }
3999
4000   int attributes = NONE;
4001   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
4002   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
4003   if (!writable->BooleanValue()) attributes |= READ_ONLY;
4004   return maybe(static_cast<PropertyAttributes>(attributes));
4005 }
4006
4007
4008 Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler(
4009     Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
4010   Isolate* isolate = proxy->GetIsolate();
4011   Handle<String> name = isolate->factory()->Uint32ToString(index);
4012   return GetPropertyAttributesWithHandler(proxy, receiver, name);
4013 }
4014
4015
4016 void JSProxy::Fix(Handle<JSProxy> proxy) {
4017   Isolate* isolate = proxy->GetIsolate();
4018
4019   // Save identity hash.
4020   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4021
4022   if (proxy->IsJSFunctionProxy()) {
4023     isolate->factory()->BecomeJSFunction(proxy);
4024     // Code will be set on the JavaScript side.
4025   } else {
4026     isolate->factory()->BecomeJSObject(proxy);
4027   }
4028   DCHECK(proxy->IsJSObject());
4029
4030   // Inherit identity, if it was present.
4031   if (hash->IsSmi()) {
4032     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
4033                               Handle<Smi>::cast(hash));
4034   }
4035 }
4036
4037
4038 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
4039                                       const char* name,
4040                                       Handle<Object> derived,
4041                                       int argc,
4042                                       Handle<Object> argv[]) {
4043   Isolate* isolate = proxy->GetIsolate();
4044   Handle<Object> handler(proxy->handler(), isolate);
4045
4046   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
4047   Handle<Object> trap;
4048   ASSIGN_RETURN_ON_EXCEPTION(
4049       isolate, trap,
4050       Object::GetPropertyOrElement(handler, trap_name),
4051       Object);
4052
4053   if (trap->IsUndefined()) {
4054     if (derived.is_null()) {
4055       Handle<Object> args[] = { handler, trap_name };
4056       THROW_NEW_ERROR(isolate,
4057                       NewTypeError("handler_trap_missing",
4058                                    HandleVector(args, arraysize(args))),
4059                       Object);
4060     }
4061     trap = Handle<Object>(derived);
4062   }
4063
4064   return Execution::Call(isolate, trap, handler, argc, argv);
4065 }
4066
4067
4068 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
4069   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
4070   ElementsKind obj_kind = object->map()->elements_kind();
4071   ElementsKind map_kind = map->elements_kind();
4072   if (map_kind != obj_kind) {
4073     ElementsKind to_kind = map_kind;
4074     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
4075         IsDictionaryElementsKind(obj_kind)) {
4076       to_kind = obj_kind;
4077     }
4078     if (IsDictionaryElementsKind(to_kind)) {
4079       NormalizeElements(object);
4080     } else {
4081       TransitionElementsKind(object, to_kind);
4082     }
4083     map = Map::AsElementsKind(map, to_kind);
4084   }
4085   JSObject::MigrateToMap(object, map);
4086 }
4087
4088
4089 void JSObject::MigrateInstance(Handle<JSObject> object) {
4090   Handle<Map> original_map(object->map());
4091   Handle<Map> map = Map::Update(original_map);
4092   map->set_migration_target(true);
4093   MigrateToMap(object, map);
4094   if (FLAG_trace_migration) {
4095     object->PrintInstanceMigration(stdout, *original_map, *map);
4096   }
4097 }
4098
4099
4100 // static
4101 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
4102   Isolate* isolate = object->GetIsolate();
4103   DisallowDeoptimization no_deoptimization(isolate);
4104   Handle<Map> original_map(object->map(), isolate);
4105   Handle<Map> new_map;
4106   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
4107     return false;
4108   }
4109   JSObject::MigrateToMap(object, new_map);
4110   if (FLAG_trace_migration) {
4111     object->PrintInstanceMigration(stdout, *original_map, object->map());
4112   }
4113   return true;
4114 }
4115
4116
4117 void JSObject::WriteToField(int descriptor, Object* value) {
4118   DisallowHeapAllocation no_gc;
4119
4120   DescriptorArray* desc = map()->instance_descriptors();
4121   PropertyDetails details = desc->GetDetails(descriptor);
4122
4123   DCHECK(details.type() == DATA);
4124
4125   FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
4126   if (details.representation().IsDouble()) {
4127     // Nothing more to be done.
4128     if (value->IsUninitialized()) return;
4129     if (IsUnboxedDoubleField(index)) {
4130       RawFastDoublePropertyAtPut(index, value->Number());
4131     } else {
4132       HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
4133       DCHECK(box->IsMutableHeapNumber());
4134       box->set_value(value->Number());
4135     }
4136   } else {
4137     RawFastPropertyAtPut(index, value);
4138   }
4139 }
4140
4141
4142 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4143                            Handle<Object> value,
4144                            PropertyAttributes attributes) {
4145   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4146   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
4147 #ifdef DEBUG
4148   uint32_t index;
4149   DCHECK(!object->IsJSProxy());
4150   DCHECK(!name->AsArrayIndex(&index));
4151   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4152   DCHECK(maybe.has_value);
4153   DCHECK(!it.IsFound());
4154   DCHECK(object->map()->is_extensible() ||
4155          it.isolate()->IsInternallyUsedPropertyName(name));
4156 #endif
4157   AddDataProperty(&it, value, attributes, STRICT,
4158                   CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4159 }
4160
4161
4162 // Reconfigures a property to a data property with attributes, even if it is not
4163 // reconfigurable.
4164 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4165     Handle<JSObject> object,
4166     Handle<Name> name,
4167     Handle<Object> value,
4168     PropertyAttributes attributes,
4169     ExecutableAccessorInfoHandling handling) {
4170   DCHECK(!value->IsTheHole());
4171   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4172   bool is_observed = object->map()->is_observed() &&
4173                      !it.isolate()->IsInternallyUsedPropertyName(name);
4174   for (; it.IsFound(); it.Next()) {
4175     switch (it.state()) {
4176       case LookupIterator::INTERCEPTOR:
4177       case LookupIterator::JSPROXY:
4178       case LookupIterator::NOT_FOUND:
4179       case LookupIterator::TRANSITION:
4180         UNREACHABLE();
4181
4182       case LookupIterator::ACCESS_CHECK:
4183         if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4184           return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4185         }
4186         break;
4187
4188       case LookupIterator::ACCESSOR: {
4189         PropertyDetails details = it.property_details();
4190         // Ensure the context isn't changed after calling into accessors.
4191         AssertNoContextChange ncc(it.isolate());
4192
4193         Handle<Object> accessors = it.GetAccessors();
4194
4195         // Special handling for ExecutableAccessorInfo, which behaves like a
4196         // data property.
4197         if (handling == DONT_FORCE_FIELD &&
4198             accessors->IsExecutableAccessorInfo()) {
4199           Handle<Object> result;
4200           ASSIGN_RETURN_ON_EXCEPTION(
4201               it.isolate(), result,
4202               JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
4203                                                 value, it.GetHolder<JSObject>(),
4204                                                 accessors, STRICT),
4205               Object);
4206           DCHECK(result->SameValue(*value));
4207
4208           if (details.attributes() == attributes) {
4209             return value;
4210           }
4211
4212           // Reconfigure the accessor if attributes mismatch.
4213           Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4214               it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4215           new_data->set_property_attributes(attributes);
4216           // By clearing the setter we don't have to introduce a lookup to
4217           // the setter, simply make it unavailable to reflect the
4218           // attributes.
4219           if (attributes & READ_ONLY) new_data->clear_setter();
4220           SetPropertyCallback(object, name, new_data, attributes);
4221           if (is_observed) {
4222             RETURN_ON_EXCEPTION(
4223                 it.isolate(),
4224                 EnqueueChangeRecord(object, "reconfigure", name,
4225                                     it.isolate()->factory()->the_hole_value()),
4226                 Object);
4227           }
4228           return value;
4229         }
4230
4231         it.ReconfigureDataProperty(value, attributes);
4232         value = it.WriteDataValue(value);
4233
4234         if (is_observed) {
4235           RETURN_ON_EXCEPTION(
4236               it.isolate(),
4237               EnqueueChangeRecord(object, "reconfigure", name,
4238                                   it.isolate()->factory()->the_hole_value()),
4239               Object);
4240         }
4241
4242         return value;
4243       }
4244
4245       case LookupIterator::DATA: {
4246         PropertyDetails details = it.property_details();
4247         Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4248         // Regular property update if the attributes match.
4249         if (details.attributes() == attributes) {
4250           return SetDataProperty(&it, value);
4251         }
4252         // Reconfigure the data property if the attributes mismatch.
4253         if (is_observed) old_value = it.GetDataValue();
4254
4255         it.ReconfigureDataProperty(value, attributes);
4256         value = it.WriteDataValue(value);
4257
4258         if (is_observed) {
4259           if (old_value->SameValue(*value)) {
4260             old_value = it.isolate()->factory()->the_hole_value();
4261           }
4262           RETURN_ON_EXCEPTION(
4263               it.isolate(),
4264               EnqueueChangeRecord(object, "reconfigure", name, old_value),
4265               Object);
4266         }
4267
4268         return value;
4269       }
4270     }
4271   }
4272
4273   return AddDataProperty(&it, value, attributes, STRICT,
4274                          CERTAINLY_NOT_STORE_FROM_KEYED);
4275 }
4276
4277
4278 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4279     Handle<JSObject> holder,
4280     Handle<Object> receiver,
4281     Handle<Name> name) {
4282   Isolate* isolate = holder->GetIsolate();
4283   HandleScope scope(isolate);
4284
4285   // Make sure that the top context does not change when doing
4286   // callbacks or interceptor calls.
4287   AssertNoContextChange ncc(isolate);
4288
4289   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4290   if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
4291     return maybe(ABSENT);
4292   }
4293   PropertyCallbackArguments args(
4294       isolate, interceptor->data(), *receiver, *holder);
4295   if (!interceptor->query()->IsUndefined()) {
4296     v8::GenericNamedPropertyQueryCallback query =
4297         v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
4298             interceptor->query());
4299     LOG(isolate,
4300         ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4301     v8::Handle<v8::Integer> result = args.Call(query, v8::Utils::ToLocal(name));
4302     if (!result.IsEmpty()) {
4303       DCHECK(result->IsInt32());
4304       return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4305     }
4306   } else if (!interceptor->getter()->IsUndefined()) {
4307     v8::GenericNamedPropertyGetterCallback getter =
4308         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
4309             interceptor->getter());
4310     LOG(isolate,
4311         ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4312     v8::Handle<v8::Value> result = args.Call(getter, v8::Utils::ToLocal(name));
4313     if (!result.IsEmpty()) return maybe(DONT_ENUM);
4314   }
4315
4316   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
4317   return maybe(ABSENT);
4318 }
4319
4320
4321 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
4322     Handle<JSReceiver> object, Handle<Name> name) {
4323   // Check whether the name is an array index.
4324   uint32_t index = 0;
4325   if (object->IsJSObject() && name->AsArrayIndex(&index)) {
4326     return GetOwnElementAttribute(object, index);
4327   }
4328   LookupIterator it(object, name, LookupIterator::HIDDEN);
4329   return GetPropertyAttributes(&it);
4330 }
4331
4332
4333 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4334     LookupIterator* it) {
4335   for (; it->IsFound(); it->Next()) {
4336     switch (it->state()) {
4337       case LookupIterator::NOT_FOUND:
4338       case LookupIterator::TRANSITION:
4339         UNREACHABLE();
4340       case LookupIterator::JSPROXY:
4341         return JSProxy::GetPropertyAttributesWithHandler(
4342             it->GetHolder<JSProxy>(), it->GetReceiver(), it->name());
4343       case LookupIterator::INTERCEPTOR: {
4344         Maybe<PropertyAttributes> result =
4345             JSObject::GetPropertyAttributesWithInterceptor(
4346                 it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
4347         if (!result.has_value) return result;
4348         if (result.value != ABSENT) return result;
4349         break;
4350       }
4351       case LookupIterator::ACCESS_CHECK:
4352         if (it->HasAccess(v8::ACCESS_HAS)) break;
4353         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4354       case LookupIterator::ACCESSOR:
4355       case LookupIterator::DATA:
4356         return maybe(it->property_details().attributes());
4357     }
4358   }
4359   return maybe(ABSENT);
4360 }
4361
4362
4363 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
4364     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4365     bool check_prototype) {
4366   Isolate* isolate = object->GetIsolate();
4367
4368   // Check access rights if needed.
4369   if (object->IsAccessCheckNeeded()) {
4370     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4371       return GetElementAttributesWithFailedAccessCheck(isolate, object,
4372                                                        receiver, index);
4373     }
4374   }
4375
4376   if (object->IsJSGlobalProxy()) {
4377     PrototypeIterator iter(isolate, object);
4378     if (iter.IsAtEnd()) return maybe(ABSENT);
4379     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4380     return JSObject::GetElementAttributeWithReceiver(
4381         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4382         index, check_prototype);
4383   }
4384
4385   // Check for lookup interceptor except when bootstrapping.
4386   if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4387     return JSObject::GetElementAttributeWithInterceptor(
4388         object, receiver, index, check_prototype);
4389   }
4390
4391   return GetElementAttributeWithoutInterceptor(
4392       object, receiver, index, check_prototype);
4393 }
4394
4395
4396 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
4397     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4398     bool check_prototype) {
4399   Isolate* isolate = object->GetIsolate();
4400   HandleScope scope(isolate);
4401
4402   // Make sure that the top context does not change when doing
4403   // callbacks or interceptor calls.
4404   AssertNoContextChange ncc(isolate);
4405
4406   Maybe<PropertyAttributes> from_interceptor =
4407       GetElementAttributeFromInterceptor(object, receiver, index);
4408   if (!from_interceptor.has_value) return Maybe<PropertyAttributes>();
4409   if (from_interceptor.value != ABSENT) return maybe(from_interceptor.value);
4410
4411   return GetElementAttributeWithoutInterceptor(object, receiver, index,
4412                                                check_prototype);
4413 }
4414
4415
4416 Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor(
4417     Handle<JSObject> object, Handle<Object> receiver, uint32_t index) {
4418   Isolate* isolate = object->GetIsolate();
4419   AssertNoContextChange ncc(isolate);
4420
4421   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4422   PropertyCallbackArguments args(
4423       isolate, interceptor->data(), *receiver, *object);
4424   if (!interceptor->query()->IsUndefined()) {
4425     v8::IndexedPropertyQueryCallback query =
4426         v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4427     LOG(isolate,
4428         ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4429     v8::Handle<v8::Integer> result = args.Call(query, index);
4430     if (!result.IsEmpty())
4431       return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4432   } else if (!interceptor->getter()->IsUndefined()) {
4433     v8::IndexedPropertyGetterCallback getter =
4434         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4435     LOG(isolate,
4436         ApiIndexedPropertyAccess(
4437             "interceptor-indexed-get-has", *object, index));
4438     v8::Handle<v8::Value> result = args.Call(getter, index);
4439     if (!result.IsEmpty()) return maybe(NONE);
4440   }
4441   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
4442   return maybe(ABSENT);
4443 }
4444
4445
4446 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor(
4447     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4448     bool check_prototype) {
4449   PropertyAttributes attr =
4450       object->GetElementsAccessor()->GetAttributes(object, index);
4451   if (attr != ABSENT) return maybe(attr);
4452
4453   // Handle [] on String objects.
4454   if (object->IsStringObjectWithCharacterAt(index)) {
4455     return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
4456   }
4457
4458   if (!check_prototype) return maybe(ABSENT);
4459
4460   PrototypeIterator iter(object->GetIsolate(), object);
4461   if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
4462     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4463     return JSProxy::GetElementAttributeWithHandler(
4464         Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4465         index);
4466   }
4467   if (iter.IsAtEnd()) return maybe(ABSENT);
4468   return GetElementAttributeWithReceiver(
4469       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4470       index, true);
4471 }
4472
4473
4474 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4475   Handle<FixedArray> array(
4476       isolate->factory()->NewFixedArray(kEntries, TENURED));
4477   return Handle<NormalizedMapCache>::cast(array);
4478 }
4479
4480
4481 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4482                                          PropertyNormalizationMode mode) {
4483   DisallowHeapAllocation no_gc;
4484   Object* value = FixedArray::get(GetIndex(fast_map));
4485   if (!value->IsMap() ||
4486       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4487     return MaybeHandle<Map>();
4488   }
4489   return handle(Map::cast(value));
4490 }
4491
4492
4493 void NormalizedMapCache::Set(Handle<Map> fast_map,
4494                              Handle<Map> normalized_map) {
4495   DisallowHeapAllocation no_gc;
4496   DCHECK(normalized_map->is_dictionary_map());
4497   FixedArray::set(GetIndex(fast_map), *normalized_map);
4498 }
4499
4500
4501 void NormalizedMapCache::Clear() {
4502   int entries = length();
4503   for (int i = 0; i != entries; i++) {
4504     set_undefined(i);
4505   }
4506 }
4507
4508
4509 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4510                                     Handle<Name> name,
4511                                     Handle<Code> code) {
4512   Handle<Map> map(object->map());
4513   Map::UpdateCodeCache(map, name, code);
4514 }
4515
4516
4517 void JSObject::NormalizeProperties(Handle<JSObject> object,
4518                                    PropertyNormalizationMode mode,
4519                                    int expected_additional_properties,
4520                                    const char* reason) {
4521   if (!object->HasFastProperties()) return;
4522
4523   Handle<Map> map(object->map());
4524   Handle<Map> new_map = Map::Normalize(map, mode, reason);
4525
4526   MigrateFastToSlow(object, new_map, expected_additional_properties);
4527 }
4528
4529
4530 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4531                                  Handle<Map> new_map,
4532                                  int expected_additional_properties) {
4533   // The global object is always normalized.
4534   DCHECK(!object->IsGlobalObject());
4535   // JSGlobalProxy must never be normalized
4536   DCHECK(!object->IsJSGlobalProxy());
4537
4538   Isolate* isolate = object->GetIsolate();
4539   HandleScope scope(isolate);
4540   Handle<Map> map(object->map());
4541
4542   // Allocate new content.
4543   int real_size = map->NumberOfOwnDescriptors();
4544   int property_count = real_size;
4545   if (expected_additional_properties > 0) {
4546     property_count += expected_additional_properties;
4547   } else {
4548     property_count += 2;  // Make space for two more properties.
4549   }
4550   Handle<NameDictionary> dictionary =
4551       NameDictionary::New(isolate, property_count);
4552
4553   Handle<DescriptorArray> descs(map->instance_descriptors());
4554   for (int i = 0; i < real_size; i++) {
4555     PropertyDetails details = descs->GetDetails(i);
4556     Handle<Name> key(descs->GetKey(i));
4557     switch (details.type()) {
4558       case DATA_CONSTANT: {
4559         Handle<Object> value(descs->GetConstant(i), isolate);
4560         PropertyDetails d(details.attributes(), DATA, i + 1);
4561         dictionary = NameDictionary::Add(dictionary, key, value, d);
4562         break;
4563       }
4564       case DATA: {
4565         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4566         Handle<Object> value;
4567         if (object->IsUnboxedDoubleField(index)) {
4568           double old_value = object->RawFastDoublePropertyAt(index);
4569           value = isolate->factory()->NewHeapNumber(old_value);
4570         } else {
4571           value = handle(object->RawFastPropertyAt(index), isolate);
4572           if (details.representation().IsDouble()) {
4573             DCHECK(value->IsMutableHeapNumber());
4574             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4575             value = isolate->factory()->NewHeapNumber(old->value());
4576           }
4577         }
4578         PropertyDetails d(details.attributes(), DATA, i + 1);
4579         dictionary = NameDictionary::Add(dictionary, key, value, d);
4580         break;
4581       }
4582       case ACCESSOR: {
4583         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4584         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
4585         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1);
4586         dictionary = NameDictionary::Add(dictionary, key, value, d);
4587         break;
4588       }
4589       case ACCESSOR_CONSTANT: {
4590         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4591         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1);
4592         dictionary = NameDictionary::Add(dictionary, key, value, d);
4593         break;
4594       }
4595     }
4596   }
4597
4598   // Copy the next enumeration index from instance descriptor.
4599   dictionary->SetNextEnumerationIndex(real_size + 1);
4600
4601   // From here on we cannot fail and we shouldn't GC anymore.
4602   DisallowHeapAllocation no_allocation;
4603
4604   // Resize the object in the heap if necessary.
4605   int new_instance_size = new_map->instance_size();
4606   int instance_size_delta = map->instance_size() - new_instance_size;
4607   DCHECK(instance_size_delta >= 0);
4608
4609   if (instance_size_delta > 0) {
4610     Heap* heap = isolate->heap();
4611     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4612                                instance_size_delta);
4613     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4614                           Heap::FROM_MUTATOR);
4615   }
4616
4617   // We are storing the new map using release store after creating a filler for
4618   // the left-over space to avoid races with the sweeper thread.
4619   object->synchronized_set_map(*new_map);
4620
4621   object->set_properties(*dictionary);
4622
4623   // Ensure that in-object space of slow-mode object does not contain random
4624   // garbage.
4625   int inobject_properties = new_map->inobject_properties();
4626   for (int i = 0; i < inobject_properties; i++) {
4627     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4628     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
4629   }
4630
4631   isolate->counters()->props_to_dictionary()->Increment();
4632
4633 #ifdef DEBUG
4634   if (FLAG_trace_normalization) {
4635     OFStream os(stdout);
4636     os << "Object properties have been normalized:\n";
4637     object->Print(os);
4638   }
4639 #endif
4640 }
4641
4642
4643 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4644                                  int unused_property_fields,
4645                                  const char* reason) {
4646   if (object->HasFastProperties()) return;
4647   DCHECK(!object->IsGlobalObject());
4648   Isolate* isolate = object->GetIsolate();
4649   Factory* factory = isolate->factory();
4650   Handle<NameDictionary> dictionary(object->property_dictionary());
4651
4652   // Make sure we preserve dictionary representation if there are too many
4653   // descriptors.
4654   int number_of_elements = dictionary->NumberOfElements();
4655   if (number_of_elements > kMaxNumberOfDescriptors) return;
4656
4657   Handle<FixedArray> iteration_order;
4658   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4659     iteration_order =
4660         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4661   } else {
4662     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
4663   }
4664
4665   int instance_descriptor_length = iteration_order->length();
4666   int number_of_fields = 0;
4667
4668   // Compute the length of the instance descriptor.
4669   for (int i = 0; i < instance_descriptor_length; i++) {
4670     int index = Smi::cast(iteration_order->get(i))->value();
4671     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
4672
4673     Object* value = dictionary->ValueAt(index);
4674     PropertyType type = dictionary->DetailsAt(index).type();
4675     if (type == DATA && !value->IsJSFunction()) {
4676       number_of_fields += 1;
4677     }
4678   }
4679
4680   int inobject_props = object->map()->inobject_properties();
4681
4682   // Allocate new map.
4683   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4684   new_map->set_dictionary_map(false);
4685
4686 #if TRACE_MAPS
4687   if (FLAG_trace_maps) {
4688     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
4689            reinterpret_cast<void*>(object->map()),
4690            reinterpret_cast<void*>(*new_map), reason);
4691   }
4692 #endif
4693
4694   if (instance_descriptor_length == 0) {
4695     DisallowHeapAllocation no_gc;
4696     DCHECK_LE(unused_property_fields, inobject_props);
4697     // Transform the object.
4698     new_map->set_unused_property_fields(inobject_props);
4699     object->synchronized_set_map(*new_map);
4700     object->set_properties(isolate->heap()->empty_fixed_array());
4701     // Check that it really works.
4702     DCHECK(object->HasFastProperties());
4703     return;
4704   }
4705
4706   // Allocate the instance descriptor.
4707   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4708       isolate, instance_descriptor_length);
4709
4710   int number_of_allocated_fields =
4711       number_of_fields + unused_property_fields - inobject_props;
4712   if (number_of_allocated_fields < 0) {
4713     // There is enough inobject space for all fields (including unused).
4714     number_of_allocated_fields = 0;
4715     unused_property_fields = inobject_props - number_of_fields;
4716   }
4717
4718   // Allocate the fixed array for the fields.
4719   Handle<FixedArray> fields = factory->NewFixedArray(
4720       number_of_allocated_fields);
4721
4722   // Fill in the instance descriptor and the fields.
4723   int current_offset = 0;
4724   for (int i = 0; i < instance_descriptor_length; i++) {
4725     int index = Smi::cast(iteration_order->get(i))->value();
4726     Object* k = dictionary->KeyAt(index);
4727     DCHECK(dictionary->IsKey(k));
4728
4729     Object* value = dictionary->ValueAt(index);
4730     Handle<Name> key;
4731     if (k->IsSymbol()) {
4732       key = handle(Symbol::cast(k));
4733     } else {
4734       // Ensure the key is a unique name before writing into the
4735       // instance descriptor.
4736       key = factory->InternalizeString(handle(String::cast(k)));
4737     }
4738
4739     PropertyDetails details = dictionary->DetailsAt(index);
4740     int enumeration_index = details.dictionary_index();
4741     PropertyType type = details.type();
4742
4743     if (value->IsJSFunction()) {
4744       DataConstantDescriptor d(key, handle(value, isolate),
4745                                details.attributes());
4746       descriptors->Set(enumeration_index - 1, &d);
4747     } else if (type == DATA) {
4748       if (current_offset < inobject_props) {
4749         object->InObjectPropertyAtPut(current_offset, value,
4750                                       UPDATE_WRITE_BARRIER);
4751       } else {
4752         int offset = current_offset - inobject_props;
4753         fields->set(offset, value);
4754       }
4755       DataDescriptor d(key, current_offset, details.attributes(),
4756                        // TODO(verwaest): value->OptimalRepresentation();
4757                        Representation::Tagged());
4758       current_offset += d.GetDetails().field_width_in_words();
4759       descriptors->Set(enumeration_index - 1, &d);
4760     } else if (type == ACCESSOR_CONSTANT) {
4761       AccessorConstantDescriptor d(key, handle(value, isolate),
4762                                    details.attributes());
4763       descriptors->Set(enumeration_index - 1, &d);
4764     } else {
4765       UNREACHABLE();
4766     }
4767   }
4768   DCHECK(current_offset == number_of_fields);
4769
4770   descriptors->Sort();
4771
4772   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
4773       new_map, descriptors, descriptors->number_of_descriptors());
4774
4775   DisallowHeapAllocation no_gc;
4776   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
4777   new_map->set_unused_property_fields(unused_property_fields);
4778
4779   // Transform the object.
4780   object->synchronized_set_map(*new_map);
4781
4782   object->set_properties(*fields);
4783   DCHECK(object->IsJSObject());
4784
4785   // Check that it really works.
4786   DCHECK(object->HasFastProperties());
4787 }
4788
4789
4790 void JSObject::ResetElements(Handle<JSObject> object) {
4791   Isolate* isolate = object->GetIsolate();
4792   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4793   if (object->map()->has_dictionary_elements()) {
4794     Handle<SeededNumberDictionary> new_elements =
4795         SeededNumberDictionary::New(isolate, 0);
4796     object->set_elements(*new_elements);
4797   } else {
4798     object->set_elements(object->map()->GetInitialElements());
4799   }
4800 }
4801
4802
4803 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4804     Handle<FixedArrayBase> array,
4805     int length,
4806     Handle<SeededNumberDictionary> dictionary) {
4807   Isolate* isolate = array->GetIsolate();
4808   Factory* factory = isolate->factory();
4809   bool has_double_elements = array->IsFixedDoubleArray();
4810   for (int i = 0; i < length; i++) {
4811     Handle<Object> value;
4812     if (has_double_elements) {
4813       Handle<FixedDoubleArray> double_array =
4814           Handle<FixedDoubleArray>::cast(array);
4815       if (double_array->is_the_hole(i)) {
4816         value = factory->the_hole_value();
4817       } else {
4818         value = factory->NewHeapNumber(double_array->get_scalar(i));
4819       }
4820     } else {
4821       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4822     }
4823     if (!value->IsTheHole()) {
4824       PropertyDetails details(NONE, DATA, 0);
4825       dictionary =
4826           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4827     }
4828   }
4829   return dictionary;
4830 }
4831
4832
4833 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4834     Handle<JSObject> object) {
4835   DCHECK(!object->HasExternalArrayElements() &&
4836          !object->HasFixedTypedArrayElements());
4837   Isolate* isolate = object->GetIsolate();
4838
4839   // Find the backing store.
4840   Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4841   bool is_arguments =
4842       (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4843   if (is_arguments) {
4844     array = handle(FixedArrayBase::cast(
4845         Handle<FixedArray>::cast(array)->get(1)));
4846   }
4847   if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4848
4849   DCHECK(object->HasFastSmiOrObjectElements() ||
4850          object->HasFastDoubleElements() ||
4851          object->HasFastArgumentsElements());
4852   // Compute the effective length and allocate a new backing store.
4853   int length = object->IsJSArray()
4854       ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4855       : array->length();
4856   int old_capacity = 0;
4857   int used_elements = 0;
4858   object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4859   Handle<SeededNumberDictionary> dictionary =
4860       SeededNumberDictionary::New(isolate, used_elements);
4861
4862   dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4863
4864   // Switch to using the dictionary as the backing storage for elements.
4865   if (is_arguments) {
4866     FixedArray::cast(object->elements())->set(1, *dictionary);
4867   } else {
4868     // Set the new map first to satify the elements type assert in
4869     // set_elements().
4870     Handle<Map> new_map =
4871         JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4872
4873     JSObject::MigrateToMap(object, new_map);
4874     object->set_elements(*dictionary);
4875   }
4876
4877   isolate->counters()->elements_to_dictionary()->Increment();
4878
4879 #ifdef DEBUG
4880   if (FLAG_trace_normalization) {
4881     OFStream os(stdout);
4882     os << "Object elements have been normalized:\n";
4883     object->Print(os);
4884   }
4885 #endif
4886
4887   DCHECK(object->HasDictionaryElements() ||
4888          object->HasDictionaryArgumentsElements());
4889   return dictionary;
4890 }
4891
4892
4893 static Smi* GenerateIdentityHash(Isolate* isolate) {
4894   int hash_value;
4895   int attempts = 0;
4896   do {
4897     // Generate a random 32-bit hash value but limit range to fit
4898     // within a smi.
4899     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4900     attempts++;
4901   } while (hash_value == 0 && attempts < 30);
4902   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4903
4904   return Smi::FromInt(hash_value);
4905 }
4906
4907
4908 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4909   DCHECK(!object->IsJSGlobalProxy());
4910   Isolate* isolate = object->GetIsolate();
4911   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4912 }
4913
4914
4915 template<typename ProxyType>
4916 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4917   Isolate* isolate = proxy->GetIsolate();
4918
4919   Handle<Object> maybe_hash(proxy->hash(), isolate);
4920   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4921
4922   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4923   proxy->set_hash(*hash);
4924   return hash;
4925 }
4926
4927
4928 Object* JSObject::GetIdentityHash() {
4929   DisallowHeapAllocation no_gc;
4930   Isolate* isolate = GetIsolate();
4931   if (IsJSGlobalProxy()) {
4932     return JSGlobalProxy::cast(this)->hash();
4933   }
4934   Object* stored_value =
4935       GetHiddenProperty(isolate->factory()->identity_hash_string());
4936   return stored_value->IsSmi()
4937       ? stored_value
4938       : isolate->heap()->undefined_value();
4939 }
4940
4941
4942 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4943   if (object->IsJSGlobalProxy()) {
4944     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4945   }
4946
4947   Isolate* isolate = object->GetIsolate();
4948
4949   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4950   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4951
4952   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4953   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4954   return hash;
4955 }
4956
4957
4958 Object* JSProxy::GetIdentityHash() {
4959   return this->hash();
4960 }
4961
4962
4963 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4964   return GetOrCreateIdentityHashHelper(proxy);
4965 }
4966
4967
4968 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4969   DisallowHeapAllocation no_gc;
4970   DCHECK(key->IsUniqueName());
4971   if (IsJSGlobalProxy()) {
4972     // JSGlobalProxies store their hash internally.
4973     DCHECK(*key != GetHeap()->identity_hash_string());
4974     // For a proxy, use the prototype as target object.
4975     PrototypeIterator iter(GetIsolate(), this);
4976     // If the proxy is detached, return undefined.
4977     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4978     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4979     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4980   }
4981   DCHECK(!IsJSGlobalProxy());
4982   Object* inline_value = GetHiddenPropertiesHashTable();
4983
4984   if (inline_value->IsSmi()) {
4985     // Handle inline-stored identity hash.
4986     if (*key == GetHeap()->identity_hash_string()) {
4987       return inline_value;
4988     } else {
4989       return GetHeap()->the_hole_value();
4990     }
4991   }
4992
4993   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4994
4995   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4996   Object* entry = hashtable->Lookup(key);
4997   return entry;
4998 }
4999
5000
5001 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5002                                            Handle<Name> key,
5003                                            Handle<Object> value) {
5004   Isolate* isolate = object->GetIsolate();
5005
5006   DCHECK(key->IsUniqueName());
5007   if (object->IsJSGlobalProxy()) {
5008     // JSGlobalProxies store their hash internally.
5009     DCHECK(*key != *isolate->factory()->identity_hash_string());
5010     // For a proxy, use the prototype as target object.
5011     PrototypeIterator iter(isolate, object);
5012     // If the proxy is detached, return undefined.
5013     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
5014     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5015     return SetHiddenProperty(
5016         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
5017         value);
5018   }
5019   DCHECK(!object->IsJSGlobalProxy());
5020
5021   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5022
5023   // If there is no backing store yet, store the identity hash inline.
5024   if (value->IsSmi() &&
5025       *key == *isolate->factory()->identity_hash_string() &&
5026       (inline_value->IsUndefined() || inline_value->IsSmi())) {
5027     return JSObject::SetHiddenPropertiesHashTable(object, value);
5028   }
5029
5030   Handle<ObjectHashTable> hashtable =
5031       GetOrCreateHiddenPropertiesHashtable(object);
5032
5033   // If it was found, check if the key is already in the dictionary.
5034   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5035                                                            value);
5036   if (*new_table != *hashtable) {
5037     // If adding the key expanded the dictionary (i.e., Add returned a new
5038     // dictionary), store it back to the object.
5039     SetHiddenPropertiesHashTable(object, new_table);
5040   }
5041
5042   // Return this to mark success.
5043   return object;
5044 }
5045
5046
5047 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5048   Isolate* isolate = object->GetIsolate();
5049   DCHECK(key->IsUniqueName());
5050
5051   if (object->IsJSGlobalProxy()) {
5052     PrototypeIterator iter(isolate, object);
5053     if (iter.IsAtEnd()) return;
5054     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5055     return DeleteHiddenProperty(
5056         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5057   }
5058
5059   Object* inline_value = object->GetHiddenPropertiesHashTable();
5060
5061   // We never delete (inline-stored) identity hashes.
5062   DCHECK(*key != *isolate->factory()->identity_hash_string());
5063   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
5064
5065   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5066   bool was_present = false;
5067   ObjectHashTable::Remove(hashtable, key, &was_present);
5068 }
5069
5070
5071 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5072   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5073   LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
5074   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5075   // Cannot get an exception since the hidden_string isn't accessible to JS.
5076   DCHECK(maybe.has_value);
5077   return maybe.value != ABSENT;
5078 }
5079
5080
5081 Object* JSObject::GetHiddenPropertiesHashTable() {
5082   DCHECK(!IsJSGlobalProxy());
5083   if (HasFastProperties()) {
5084     // If the object has fast properties, check whether the first slot
5085     // in the descriptor array matches the hidden string. Since the
5086     // hidden strings hash code is zero (and no other name has hash
5087     // code zero) it will always occupy the first entry if present.
5088     DescriptorArray* descriptors = this->map()->instance_descriptors();
5089     if (descriptors->number_of_descriptors() > 0) {
5090       int sorted_index = descriptors->GetSortedKeyIndex(0);
5091       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5092           sorted_index < map()->NumberOfOwnDescriptors()) {
5093         DCHECK(descriptors->GetType(sorted_index) == DATA);
5094         DCHECK(descriptors->GetDetails(sorted_index).representation().
5095                IsCompatibleForLoad(Representation::Tagged()));
5096         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5097                                                      sorted_index);
5098         return this->RawFastPropertyAt(index);
5099       } else {
5100         return GetHeap()->undefined_value();
5101       }
5102     } else {
5103       return GetHeap()->undefined_value();
5104     }
5105   } else {
5106     Isolate* isolate = GetIsolate();
5107     LookupIterator it(handle(this), isolate->factory()->hidden_string(),
5108                       LookupIterator::OWN_SKIP_INTERCEPTOR);
5109     // Access check is always skipped for the hidden string anyways.
5110     return *GetDataProperty(&it);
5111   }
5112 }
5113
5114 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5115     Handle<JSObject> object) {
5116   Isolate* isolate = object->GetIsolate();
5117
5118   static const int kInitialCapacity = 4;
5119   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5120   if (inline_value->IsHashTable()) {
5121     return Handle<ObjectHashTable>::cast(inline_value);
5122   }
5123
5124   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5125       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5126
5127   if (inline_value->IsSmi()) {
5128     // We were storing the identity hash inline and now allocated an actual
5129     // dictionary.  Put the identity hash into the new dictionary.
5130     hashtable = ObjectHashTable::Put(hashtable,
5131                                      isolate->factory()->identity_hash_string(),
5132                                      inline_value);
5133   }
5134
5135   SetHiddenPropertiesHashTable(object, hashtable);
5136   return hashtable;
5137 }
5138
5139
5140 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5141                                                       Handle<Object> value) {
5142   DCHECK(!object->IsJSGlobalProxy());
5143   Isolate* isolate = object->GetIsolate();
5144   Handle<Name> name = isolate->factory()->hidden_string();
5145   SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
5146   return object;
5147 }
5148
5149
5150 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5151     Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) {
5152   Isolate* isolate = holder->GetIsolate();
5153
5154   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
5155   if (interceptor->deleter()->IsUndefined() ||
5156       (name->IsSymbol() && !interceptor->can_intercept_symbols())) {
5157     return MaybeHandle<Object>();
5158   }
5159
5160   v8::GenericNamedPropertyDeleterCallback deleter =
5161       v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
5162           interceptor->deleter());
5163   LOG(isolate,
5164       ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
5165   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
5166                                  *holder);
5167   v8::Handle<v8::Boolean> result = args.Call(deleter, v8::Utils::ToLocal(name));
5168   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5169   if (result.IsEmpty()) return MaybeHandle<Object>();
5170
5171   DCHECK(result->IsBoolean());
5172   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5173   result_internal->VerifyApiCallResultType();
5174   // Rebox CustomArguments::kReturnValueOffset before returning.
5175   return handle(*result_internal, isolate);
5176 }
5177
5178
5179 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
5180     Handle<JSObject> object,
5181     uint32_t index) {
5182   Isolate* isolate = object->GetIsolate();
5183   Factory* factory = isolate->factory();
5184
5185   // Make sure that the top context does not change when doing
5186   // callbacks or interceptor calls.
5187   AssertNoContextChange ncc(isolate);
5188
5189   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
5190   if (interceptor->deleter()->IsUndefined()) return factory->false_value();
5191   v8::IndexedPropertyDeleterCallback deleter =
5192       v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5193   LOG(isolate,
5194       ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
5195   PropertyCallbackArguments args(
5196       isolate, interceptor->data(), *object, *object);
5197   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
5198   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5199   if (!result.IsEmpty()) {
5200     DCHECK(result->IsBoolean());
5201     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5202     result_internal->VerifyApiCallResultType();
5203     // Rebox CustomArguments::kReturnValueOffset before returning.
5204     return handle(*result_internal, isolate);
5205   }
5206   // TODO(verwaest): Shouldn't this be the mode that was passed in?
5207   MaybeHandle<Object> delete_result =
5208       object->GetElementsAccessor()->Delete(object, index, SLOPPY);
5209   return delete_result;
5210 }
5211
5212
5213 MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
5214                                             uint32_t index,
5215                                             LanguageMode language_mode) {
5216   Isolate* isolate = object->GetIsolate();
5217   Factory* factory = isolate->factory();
5218
5219   // Check access rights if needed.
5220   if (object->IsAccessCheckNeeded() &&
5221       !isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
5222     isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
5223     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5224     return factory->false_value();
5225   }
5226
5227   if (object->IsStringObjectWithCharacterAt(index)) {
5228     if (is_strict(language_mode)) {
5229       // Deleting a non-configurable property in strict mode.
5230       Handle<Object> name = factory->NewNumberFromUint(index);
5231       Handle<Object> args[] = {name, object};
5232       THROW_NEW_ERROR(isolate,
5233                       NewTypeError("strict_delete_property",
5234                                    HandleVector(args, arraysize(args))),
5235                       Object);
5236     }
5237     return factory->false_value();
5238   }
5239
5240   if (object->IsJSGlobalProxy()) {
5241     PrototypeIterator iter(isolate, object);
5242     if (iter.IsAtEnd()) return factory->false_value();
5243     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5244     return DeleteElement(
5245         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
5246         language_mode);
5247   }
5248
5249   Handle<Object> old_value;
5250   bool should_enqueue_change_record = false;
5251   if (object->map()->is_observed()) {
5252     Maybe<bool> maybe = HasOwnElement(object, index);
5253     if (!maybe.has_value) return MaybeHandle<Object>();
5254     should_enqueue_change_record = maybe.value;
5255     if (should_enqueue_change_record) {
5256       if (!GetOwnElementAccessorPair(object, index).is_null()) {
5257         old_value = Handle<Object>::cast(factory->the_hole_value());
5258       } else {
5259         old_value = Object::GetElement(
5260             isolate, object, index).ToHandleChecked();
5261       }
5262     }
5263   }
5264
5265   // Skip interceptor if forcing deletion.
5266   MaybeHandle<Object> maybe_result;
5267   if (object->HasIndexedInterceptor()) {
5268     maybe_result = DeleteElementWithInterceptor(object, index);
5269   } else {
5270     maybe_result =
5271         object->GetElementsAccessor()->Delete(object, index, language_mode);
5272   }
5273   Handle<Object> result;
5274   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
5275
5276   if (should_enqueue_change_record) {
5277     Maybe<bool> maybe = HasOwnElement(object, index);
5278     if (!maybe.has_value) return MaybeHandle<Object>();
5279     if (!maybe.value) {
5280       Handle<String> name = factory->Uint32ToString(index);
5281       RETURN_ON_EXCEPTION(
5282           isolate, EnqueueChangeRecord(object, "delete", name, old_value),
5283           Object);
5284     }
5285   }
5286
5287   return result;
5288 }
5289
5290
5291 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
5292                                         Handle<Name> name) {
5293   DCHECK(!object->HasFastProperties());
5294   Isolate* isolate = object->GetIsolate();
5295   Handle<NameDictionary> dictionary(object->property_dictionary());
5296   int entry = dictionary->FindEntry(name);
5297   DCHECK_NE(NameDictionary::kNotFound, entry);
5298
5299   // If we have a global object set the cell to the hole.
5300   if (object->IsGlobalObject()) {
5301     PropertyDetails details = dictionary->DetailsAt(entry);
5302     DCHECK(details.IsConfigurable());
5303     Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
5304     Handle<Object> value = isolate->factory()->the_hole_value();
5305     PropertyCell::SetValueInferType(cell, value);
5306     dictionary->DetailsAtPut(entry, details.AsDeleted());
5307     return;
5308   }
5309
5310   NameDictionary::DeleteProperty(dictionary, entry);
5311   Handle<NameDictionary> new_properties =
5312       NameDictionary::Shrink(dictionary, name);
5313   object->set_properties(*new_properties);
5314 }
5315
5316
5317 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5318                                              Handle<Name> name,
5319                                              LanguageMode language_mode) {
5320   // ECMA-262, 3rd, 8.6.2.5
5321   DCHECK(name->IsName());
5322
5323   uint32_t index = 0;
5324   if (name->AsArrayIndex(&index)) {
5325     return DeleteElement(object, index, language_mode);
5326   }
5327
5328   LookupIterator it(object, name, LookupIterator::HIDDEN);
5329
5330   bool is_observed = object->map()->is_observed() &&
5331                      !it.isolate()->IsInternallyUsedPropertyName(name);
5332   Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
5333
5334   for (; it.IsFound(); it.Next()) {
5335     switch (it.state()) {
5336       case LookupIterator::JSPROXY:
5337       case LookupIterator::NOT_FOUND:
5338       case LookupIterator::TRANSITION:
5339         UNREACHABLE();
5340       case LookupIterator::ACCESS_CHECK:
5341         if (it.HasAccess(v8::ACCESS_DELETE)) break;
5342         it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
5343                                               v8::ACCESS_DELETE);
5344         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object);
5345         return it.isolate()->factory()->false_value();
5346       case LookupIterator::INTERCEPTOR: {
5347         MaybeHandle<Object> maybe_result =
5348             JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(),
5349                                                     object, it.name());
5350         // Delete with interceptor succeeded. Return result.
5351         if (!maybe_result.is_null()) return maybe_result;
5352         // An exception was thrown in the interceptor. Propagate.
5353         if (it.isolate()->has_pending_exception()) return maybe_result;
5354         break;
5355       }
5356       case LookupIterator::DATA:
5357         if (is_observed) {
5358           old_value = it.GetDataValue();
5359         }
5360       // Fall through.
5361       case LookupIterator::ACCESSOR: {
5362         if (!it.IsConfigurable()) {
5363           // Fail if the property is not configurable.
5364           if (is_strict(language_mode)) {
5365             Handle<Object> args[] = {name, object};
5366             THROW_NEW_ERROR(it.isolate(),
5367                             NewTypeError("strict_delete_property",
5368                                          HandleVector(args, arraysize(args))),
5369                             Object);
5370           }
5371           return it.isolate()->factory()->false_value();
5372         }
5373
5374         PropertyNormalizationMode mode = object->map()->is_prototype_map()
5375                                              ? KEEP_INOBJECT_PROPERTIES
5376                                              : CLEAR_INOBJECT_PROPERTIES;
5377         Handle<JSObject> holder = it.GetHolder<JSObject>();
5378         // TODO(verwaest): Remove this temporary compatibility hack when blink
5379         // tests are updated.
5380         if (!holder.is_identical_to(object) &&
5381             !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) {
5382           return it.isolate()->factory()->true_value();
5383         }
5384
5385         NormalizeProperties(holder, mode, 0, "DeletingProperty");
5386         DeleteNormalizedProperty(holder, name);
5387         ReoptimizeIfPrototype(holder);
5388
5389         if (is_observed) {
5390           RETURN_ON_EXCEPTION(
5391               it.isolate(),
5392               EnqueueChangeRecord(object, "delete", name, old_value), Object);
5393         }
5394
5395         return it.isolate()->factory()->true_value();
5396       }
5397     }
5398   }
5399
5400   return it.isolate()->factory()->true_value();
5401 }
5402
5403
5404 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5405                                               uint32_t index,
5406                                               LanguageMode language_mode) {
5407   if (object->IsJSProxy()) {
5408     return JSProxy::DeleteElementWithHandler(Handle<JSProxy>::cast(object),
5409                                              index, language_mode);
5410   }
5411   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index,
5412                                  language_mode);
5413 }
5414
5415
5416 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5417                                                Handle<Name> name,
5418                                                LanguageMode language_mode) {
5419   if (object->IsJSProxy()) {
5420     return JSProxy::DeletePropertyWithHandler(Handle<JSProxy>::cast(object),
5421                                               name, language_mode);
5422   }
5423   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name,
5424                                   language_mode);
5425 }
5426
5427
5428 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5429                                             ElementsKind kind,
5430                                             Object* object) {
5431   DCHECK(IsFastObjectElementsKind(kind) ||
5432          kind == DICTIONARY_ELEMENTS);
5433   if (IsFastObjectElementsKind(kind)) {
5434     int length = IsJSArray()
5435         ? Smi::cast(JSArray::cast(this)->length())->value()
5436         : elements->length();
5437     for (int i = 0; i < length; ++i) {
5438       Object* element = elements->get(i);
5439       if (!element->IsTheHole() && element == object) return true;
5440     }
5441   } else {
5442     Object* key =
5443         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5444     if (!key->IsUndefined()) return true;
5445   }
5446   return false;
5447 }
5448
5449
5450 // Check whether this object references another object.
5451 bool JSObject::ReferencesObject(Object* obj) {
5452   Map* map_of_this = map();
5453   Heap* heap = GetHeap();
5454   DisallowHeapAllocation no_allocation;
5455
5456   // Is the object the constructor for this object?
5457   if (map_of_this->constructor() == obj) {
5458     return true;
5459   }
5460
5461   // Is the object the prototype for this object?
5462   if (map_of_this->prototype() == obj) {
5463     return true;
5464   }
5465
5466   // Check if the object is among the named properties.
5467   Object* key = SlowReverseLookup(obj);
5468   if (!key->IsUndefined()) {
5469     return true;
5470   }
5471
5472   // Check if the object is among the indexed properties.
5473   ElementsKind kind = GetElementsKind();
5474   switch (kind) {
5475     // Raw pixels and external arrays do not reference other
5476     // objects.
5477 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5478     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5479     case TYPE##_ELEMENTS:                                                      \
5480       break;
5481
5482     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5483 #undef TYPED_ARRAY_CASE
5484
5485     case FAST_DOUBLE_ELEMENTS:
5486     case FAST_HOLEY_DOUBLE_ELEMENTS:
5487       break;
5488     case FAST_SMI_ELEMENTS:
5489     case FAST_HOLEY_SMI_ELEMENTS:
5490       break;
5491     case FAST_ELEMENTS:
5492     case FAST_HOLEY_ELEMENTS:
5493     case DICTIONARY_ELEMENTS: {
5494       FixedArray* elements = FixedArray::cast(this->elements());
5495       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5496       break;
5497     }
5498     case SLOPPY_ARGUMENTS_ELEMENTS: {
5499       FixedArray* parameter_map = FixedArray::cast(elements());
5500       // Check the mapped parameters.
5501       int length = parameter_map->length();
5502       for (int i = 2; i < length; ++i) {
5503         Object* value = parameter_map->get(i);
5504         if (!value->IsTheHole() && value == obj) return true;
5505       }
5506       // Check the arguments.
5507       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5508       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5509           FAST_HOLEY_ELEMENTS;
5510       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5511       break;
5512     }
5513   }
5514
5515   // For functions check the context.
5516   if (IsJSFunction()) {
5517     // Get the constructor function for arguments array.
5518     Map* arguments_map =
5519         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5520     JSFunction* arguments_function =
5521         JSFunction::cast(arguments_map->constructor());
5522
5523     // Get the context and don't check if it is the native context.
5524     JSFunction* f = JSFunction::cast(this);
5525     Context* context = f->context();
5526     if (context->IsNativeContext()) {
5527       return false;
5528     }
5529
5530     // Check the non-special context slots.
5531     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5532       // Only check JS objects.
5533       if (context->get(i)->IsJSObject()) {
5534         JSObject* ctxobj = JSObject::cast(context->get(i));
5535         // If it is an arguments array check the content.
5536         if (ctxobj->map()->constructor() == arguments_function) {
5537           if (ctxobj->ReferencesObject(obj)) {
5538             return true;
5539           }
5540         } else if (ctxobj == obj) {
5541           return true;
5542         }
5543       }
5544     }
5545
5546     // Check the context extension (if any) if it can have references.
5547     if (context->has_extension() && !context->IsCatchContext()) {
5548       // With harmony scoping, a JSFunction may have a global context.
5549       // TODO(mvstanton): walk into the ScopeInfo.
5550       if (FLAG_harmony_scoping && context->IsScriptContext()) {
5551         return false;
5552       }
5553
5554       return JSObject::cast(context->extension())->ReferencesObject(obj);
5555     }
5556   }
5557
5558   // No references to object.
5559   return false;
5560 }
5561
5562
5563 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5564   if (!object->map()->is_extensible()) return object;
5565
5566   if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
5567     return PreventExtensionsWithTransition<NONE>(object);
5568   }
5569
5570   Isolate* isolate = object->GetIsolate();
5571
5572   if (object->IsAccessCheckNeeded() &&
5573       !isolate->MayNamedAccess(
5574           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5575     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5576     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5577     return isolate->factory()->false_value();
5578   }
5579
5580   if (object->IsJSGlobalProxy()) {
5581     PrototypeIterator iter(isolate, object);
5582     if (iter.IsAtEnd()) return object;
5583     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5584     return PreventExtensions(
5585         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5586   }
5587
5588   // It's not possible to seal objects with external array elements
5589   if (object->HasExternalArrayElements() ||
5590       object->HasFixedTypedArrayElements()) {
5591     THROW_NEW_ERROR(isolate,
5592                     NewTypeError("cant_prevent_ext_external_array_elements",
5593                                  HandleVector(&object, 1)),
5594                     Object);
5595   }
5596
5597   // If there are fast elements we normalize.
5598   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5599   DCHECK(object->HasDictionaryElements() ||
5600          object->HasDictionaryArgumentsElements());
5601
5602   // Make sure that we never go back to fast case.
5603   dictionary->set_requires_slow_elements();
5604
5605   // Do a map transition, other objects with this map may still
5606   // be extensible.
5607   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5608   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
5609
5610   new_map->set_is_extensible(false);
5611   JSObject::MigrateToMap(object, new_map);
5612   DCHECK(!object->map()->is_extensible());
5613
5614   if (object->map()->is_observed()) {
5615     RETURN_ON_EXCEPTION(
5616         isolate,
5617         EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5618                             isolate->factory()->the_hole_value()),
5619         Object);
5620   }
5621   return object;
5622 }
5623
5624
5625 Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
5626     Handle<JSObject> object) {
5627   DCHECK(!object->elements()->IsDictionary());
5628   Isolate* isolate = object->GetIsolate();
5629   int length = object->IsJSArray()
5630                    ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5631                    : object->elements()->length();
5632   if (length > 0) {
5633     int capacity = 0;
5634     int used = 0;
5635     object->GetElementsCapacityAndUsage(&capacity, &used);
5636     Handle<SeededNumberDictionary> new_element_dictionary =
5637         SeededNumberDictionary::New(isolate, used);
5638
5639     // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5640     // unnecessary transitions.
5641     return CopyFastElementsToDictionary(handle(object->elements()), length,
5642                                         new_element_dictionary);
5643   }
5644   // No existing elements, use a pre-allocated empty backing store
5645   return isolate->factory()->empty_slow_element_dictionary();
5646 }
5647
5648
5649 template <typename Dictionary>
5650 static void ApplyAttributesToDictionary(Dictionary* dictionary,
5651                                         const PropertyAttributes attributes) {
5652   int capacity = dictionary->Capacity();
5653   for (int i = 0; i < capacity; i++) {
5654     Object* k = dictionary->KeyAt(i);
5655     if (dictionary->IsKey(k) &&
5656         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5657       PropertyDetails details = dictionary->DetailsAt(i);
5658       int attrs = attributes;
5659       // READ_ONLY is an invalid attribute for JS setters/getters.
5660       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
5661         Object* v = dictionary->ValueAt(i);
5662         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5663         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
5664       }
5665       details = details.CopyAddAttributes(
5666           static_cast<PropertyAttributes>(attrs));
5667       dictionary->DetailsAtPut(i, details);
5668     }
5669   }
5670 }
5671
5672
5673 template <PropertyAttributes attrs>
5674 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
5675     Handle<JSObject> object) {
5676   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
5677
5678   // Sealing/freezing sloppy arguments should be handled elsewhere.
5679   DCHECK(!object->HasSloppyArgumentsElements());
5680   DCHECK(!object->map()->is_observed());
5681
5682   Isolate* isolate = object->GetIsolate();
5683   if (object->IsAccessCheckNeeded() &&
5684       !isolate->MayNamedAccess(
5685           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5686     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5687     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5688     return isolate->factory()->false_value();
5689   }
5690
5691   if (object->IsJSGlobalProxy()) {
5692     PrototypeIterator iter(isolate, object);
5693     if (iter.IsAtEnd()) return object;
5694     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5695     return PreventExtensionsWithTransition<attrs>(
5696         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5697   }
5698
5699   // It's not possible to seal or freeze objects with external array elements
5700   if (object->HasExternalArrayElements() ||
5701       object->HasFixedTypedArrayElements()) {
5702     THROW_NEW_ERROR(isolate,
5703                     NewTypeError("cant_prevent_ext_external_array_elements",
5704                                  HandleVector(&object, 1)),
5705                     Object);
5706   }
5707
5708   Handle<SeededNumberDictionary> new_element_dictionary;
5709   if (!object->elements()->IsDictionary()) {
5710     new_element_dictionary = GetNormalizedElementDictionary(object);
5711   }
5712
5713   Handle<Symbol> transition_marker;
5714   if (attrs == NONE) {
5715     transition_marker = isolate->factory()->nonextensible_symbol();
5716   } else if (attrs == SEALED) {
5717     transition_marker = isolate->factory()->sealed_symbol();
5718   } else {
5719     DCHECK(attrs == FROZEN);
5720     transition_marker = isolate->factory()->frozen_symbol();
5721   }
5722
5723   Handle<Map> old_map(object->map(), isolate);
5724   int transition_index = old_map->SearchSpecialTransition(*transition_marker);
5725   if (transition_index != TransitionArray::kNotFound) {
5726     Handle<Map> transition_map(old_map->GetTransition(transition_index));
5727     DCHECK(transition_map->has_dictionary_elements());
5728     DCHECK(!transition_map->is_extensible());
5729     JSObject::MigrateToMap(object, transition_map);
5730   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5731     // Create a new descriptor array with the appropriate property attributes
5732     Handle<Map> new_map = Map::CopyForPreventExtensions(
5733         old_map, attrs, transition_marker, "CopyForPreventExtensions");
5734     JSObject::MigrateToMap(object, new_map);
5735   } else {
5736     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5737     // Slow path: need to normalize properties for safety
5738     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5739                         "SlowPreventExtensions");
5740
5741     // Create a new map, since other objects with this map may be extensible.
5742     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5743     Handle<Map> new_map =
5744         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5745     new_map->set_is_extensible(false);
5746     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5747     JSObject::MigrateToMap(object, new_map);
5748
5749     if (attrs != NONE) {
5750       ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5751     }
5752   }
5753
5754   DCHECK(object->map()->has_dictionary_elements());
5755   if (!new_element_dictionary.is_null()) {
5756     object->set_elements(*new_element_dictionary);
5757   }
5758
5759   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5760     SeededNumberDictionary* dictionary = object->element_dictionary();
5761     // Make sure we never go back to the fast case
5762     dictionary->set_requires_slow_elements();
5763     if (attrs != NONE) {
5764       ApplyAttributesToDictionary(dictionary, attrs);
5765     }
5766   }
5767
5768   return object;
5769 }
5770
5771
5772 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5773   return PreventExtensionsWithTransition<FROZEN>(object);
5774 }
5775
5776
5777 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
5778   return PreventExtensionsWithTransition<SEALED>(object);
5779 }
5780
5781
5782 void JSObject::SetObserved(Handle<JSObject> object) {
5783   DCHECK(!object->IsJSGlobalProxy());
5784   DCHECK(!object->IsJSGlobalObject());
5785   Isolate* isolate = object->GetIsolate();
5786   Handle<Map> new_map;
5787   Handle<Map> old_map(object->map(), isolate);
5788   DCHECK(!old_map->is_observed());
5789   int transition_index =
5790       old_map->SearchSpecialTransition(isolate->heap()->observed_symbol());
5791   if (transition_index != TransitionArray::kNotFound) {
5792     new_map = handle(old_map->GetTransition(transition_index), isolate);
5793     DCHECK(new_map->is_observed());
5794   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5795     new_map = Map::CopyForObserved(old_map);
5796   } else {
5797     new_map = Map::Copy(old_map, "SlowObserved");
5798     new_map->set_is_observed();
5799   }
5800   JSObject::MigrateToMap(object, new_map);
5801 }
5802
5803
5804 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5805                                         Representation representation,
5806                                         FieldIndex index) {
5807   Isolate* isolate = object->GetIsolate();
5808   if (object->IsUnboxedDoubleField(index)) {
5809     double value = object->RawFastDoublePropertyAt(index);
5810     return isolate->factory()->NewHeapNumber(value);
5811   }
5812   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5813   return Object::WrapForRead(isolate, raw_value, representation);
5814 }
5815
5816
5817 template<class ContextObject>
5818 class JSObjectWalkVisitor {
5819  public:
5820   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5821                       JSObject::DeepCopyHints hints)
5822     : site_context_(site_context),
5823       copying_(copying),
5824       hints_(hints) {}
5825
5826   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5827
5828  protected:
5829   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5830       Handle<JSObject> object,
5831       Handle<JSObject> value) {
5832     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5833     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5834     site_context()->ExitScope(current_site, value);
5835     return copy_of_value;
5836   }
5837
5838   inline ContextObject* site_context() { return site_context_; }
5839   inline Isolate* isolate() { return site_context()->isolate(); }
5840
5841   inline bool copying() const { return copying_; }
5842
5843  private:
5844   ContextObject* site_context_;
5845   const bool copying_;
5846   const JSObject::DeepCopyHints hints_;
5847 };
5848
5849
5850 template <class ContextObject>
5851 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5852     Handle<JSObject> object) {
5853   Isolate* isolate = this->isolate();
5854   bool copying = this->copying();
5855   bool shallow = hints_ == JSObject::kObjectIsShallow;
5856
5857   if (!shallow) {
5858     StackLimitCheck check(isolate);
5859
5860     if (check.HasOverflowed()) {
5861       isolate->StackOverflow();
5862       return MaybeHandle<JSObject>();
5863     }
5864   }
5865
5866   if (object->map()->is_deprecated()) {
5867     JSObject::MigrateInstance(object);
5868   }
5869
5870   Handle<JSObject> copy;
5871   if (copying) {
5872     Handle<AllocationSite> site_to_pass;
5873     if (site_context()->ShouldCreateMemento(object)) {
5874       site_to_pass = site_context()->current();
5875     }
5876     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5877         object, site_to_pass);
5878   } else {
5879     copy = object;
5880   }
5881
5882   DCHECK(copying || copy.is_identical_to(object));
5883
5884   ElementsKind kind = copy->GetElementsKind();
5885   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5886       FixedArray::cast(copy->elements())->map() ==
5887         isolate->heap()->fixed_cow_array_map()) {
5888     isolate->counters()->cow_arrays_created_runtime()->Increment();
5889   }
5890
5891   if (!shallow) {
5892     HandleScope scope(isolate);
5893
5894     // Deep copy own properties.
5895     if (copy->HasFastProperties()) {
5896       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5897       int limit = copy->map()->NumberOfOwnDescriptors();
5898       for (int i = 0; i < limit; i++) {
5899         PropertyDetails details = descriptors->GetDetails(i);
5900         if (details.type() != DATA) continue;
5901         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5902         if (object->IsUnboxedDoubleField(index)) {
5903           if (copying) {
5904             double value = object->RawFastDoublePropertyAt(index);
5905             copy->RawFastDoublePropertyAtPut(index, value);
5906           }
5907         } else {
5908           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5909           if (value->IsJSObject()) {
5910             ASSIGN_RETURN_ON_EXCEPTION(
5911                 isolate, value,
5912                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5913                 JSObject);
5914             if (copying) {
5915               copy->FastPropertyAtPut(index, *value);
5916             }
5917           } else {
5918             if (copying) {
5919               Representation representation = details.representation();
5920               value = Object::NewStorageFor(isolate, value, representation);
5921               copy->FastPropertyAtPut(index, *value);
5922             }
5923           }
5924         }
5925       }
5926     } else {
5927       Handle<FixedArray> names =
5928           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5929       copy->GetOwnPropertyNames(*names, 0);
5930       for (int i = 0; i < names->length(); i++) {
5931         DCHECK(names->get(i)->IsString());
5932         Handle<String> key_string(String::cast(names->get(i)));
5933         Maybe<PropertyAttributes> maybe =
5934             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5935         DCHECK(maybe.has_value);
5936         PropertyAttributes attributes = maybe.value;
5937         // Only deep copy fields from the object literal expression.
5938         // In particular, don't try to copy the length attribute of
5939         // an array.
5940         if (attributes != NONE) continue;
5941         Handle<Object> value =
5942             Object::GetProperty(copy, key_string).ToHandleChecked();
5943         if (value->IsJSObject()) {
5944           Handle<JSObject> result;
5945           ASSIGN_RETURN_ON_EXCEPTION(
5946               isolate, result,
5947               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5948               JSObject);
5949           if (copying) {
5950             // Creating object copy for literals. No strict mode needed.
5951             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5952           }
5953         }
5954       }
5955     }
5956
5957     // Deep copy own elements.
5958     // Pixel elements cannot be created using an object literal.
5959     DCHECK(!copy->HasExternalArrayElements());
5960     switch (kind) {
5961       case FAST_SMI_ELEMENTS:
5962       case FAST_ELEMENTS:
5963       case FAST_HOLEY_SMI_ELEMENTS:
5964       case FAST_HOLEY_ELEMENTS: {
5965         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5966         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5967 #ifdef DEBUG
5968           for (int i = 0; i < elements->length(); i++) {
5969             DCHECK(!elements->get(i)->IsJSObject());
5970           }
5971 #endif
5972         } else {
5973           for (int i = 0; i < elements->length(); i++) {
5974             Handle<Object> value(elements->get(i), isolate);
5975             DCHECK(value->IsSmi() ||
5976                    value->IsTheHole() ||
5977                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5978             if (value->IsJSObject()) {
5979               Handle<JSObject> result;
5980               ASSIGN_RETURN_ON_EXCEPTION(
5981                   isolate, result,
5982                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5983                   JSObject);
5984               if (copying) {
5985                 elements->set(i, *result);
5986               }
5987             }
5988           }
5989         }
5990         break;
5991       }
5992       case DICTIONARY_ELEMENTS: {
5993         Handle<SeededNumberDictionary> element_dictionary(
5994             copy->element_dictionary());
5995         int capacity = element_dictionary->Capacity();
5996         for (int i = 0; i < capacity; i++) {
5997           Object* k = element_dictionary->KeyAt(i);
5998           if (element_dictionary->IsKey(k)) {
5999             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
6000             if (value->IsJSObject()) {
6001               Handle<JSObject> result;
6002               ASSIGN_RETURN_ON_EXCEPTION(
6003                   isolate, result,
6004                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
6005                   JSObject);
6006               if (copying) {
6007                 element_dictionary->ValueAtPut(i, *result);
6008               }
6009             }
6010           }
6011         }
6012         break;
6013       }
6014       case SLOPPY_ARGUMENTS_ELEMENTS:
6015         UNIMPLEMENTED();
6016         break;
6017
6018
6019 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6020       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6021       case TYPE##_ELEMENTS:                                                    \
6022
6023       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6024 #undef TYPED_ARRAY_CASE
6025
6026       case FAST_DOUBLE_ELEMENTS:
6027       case FAST_HOLEY_DOUBLE_ELEMENTS:
6028         // No contained objects, nothing to do.
6029         break;
6030     }
6031   }
6032
6033   return copy;
6034 }
6035
6036
6037 MaybeHandle<JSObject> JSObject::DeepWalk(
6038     Handle<JSObject> object,
6039     AllocationSiteCreationContext* site_context) {
6040   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
6041                                                        kNoHints);
6042   MaybeHandle<JSObject> result = v.StructureWalk(object);
6043   Handle<JSObject> for_assert;
6044   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
6045   return result;
6046 }
6047
6048
6049 MaybeHandle<JSObject> JSObject::DeepCopy(
6050     Handle<JSObject> object,
6051     AllocationSiteUsageContext* site_context,
6052     DeepCopyHints hints) {
6053   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
6054   MaybeHandle<JSObject> copy = v.StructureWalk(object);
6055   Handle<JSObject> for_assert;
6056   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
6057   return copy;
6058 }
6059
6060
6061 // Tests for the fast common case for property enumeration:
6062 // - This object and all prototypes has an enum cache (which means that
6063 //   it is no proxy, has no interceptors and needs no access checks).
6064 // - This object has no elements.
6065 // - No prototype has enumerable properties/elements.
6066 bool JSReceiver::IsSimpleEnum() {
6067   for (PrototypeIterator iter(GetIsolate(), this,
6068                               PrototypeIterator::START_AT_RECEIVER);
6069        !iter.IsAtEnd(); iter.Advance()) {
6070     if (!iter.GetCurrent()->IsJSObject()) return false;
6071     JSObject* curr = JSObject::cast(iter.GetCurrent());
6072     int enum_length = curr->map()->EnumLength();
6073     if (enum_length == kInvalidEnumCacheSentinel) return false;
6074     if (curr->IsAccessCheckNeeded()) return false;
6075     DCHECK(!curr->HasNamedInterceptor());
6076     DCHECK(!curr->HasIndexedInterceptor());
6077     if (curr->NumberOfEnumElements() > 0) return false;
6078     if (curr != this && enum_length != 0) return false;
6079   }
6080   return true;
6081 }
6082
6083
6084 static bool FilterKey(Object* key, PropertyAttributes filter) {
6085   if ((filter & SYMBOLIC) && key->IsSymbol()) {
6086     return true;
6087   }
6088
6089   if ((filter & PRIVATE_SYMBOL) &&
6090       key->IsSymbol() && Symbol::cast(key)->is_private()) {
6091     return true;
6092   }
6093
6094   if ((filter & STRING) && !key->IsSymbol()) {
6095     return true;
6096   }
6097
6098   return false;
6099 }
6100
6101
6102 int Map::NumberOfDescribedProperties(DescriptorFlag which,
6103                                      PropertyAttributes filter) {
6104   int result = 0;
6105   DescriptorArray* descs = instance_descriptors();
6106   int limit = which == ALL_DESCRIPTORS
6107       ? descs->number_of_descriptors()
6108       : NumberOfOwnDescriptors();
6109   for (int i = 0; i < limit; i++) {
6110     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
6111         !FilterKey(descs->GetKey(i), filter)) {
6112       result++;
6113     }
6114   }
6115   return result;
6116 }
6117
6118
6119 int Map::NextFreePropertyIndex() {
6120   int free_index = 0;
6121   int number_of_own_descriptors = NumberOfOwnDescriptors();
6122   DescriptorArray* descs = instance_descriptors();
6123   for (int i = 0; i < number_of_own_descriptors; i++) {
6124     PropertyDetails details = descs->GetDetails(i);
6125     if (details.location() == kField) {
6126       int candidate = details.field_index() + details.field_width_in_words();
6127       if (candidate > free_index) free_index = candidate;
6128     }
6129   }
6130   return free_index;
6131 }
6132
6133
6134 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6135   int len = array->length();
6136   for (int i = 0; i < len; i++) {
6137     Object* e = array->get(i);
6138     if (!(e->IsName() || e->IsNumber())) return false;
6139   }
6140   return true;
6141 }
6142
6143
6144 static Handle<FixedArray> ReduceFixedArrayTo(
6145     Handle<FixedArray> array, int length) {
6146   DCHECK(array->length() >= length);
6147   if (array->length() == length) return array;
6148
6149   Handle<FixedArray> new_array =
6150       array->GetIsolate()->factory()->NewFixedArray(length);
6151   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6152   return new_array;
6153 }
6154
6155
6156 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
6157                                               bool cache_result) {
6158   Isolate* isolate = object->GetIsolate();
6159   if (object->HasFastProperties()) {
6160     int own_property_count = object->map()->EnumLength();
6161     // If the enum length of the given map is set to kInvalidEnumCache, this
6162     // means that the map itself has never used the present enum cache. The
6163     // first step to using the cache is to set the enum length of the map by
6164     // counting the number of own descriptors that are not DONT_ENUM or
6165     // SYMBOLIC.
6166     if (own_property_count == kInvalidEnumCacheSentinel) {
6167       own_property_count = object->map()->NumberOfDescribedProperties(
6168           OWN_DESCRIPTORS, DONT_SHOW);
6169     } else {
6170       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6171           OWN_DESCRIPTORS, DONT_SHOW));
6172     }
6173
6174     if (object->map()->instance_descriptors()->HasEnumCache()) {
6175       DescriptorArray* desc = object->map()->instance_descriptors();
6176       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6177
6178       // In case the number of properties required in the enum are actually
6179       // present, we can reuse the enum cache. Otherwise, this means that the
6180       // enum cache was generated for a previous (smaller) version of the
6181       // Descriptor Array. In that case we regenerate the enum cache.
6182       if (own_property_count <= keys->length()) {
6183         if (cache_result) object->map()->SetEnumLength(own_property_count);
6184         isolate->counters()->enum_cache_hits()->Increment();
6185         return ReduceFixedArrayTo(keys, own_property_count);
6186       }
6187     }
6188
6189     Handle<Map> map(object->map());
6190
6191     if (map->instance_descriptors()->IsEmpty()) {
6192       isolate->counters()->enum_cache_hits()->Increment();
6193       if (cache_result) map->SetEnumLength(0);
6194       return isolate->factory()->empty_fixed_array();
6195     }
6196
6197     isolate->counters()->enum_cache_misses()->Increment();
6198
6199     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6200         own_property_count);
6201     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6202         own_property_count);
6203
6204     Handle<DescriptorArray> descs =
6205         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6206
6207     int size = map->NumberOfOwnDescriptors();
6208     int index = 0;
6209
6210     for (int i = 0; i < size; i++) {
6211       PropertyDetails details = descs->GetDetails(i);
6212       Object* key = descs->GetKey(i);
6213       if (!(details.IsDontEnum() || key->IsSymbol())) {
6214         storage->set(index, key);
6215         if (!indices.is_null()) {
6216           if (details.type() != DATA) {
6217             indices = Handle<FixedArray>();
6218           } else {
6219             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6220             int load_by_field_index = field_index.GetLoadByFieldIndex();
6221             indices->set(index, Smi::FromInt(load_by_field_index));
6222           }
6223         }
6224         index++;
6225       }
6226     }
6227     DCHECK(index == storage->length());
6228
6229     Handle<FixedArray> bridge_storage =
6230         isolate->factory()->NewFixedArray(
6231             DescriptorArray::kEnumCacheBridgeLength);
6232     DescriptorArray* desc = object->map()->instance_descriptors();
6233     desc->SetEnumCache(*bridge_storage,
6234                        *storage,
6235                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6236                                          : Object::cast(*indices));
6237     if (cache_result) {
6238       object->map()->SetEnumLength(own_property_count);
6239     }
6240     return storage;
6241   } else {
6242     Handle<NameDictionary> dictionary(object->property_dictionary());
6243     int length = dictionary->NumberOfEnumElements();
6244     if (length == 0) {
6245       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6246     }
6247     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6248     dictionary->CopyEnumKeysTo(*storage);
6249     return storage;
6250   }
6251 }
6252
6253
6254 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6255                                             KeyCollectionType type) {
6256   USE(ContainsOnlyValidKeys);
6257   Isolate* isolate = object->GetIsolate();
6258   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6259   Handle<JSFunction> arguments_function(
6260       JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
6261
6262   // Only collect keys if access is permitted.
6263   for (PrototypeIterator iter(isolate, object,
6264                               PrototypeIterator::START_AT_RECEIVER);
6265        !iter.IsAtEnd(); iter.Advance()) {
6266     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6267       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6268                             isolate);
6269       Handle<Object> args[] = { proxy };
6270       Handle<Object> names;
6271       ASSIGN_RETURN_ON_EXCEPTION(
6272           isolate, names,
6273           Execution::Call(isolate,
6274                           isolate->proxy_enumerate(),
6275                           object,
6276                           arraysize(args),
6277                           args),
6278           FixedArray);
6279       ASSIGN_RETURN_ON_EXCEPTION(
6280           isolate, content,
6281           FixedArray::AddKeysFromArrayLike(
6282               content, Handle<JSObject>::cast(names)),
6283           FixedArray);
6284       break;
6285     }
6286
6287     Handle<JSObject> current =
6288         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6289
6290     // Check access rights if required.
6291     if (current->IsAccessCheckNeeded() &&
6292         !isolate->MayNamedAccess(
6293             current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6294       isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
6295       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6296       break;
6297     }
6298
6299     // Compute the element keys.
6300     Handle<FixedArray> element_keys =
6301         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6302     current->GetEnumElementKeys(*element_keys);
6303     ASSIGN_RETURN_ON_EXCEPTION(
6304         isolate, content,
6305         FixedArray::UnionOfKeys(content, element_keys),
6306         FixedArray);
6307     DCHECK(ContainsOnlyValidKeys(content));
6308
6309     // Add the element keys from the interceptor.
6310     if (current->HasIndexedInterceptor()) {
6311       Handle<JSObject> result;
6312       if (JSObject::GetKeysForIndexedInterceptor(
6313               current, object).ToHandle(&result)) {
6314         ASSIGN_RETURN_ON_EXCEPTION(
6315             isolate, content,
6316             FixedArray::AddKeysFromArrayLike(content, result),
6317             FixedArray);
6318       }
6319       DCHECK(ContainsOnlyValidKeys(content));
6320     }
6321
6322     // We can cache the computed property keys if access checks are
6323     // not needed and no interceptors are involved.
6324     //
6325     // We do not use the cache if the object has elements and
6326     // therefore it does not make sense to cache the property names
6327     // for arguments objects.  Arguments objects will always have
6328     // elements.
6329     // Wrapped strings have elements, but don't have an elements
6330     // array or dictionary.  So the fast inline test for whether to
6331     // use the cache says yes, so we should not create a cache.
6332     bool cache_enum_keys =
6333         ((current->map()->constructor() != *arguments_function) &&
6334          !current->IsJSValue() &&
6335          !current->IsAccessCheckNeeded() &&
6336          !current->HasNamedInterceptor() &&
6337          !current->HasIndexedInterceptor());
6338     // Compute the property keys and cache them if possible.
6339     ASSIGN_RETURN_ON_EXCEPTION(
6340         isolate, content,
6341         FixedArray::UnionOfKeys(
6342             content, GetEnumPropertyKeys(current, cache_enum_keys)),
6343         FixedArray);
6344     DCHECK(ContainsOnlyValidKeys(content));
6345
6346     // Add the non-symbol property keys from the interceptor.
6347     if (current->HasNamedInterceptor()) {
6348       Handle<JSObject> result;
6349       if (JSObject::GetKeysForNamedInterceptor(
6350               current, object).ToHandle(&result)) {
6351         ASSIGN_RETURN_ON_EXCEPTION(
6352             isolate, content, FixedArray::AddKeysFromArrayLike(
6353                                   content, result, FixedArray::NON_SYMBOL_KEYS),
6354             FixedArray);
6355       }
6356       DCHECK(ContainsOnlyValidKeys(content));
6357     }
6358
6359     // If we only want own properties we bail out after the first
6360     // iteration.
6361     if (type == OWN_ONLY) break;
6362   }
6363   return content;
6364 }
6365
6366
6367 // Try to update an accessor in an elements dictionary. Return true if the
6368 // update succeeded, and false otherwise.
6369 static bool UpdateGetterSetterInDictionary(
6370     SeededNumberDictionary* dictionary,
6371     uint32_t index,
6372     Object* getter,
6373     Object* setter,
6374     PropertyAttributes attributes) {
6375   int entry = dictionary->FindEntry(index);
6376   if (entry != SeededNumberDictionary::kNotFound) {
6377     Object* result = dictionary->ValueAt(entry);
6378     PropertyDetails details = dictionary->DetailsAt(entry);
6379     if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) {
6380       DCHECK(details.IsConfigurable());
6381       if (details.attributes() != attributes) {
6382         dictionary->DetailsAtPut(
6383             entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index));
6384       }
6385       AccessorPair::cast(result)->SetComponents(getter, setter);
6386       return true;
6387     }
6388   }
6389   return false;
6390 }
6391
6392
6393 void JSObject::DefineElementAccessor(Handle<JSObject> object,
6394                                      uint32_t index,
6395                                      Handle<Object> getter,
6396                                      Handle<Object> setter,
6397                                      PropertyAttributes attributes) {
6398   switch (object->GetElementsKind()) {
6399     case FAST_SMI_ELEMENTS:
6400     case FAST_ELEMENTS:
6401     case FAST_DOUBLE_ELEMENTS:
6402     case FAST_HOLEY_SMI_ELEMENTS:
6403     case FAST_HOLEY_ELEMENTS:
6404     case FAST_HOLEY_DOUBLE_ELEMENTS:
6405       break;
6406
6407 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6408     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
6409     case TYPE##_ELEMENTS:                                                      \
6410
6411     TYPED_ARRAYS(TYPED_ARRAY_CASE)
6412 #undef TYPED_ARRAY_CASE
6413       // Ignore getters and setters on pixel and external array elements.
6414       return;
6415
6416     case DICTIONARY_ELEMENTS:
6417       if (UpdateGetterSetterInDictionary(object->element_dictionary(),
6418                                          index,
6419                                          *getter,
6420                                          *setter,
6421                                          attributes)) {
6422         return;
6423       }
6424       break;
6425     case SLOPPY_ARGUMENTS_ELEMENTS: {
6426       // Ascertain whether we have read-only properties or an existing
6427       // getter/setter pair in an arguments elements dictionary backing
6428       // store.
6429       FixedArray* parameter_map = FixedArray::cast(object->elements());
6430       uint32_t length = parameter_map->length();
6431       Object* probe =
6432           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
6433       if (probe == NULL || probe->IsTheHole()) {
6434         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
6435         if (arguments->IsDictionary()) {
6436           SeededNumberDictionary* dictionary =
6437               SeededNumberDictionary::cast(arguments);
6438           if (UpdateGetterSetterInDictionary(dictionary,
6439                                              index,
6440                                              *getter,
6441                                              *setter,
6442                                              attributes)) {
6443             return;
6444           }
6445         }
6446       }
6447       break;
6448     }
6449   }
6450
6451   Isolate* isolate = object->GetIsolate();
6452   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
6453   accessors->SetComponents(*getter, *setter);
6454
6455   SetElementCallback(object, index, accessors, attributes);
6456 }
6457
6458
6459 bool Map::DictionaryElementsInPrototypeChainOnly() {
6460   if (IsDictionaryElementsKind(elements_kind())) {
6461     return false;
6462   }
6463
6464   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6465     if (iter.GetCurrent()->IsJSProxy()) {
6466       // Be conservative, don't walk into proxies.
6467       return true;
6468     }
6469
6470     if (IsDictionaryElementsKind(
6471             JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
6472       return true;
6473     }
6474   }
6475
6476   return false;
6477 }
6478
6479
6480 void JSObject::SetElementCallback(Handle<JSObject> object,
6481                                   uint32_t index,
6482                                   Handle<Object> structure,
6483                                   PropertyAttributes attributes) {
6484   Heap* heap = object->GetHeap();
6485   PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0);
6486
6487   // Normalize elements to make this operation simple.
6488   bool had_dictionary_elements = object->HasDictionaryElements();
6489   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6490   DCHECK(object->HasDictionaryElements() ||
6491          object->HasDictionaryArgumentsElements());
6492   // Update the dictionary with the new ACCESSOR_CONSTANT property.
6493   dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6494                                            details);
6495   dictionary->set_requires_slow_elements();
6496
6497   // Update the dictionary backing store on the object.
6498   if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6499     // Also delete any parameter alias.
6500     //
6501     // TODO(kmillikin): when deleting the last parameter alias we could
6502     // switch to a direct backing store without the parameter map.  This
6503     // would allow GC of the context.
6504     FixedArray* parameter_map = FixedArray::cast(object->elements());
6505     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6506       parameter_map->set(index + 2, heap->the_hole_value());
6507     }
6508     parameter_map->set(1, *dictionary);
6509   } else {
6510     object->set_elements(*dictionary);
6511
6512     if (!had_dictionary_elements) {
6513       // KeyedStoreICs (at least the non-generic ones) need a reset.
6514       heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6515     }
6516   }
6517 }
6518
6519
6520 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6521                                    Handle<Name> name,
6522                                    Handle<Object> structure,
6523                                    PropertyAttributes attributes) {
6524   PropertyNormalizationMode mode = object->map()->is_prototype_map()
6525                                        ? KEEP_INOBJECT_PROPERTIES
6526                                        : CLEAR_INOBJECT_PROPERTIES;
6527   // Normalize object to make this operation simple.
6528   NormalizeProperties(object, mode, 0, "SetPropertyCallback");
6529
6530   // For the global object allocate a new map to invalidate the global inline
6531   // caches which have a global property cell reference directly in the code.
6532   if (object->IsGlobalObject()) {
6533     Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6534     DCHECK(new_map->is_dictionary_map());
6535 #if TRACE_MAPS
6536     if (FLAG_trace_maps) {
6537       PrintF("[TraceMaps: GlobalPropertyCallback from= %p to= %p ]\n",
6538              reinterpret_cast<void*>(object->map()),
6539              reinterpret_cast<void*>(*new_map));
6540     }
6541 #endif
6542     JSObject::MigrateToMap(object, new_map);
6543
6544     // When running crankshaft, changing the map is not enough. We
6545     // need to deoptimize all functions that rely on this global
6546     // object.
6547     Deoptimizer::DeoptimizeGlobalObject(*object);
6548   }
6549
6550   // Update the dictionary with the new ACCESSOR_CONSTANT property.
6551   PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0);
6552   SetNormalizedProperty(object, name, structure, details);
6553
6554   ReoptimizeIfPrototype(object);
6555 }
6556
6557
6558 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6559                                              Handle<Name> name,
6560                                              Handle<Object> getter,
6561                                              Handle<Object> setter,
6562                                              PropertyAttributes attributes) {
6563   Isolate* isolate = object->GetIsolate();
6564   // Check access rights if needed.
6565   if (object->IsAccessCheckNeeded() &&
6566       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6567     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6568     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6569     return isolate->factory()->undefined_value();
6570   }
6571
6572   if (object->IsJSGlobalProxy()) {
6573     PrototypeIterator iter(isolate, object);
6574     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6575     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6576     DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
6577                    name, getter, setter, attributes);
6578     return isolate->factory()->undefined_value();
6579   }
6580
6581   // Make sure that the top context does not change when doing callbacks or
6582   // interceptor calls.
6583   AssertNoContextChange ncc(isolate);
6584
6585   // Try to flatten before operating on the string.
6586   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6587
6588   uint32_t index = 0;
6589   bool is_element = name->AsArrayIndex(&index);
6590
6591   Handle<Object> old_value = isolate->factory()->the_hole_value();
6592   bool is_observed = object->map()->is_observed() &&
6593                      !isolate->IsInternallyUsedPropertyName(name);
6594   bool preexists = false;
6595   if (is_observed) {
6596     if (is_element) {
6597       Maybe<bool> maybe = HasOwnElement(object, index);
6598       // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6599       // uninitialized in this function".
6600       if (!maybe.has_value) {
6601         DCHECK(false);
6602         return isolate->factory()->undefined_value();
6603       }
6604       preexists = maybe.value;
6605       if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6606         old_value =
6607             Object::GetElement(isolate, object, index).ToHandleChecked();
6608       }
6609     } else {
6610       LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6611       CHECK(GetPropertyAttributes(&it).has_value);
6612       preexists = it.IsFound();
6613       if (preexists && (it.state() == LookupIterator::DATA ||
6614                         it.GetAccessors()->IsAccessorInfo())) {
6615         old_value = GetProperty(&it).ToHandleChecked();
6616       }
6617     }
6618   }
6619
6620   if (is_element) {
6621     DefineElementAccessor(object, index, getter, setter, attributes);
6622   } else {
6623     DCHECK(getter->IsSpecFunction() || getter->IsUndefined() ||
6624            getter->IsNull());
6625     DCHECK(setter->IsSpecFunction() || setter->IsUndefined() ||
6626            setter->IsNull());
6627     // At least one of the accessors needs to be a new value.
6628     DCHECK(!getter->IsNull() || !setter->IsNull());
6629     LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
6630     if (it.state() == LookupIterator::ACCESS_CHECK) {
6631       // We already did an access check before. We do have access.
6632       it.Next();
6633     }
6634     if (!getter->IsNull()) {
6635       it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6636     }
6637     if (!setter->IsNull()) {
6638       it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6639     }
6640   }
6641
6642   if (is_observed) {
6643     const char* type = preexists ? "reconfigure" : "add";
6644     RETURN_ON_EXCEPTION(
6645         isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
6646   }
6647
6648   return isolate->factory()->undefined_value();
6649 }
6650
6651
6652 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6653                                           Handle<AccessorInfo> info) {
6654   Isolate* isolate = object->GetIsolate();
6655   Factory* factory = isolate->factory();
6656   Handle<Name> name(Name::cast(info->name()));
6657
6658   // Check access rights if needed.
6659   if (object->IsAccessCheckNeeded() &&
6660       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6661     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6662     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6663     return factory->undefined_value();
6664   }
6665
6666   if (object->IsJSGlobalProxy()) {
6667     PrototypeIterator iter(isolate, object);
6668     if (iter.IsAtEnd()) return object;
6669     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6670     return SetAccessor(
6671         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info);
6672   }
6673
6674   // Make sure that the top context does not change when doing callbacks or
6675   // interceptor calls.
6676   AssertNoContextChange ncc(isolate);
6677
6678   // Try to flatten before operating on the string.
6679   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6680
6681   uint32_t index = 0;
6682   bool is_element = name->AsArrayIndex(&index);
6683
6684   if (is_element) {
6685     if (object->IsJSArray()) return factory->undefined_value();
6686
6687     // Accessors overwrite previous callbacks (cf. with getters/setters).
6688     switch (object->GetElementsKind()) {
6689       case FAST_SMI_ELEMENTS:
6690       case FAST_ELEMENTS:
6691       case FAST_DOUBLE_ELEMENTS:
6692       case FAST_HOLEY_SMI_ELEMENTS:
6693       case FAST_HOLEY_ELEMENTS:
6694       case FAST_HOLEY_DOUBLE_ELEMENTS:
6695         break;
6696
6697 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6698       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6699       case TYPE##_ELEMENTS:                                                    \
6700
6701       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6702 #undef TYPED_ARRAY_CASE
6703         // Ignore getters and setters on pixel and external array
6704         // elements.
6705         return factory->undefined_value();
6706
6707       case DICTIONARY_ELEMENTS:
6708         break;
6709       case SLOPPY_ARGUMENTS_ELEMENTS:
6710         UNIMPLEMENTED();
6711         break;
6712     }
6713
6714     SetElementCallback(object, index, info, info->property_attributes());
6715   } else {
6716     // Lookup the name.
6717     LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6718     CHECK(GetPropertyAttributes(&it).has_value);
6719     // ES5 forbids turning a property into an accessor if it's not
6720     // configurable. See 8.6.1 (Table 5).
6721     if (it.IsFound() && (it.IsReadOnly() || !it.IsConfigurable())) {
6722       return factory->undefined_value();
6723     }
6724
6725     SetPropertyCallback(object, name, info, info->property_attributes());
6726   }
6727
6728   return object;
6729 }
6730
6731
6732 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6733                                           Handle<Name> name,
6734                                           AccessorComponent component) {
6735   Isolate* isolate = object->GetIsolate();
6736
6737   // Make sure that the top context does not change when doing callbacks or
6738   // interceptor calls.
6739   AssertNoContextChange ncc(isolate);
6740
6741   // Make the lookup and include prototypes.
6742   uint32_t index = 0;
6743   if (name->AsArrayIndex(&index)) {
6744     for (PrototypeIterator iter(isolate, object,
6745                                 PrototypeIterator::START_AT_RECEIVER);
6746          !iter.IsAtEnd(); iter.Advance()) {
6747       Handle<Object> current = PrototypeIterator::GetCurrent(iter);
6748       // Check access rights if needed.
6749       if (current->IsAccessCheckNeeded() &&
6750           !isolate->MayNamedAccess(Handle<JSObject>::cast(current), name,
6751                                    v8::ACCESS_HAS)) {
6752         isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(current),
6753                                          v8::ACCESS_HAS);
6754         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6755         return isolate->factory()->undefined_value();
6756       }
6757
6758       if (current->IsJSObject() &&
6759           Handle<JSObject>::cast(current)->HasDictionaryElements()) {
6760         JSObject* js_object = JSObject::cast(*current);
6761         SeededNumberDictionary* dictionary = js_object->element_dictionary();
6762         int entry = dictionary->FindEntry(index);
6763         if (entry != SeededNumberDictionary::kNotFound) {
6764           Object* element = dictionary->ValueAt(entry);
6765           if (dictionary->DetailsAt(entry).type() == ACCESSOR_CONSTANT &&
6766               element->IsAccessorPair()) {
6767             return handle(AccessorPair::cast(element)->GetComponent(component),
6768                           isolate);
6769           }
6770         }
6771       }
6772     }
6773   } else {
6774     LookupIterator it(object, name,
6775                       LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6776     for (; it.IsFound(); it.Next()) {
6777       switch (it.state()) {
6778         case LookupIterator::INTERCEPTOR:
6779         case LookupIterator::NOT_FOUND:
6780         case LookupIterator::TRANSITION:
6781           UNREACHABLE();
6782
6783         case LookupIterator::ACCESS_CHECK:
6784           if (it.HasAccess(v8::ACCESS_HAS)) continue;
6785           isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
6786                                            v8::ACCESS_HAS);
6787           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6788           return isolate->factory()->undefined_value();
6789
6790         case LookupIterator::JSPROXY:
6791           return isolate->factory()->undefined_value();
6792
6793         case LookupIterator::DATA:
6794           continue;
6795         case LookupIterator::ACCESSOR: {
6796           Handle<Object> maybe_pair = it.GetAccessors();
6797           if (maybe_pair->IsAccessorPair()) {
6798             return handle(
6799                 AccessorPair::cast(*maybe_pair)->GetComponent(component),
6800                 isolate);
6801           }
6802         }
6803       }
6804     }
6805   }
6806   return isolate->factory()->undefined_value();
6807 }
6808
6809
6810 Object* JSObject::SlowReverseLookup(Object* value) {
6811   if (HasFastProperties()) {
6812     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6813     DescriptorArray* descs = map()->instance_descriptors();
6814     bool value_is_number = value->IsNumber();
6815     for (int i = 0; i < number_of_own_descriptors; i++) {
6816       if (descs->GetType(i) == DATA) {
6817         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
6818         if (IsUnboxedDoubleField(field_index)) {
6819           if (value_is_number) {
6820             double property = RawFastDoublePropertyAt(field_index);
6821             if (property == value->Number()) {
6822               return descs->GetKey(i);
6823             }
6824           }
6825         } else {
6826           Object* property = RawFastPropertyAt(field_index);
6827           if (field_index.is_double()) {
6828             DCHECK(property->IsMutableHeapNumber());
6829             if (value_is_number && property->Number() == value->Number()) {
6830               return descs->GetKey(i);
6831             }
6832           } else if (property == value) {
6833             return descs->GetKey(i);
6834           }
6835         }
6836       } else if (descs->GetType(i) == DATA_CONSTANT) {
6837         if (descs->GetConstant(i) == value) {
6838           return descs->GetKey(i);
6839         }
6840       }
6841     }
6842     return GetHeap()->undefined_value();
6843   } else {
6844     return property_dictionary()->SlowReverseLookup(value);
6845   }
6846 }
6847
6848
6849 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6850   Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6851       map->instance_type(), instance_size);
6852   result->SetPrototype(handle(map->prototype(), map->GetIsolate()));
6853   result->set_constructor(map->constructor());
6854   result->set_bit_field(map->bit_field());
6855   result->set_bit_field2(map->bit_field2());
6856   int new_bit_field3 = map->bit_field3();
6857   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6858   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6859   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6860                                           kInvalidEnumCacheSentinel);
6861   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6862   if (!map->is_dictionary_map()) {
6863     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6864   }
6865   new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
6866   result->set_bit_field3(new_bit_field3);
6867   return result;
6868 }
6869
6870
6871 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
6872                            const char* reason) {
6873   DCHECK(!fast_map->is_dictionary_map());
6874
6875   Isolate* isolate = fast_map->GetIsolate();
6876   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6877                              isolate);
6878   bool use_cache = !maybe_cache->IsUndefined();
6879   Handle<NormalizedMapCache> cache;
6880   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6881
6882   Handle<Map> new_map;
6883   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6884 #ifdef VERIFY_HEAP
6885     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6886 #endif
6887 #ifdef ENABLE_SLOW_DCHECKS
6888     if (FLAG_enable_slow_asserts) {
6889       // The cached map should match newly created normalized map bit-by-bit,
6890       // except for the code cache, which can contain some ics which can be
6891       // applied to the shared map.
6892       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6893
6894       DCHECK(memcmp(fresh->address(),
6895                     new_map->address(),
6896                     Map::kCodeCacheOffset) == 0);
6897       STATIC_ASSERT(Map::kDependentCodeOffset ==
6898                     Map::kCodeCacheOffset + kPointerSize);
6899       int offset = Map::kDependentCodeOffset + kPointerSize;
6900       DCHECK(memcmp(fresh->address() + offset,
6901                     new_map->address() + offset,
6902                     Map::kSize - offset) == 0);
6903     }
6904 #endif
6905   } else {
6906     new_map = Map::CopyNormalized(fast_map, mode);
6907     if (use_cache) {
6908       cache->Set(fast_map, new_map);
6909       isolate->counters()->normalized_maps()->Increment();
6910     }
6911 #if TRACE_MAPS
6912     if (FLAG_trace_maps) {
6913       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
6914              reinterpret_cast<void*>(*fast_map),
6915              reinterpret_cast<void*>(*new_map), reason);
6916     }
6917 #endif
6918   }
6919   fast_map->NotifyLeafMapLayoutChange();
6920   return new_map;
6921 }
6922
6923
6924 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6925                                 PropertyNormalizationMode mode) {
6926   int new_instance_size = map->instance_size();
6927   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6928     new_instance_size -= map->inobject_properties() * kPointerSize;
6929   }
6930
6931   Handle<Map> result = RawCopy(map, new_instance_size);
6932
6933   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6934     result->set_inobject_properties(map->inobject_properties());
6935   }
6936
6937   result->set_dictionary_map(true);
6938   result->set_migration_target(false);
6939
6940 #ifdef VERIFY_HEAP
6941   if (FLAG_verify_heap) result->DictionaryMapVerify();
6942 #endif
6943
6944   return result;
6945 }
6946
6947
6948 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6949   Handle<Map> result = RawCopy(map, map->instance_size());
6950
6951   // Please note instance_type and instance_size are set when allocated.
6952   result->set_inobject_properties(map->inobject_properties());
6953   result->set_unused_property_fields(map->unused_property_fields());
6954
6955   result->set_pre_allocated_property_fields(
6956       map->pre_allocated_property_fields());
6957   result->ClearCodeCache(map->GetHeap());
6958   map->NotifyLeafMapLayoutChange();
6959   return result;
6960 }
6961
6962
6963 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6964                                  Handle<DescriptorArray> descriptors,
6965                                  Descriptor* descriptor) {
6966   // Sanity check. This path is only to be taken if the map owns its descriptor
6967   // array, implying that its NumberOfOwnDescriptors equals the number of
6968   // descriptors in the descriptor array.
6969   DCHECK(map->NumberOfOwnDescriptors() ==
6970          map->instance_descriptors()->number_of_descriptors());
6971
6972   Handle<Map> result = CopyDropDescriptors(map);
6973   Handle<Name> name = descriptor->GetKey();
6974
6975   // Ensure there's space for the new descriptor in the shared descriptor array.
6976   if (descriptors->NumberOfSlackDescriptors() == 0) {
6977     int old_size = descriptors->number_of_descriptors();
6978     if (old_size == 0) {
6979       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6980     } else {
6981       EnsureDescriptorSlack(
6982           map, SlackForArraySize(old_size, kMaxNumberOfDescriptors));
6983       descriptors = handle(map->instance_descriptors());
6984     }
6985   }
6986
6987   Handle<LayoutDescriptor> layout_descriptor =
6988       FLAG_unbox_double_fields
6989           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
6990           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
6991
6992   {
6993     DisallowHeapAllocation no_gc;
6994     descriptors->Append(descriptor);
6995     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6996   }
6997
6998   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6999   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
7000
7001   return result;
7002 }
7003
7004
7005 #if TRACE_MAPS
7006
7007 // static
7008 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
7009   if (FLAG_trace_maps) {
7010     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
7011            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
7012     name->NameShortPrint();
7013     PrintF(" ]\n");
7014   }
7015 }
7016
7017
7018 // static
7019 void Map::TraceAllTransitions(Map* map) {
7020   if (!map->HasTransitionArray()) return;
7021   TransitionArray* transitions = map->transitions();
7022   for (int i = 0; i < transitions->number_of_transitions(); ++i) {
7023     Map* target = transitions->GetTarget(i);
7024     Map::TraceTransition("Transition", map, target, transitions->GetKey(i));
7025     Map::TraceAllTransitions(target);
7026   }
7027 }
7028
7029 #endif  // TRACE_MAPS
7030
7031
7032 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7033                             Handle<Name> name, SimpleTransitionFlag flag) {
7034   parent->set_owns_descriptors(false);
7035   if (parent->is_prototype_map()) {
7036     DCHECK(child->is_prototype_map());
7037 #if TRACE_MAPS
7038     Map::TraceTransition("NoTransition", *parent, *child, *name);
7039 #endif
7040   } else {
7041     Handle<TransitionArray> transitions =
7042         TransitionArray::Insert(parent, name, child, flag);
7043     if (!parent->HasTransitionArray() ||
7044         *transitions != parent->transitions()) {
7045       parent->set_transitions(*transitions);
7046     }
7047     child->SetBackPointer(*parent);
7048     if (child->prototype()->IsJSObject()) {
7049       Handle<JSObject> proto(JSObject::cast(child->prototype()));
7050       if (!child->ShouldRegisterAsPrototypeUser(proto)) {
7051         JSObject::UnregisterPrototypeUser(proto, child);
7052       }
7053     }
7054 #if TRACE_MAPS
7055     Map::TraceTransition("Transition", *parent, *child, *name);
7056 #endif
7057   }
7058 }
7059
7060
7061 Handle<Map> Map::CopyReplaceDescriptors(
7062     Handle<Map> map, Handle<DescriptorArray> descriptors,
7063     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
7064     MaybeHandle<Name> maybe_name, const char* reason,
7065     SimpleTransitionFlag simple_flag) {
7066   DCHECK(descriptors->IsSortedNoDuplicates());
7067
7068   Handle<Map> result = CopyDropDescriptors(map);
7069
7070   if (!map->is_prototype_map()) {
7071     if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
7072       result->InitializeDescriptors(*descriptors, *layout_descriptor);
7073
7074       Handle<Name> name;
7075       CHECK(maybe_name.ToHandle(&name));
7076       ConnectTransition(map, result, name, simple_flag);
7077     } else {
7078       int length = descriptors->number_of_descriptors();
7079       for (int i = 0; i < length; i++) {
7080         descriptors->SetRepresentation(i, Representation::Tagged());
7081         if (descriptors->GetDetails(i).type() == DATA) {
7082           descriptors->SetValue(i, HeapType::Any());
7083         }
7084       }
7085       result->InitializeDescriptors(*descriptors,
7086                                     LayoutDescriptor::FastPointerLayout());
7087     }
7088   } else {
7089     result->InitializeDescriptors(*descriptors, *layout_descriptor);
7090   }
7091 #if TRACE_MAPS
7092   if (FLAG_trace_maps &&
7093       // Mirror conditions above that did not call ConnectTransition().
7094       (map->is_prototype_map() ||
7095        !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) {
7096     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
7097            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
7098            reason);
7099   }
7100 #endif
7101
7102   return result;
7103 }
7104
7105
7106 // Since this method is used to rewrite an existing transition tree, it can
7107 // always insert transitions without checking.
7108 Handle<Map> Map::CopyInstallDescriptors(
7109     Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
7110     Handle<LayoutDescriptor> full_layout_descriptor) {
7111   DCHECK(descriptors->IsSortedNoDuplicates());
7112
7113   Handle<Map> result = CopyDropDescriptors(map);
7114
7115   result->set_instance_descriptors(*descriptors);
7116   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
7117
7118   int unused_property_fields = map->unused_property_fields();
7119   PropertyDetails details = descriptors->GetDetails(new_descriptor);
7120   if (details.location() == kField) {
7121     unused_property_fields = map->unused_property_fields() - 1;
7122     if (unused_property_fields < 0) {
7123       unused_property_fields += JSObject::kFieldsAdded;
7124     }
7125   }
7126   result->set_unused_property_fields(unused_property_fields);
7127
7128   if (FLAG_unbox_double_fields) {
7129     Handle<LayoutDescriptor> layout_descriptor =
7130         LayoutDescriptor::AppendIfFastOrUseFull(map, details,
7131                                                 full_layout_descriptor);
7132     result->set_layout_descriptor(*layout_descriptor);
7133 #ifdef VERIFY_HEAP
7134     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
7135     if (FLAG_verify_heap) {
7136       CHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
7137     }
7138 #else
7139     SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
7140 #endif
7141     result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
7142   }
7143
7144   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
7145   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
7146
7147   return result;
7148 }
7149
7150
7151 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
7152                                     TransitionFlag flag) {
7153   if (flag == INSERT_TRANSITION) {
7154     DCHECK(!map->HasElementsTransition() ||
7155         ((map->elements_transition_map()->elements_kind() ==
7156           DICTIONARY_ELEMENTS ||
7157           IsExternalArrayElementsKind(
7158               map->elements_transition_map()->elements_kind())) &&
7159          (kind == DICTIONARY_ELEMENTS ||
7160           IsExternalArrayElementsKind(kind))));
7161     DCHECK(!IsFastElementsKind(kind) ||
7162            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
7163     DCHECK(kind != map->elements_kind());
7164   }
7165
7166   bool insert_transition = flag == INSERT_TRANSITION &&
7167                            map->CanHaveMoreTransitions() &&
7168                            !map->HasElementsTransition();
7169
7170   if (insert_transition) {
7171     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
7172     new_map->set_elements_kind(kind);
7173
7174     ConnectElementsTransition(map, new_map);
7175
7176     return new_map;
7177   }
7178
7179   // Create a new free-floating map only if we are not allowed to store it.
7180   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
7181   new_map->set_elements_kind(kind);
7182   return new_map;
7183 }
7184
7185
7186 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7187   DCHECK(!map->is_observed());
7188
7189   Isolate* isolate = map->GetIsolate();
7190
7191   bool insert_transition =
7192       map->CanHaveMoreTransitions() && !map->is_prototype_map();
7193
7194   if (insert_transition) {
7195     Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
7196     new_map->set_is_observed();
7197
7198     Handle<Name> name = isolate->factory()->observed_symbol();
7199     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
7200     return new_map;
7201   }
7202
7203   // Create a new free-floating map only if we are not allowed to store it.
7204   Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
7205   new_map->set_is_observed();
7206   return new_map;
7207 }
7208
7209
7210 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
7211   DCHECK(!map->is_prototype_map());
7212   Handle<Map> new_map = CopyDropDescriptors(map);
7213
7214   if (map->owns_descriptors()) {
7215     // In case the map owned its own descriptors, share the descriptors and
7216     // transfer ownership to the new map.
7217     // The properties did not change, so reuse descriptors.
7218     new_map->InitializeDescriptors(map->instance_descriptors(),
7219                                    map->GetLayoutDescriptor());
7220   } else {
7221     // In case the map did not own its own descriptors, a split is forced by
7222     // copying the map; creating a new descriptor array cell.
7223     Handle<DescriptorArray> descriptors(map->instance_descriptors());
7224     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7225     Handle<DescriptorArray> new_descriptors =
7226         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7227     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7228                                                    map->GetIsolate());
7229     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
7230   }
7231
7232 #if TRACE_MAPS
7233   if (FLAG_trace_maps) {
7234     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
7235            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
7236            reason);
7237   }
7238 #endif
7239
7240   return new_map;
7241 }
7242
7243
7244 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
7245   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7246   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7247   Handle<DescriptorArray> new_descriptors =
7248       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7249   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7250                                                  map->GetIsolate());
7251   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7252                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
7253                                 SPECIAL_TRANSITION);
7254 }
7255
7256
7257 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
7258   Handle<Map> copy =
7259       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
7260
7261   // Check that we do not overflow the instance size when adding the extra
7262   // inobject properties. If the instance size overflows, we allocate as many
7263   // properties as we can as inobject properties.
7264   int max_extra_properties =
7265       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
7266
7267   if (inobject_properties > max_extra_properties) {
7268     inobject_properties = max_extra_properties;
7269   }
7270
7271   int new_instance_size =
7272       JSObject::kHeaderSize + kPointerSize * inobject_properties;
7273
7274   // Adjust the map with the extra inobject properties.
7275   copy->set_inobject_properties(inobject_properties);
7276   copy->set_unused_property_fields(inobject_properties);
7277   copy->set_instance_size(new_instance_size);
7278   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
7279   return copy;
7280 }
7281
7282
7283 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
7284                                           PropertyAttributes attrs_to_add,
7285                                           Handle<Symbol> transition_marker,
7286                                           const char* reason) {
7287   int num_descriptors = map->NumberOfOwnDescriptors();
7288   Isolate* isolate = map->GetIsolate();
7289   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
7290       handle(map->instance_descriptors(), isolate), num_descriptors,
7291       attrs_to_add);
7292   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7293                                                  isolate);
7294   Handle<Map> new_map = CopyReplaceDescriptors(
7295       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
7296       transition_marker, reason, SPECIAL_TRANSITION);
7297   new_map->set_is_extensible(false);
7298   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7299   return new_map;
7300 }
7301
7302
7303 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
7304   PropertyDetails details = GetDetails(descriptor);
7305   switch (details.type()) {
7306     case DATA:
7307       return value->FitsRepresentation(details.representation()) &&
7308              GetFieldType(descriptor)->NowContains(value);
7309
7310     case DATA_CONSTANT:
7311       DCHECK(GetConstant(descriptor) != value ||
7312              value->FitsRepresentation(details.representation()));
7313       return GetConstant(descriptor) == value;
7314
7315     case ACCESSOR:
7316     case ACCESSOR_CONSTANT:
7317       return false;
7318   }
7319
7320   UNREACHABLE();
7321   return false;
7322 }
7323
7324
7325 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7326                                         Handle<Object> value) {
7327   // Dictionaries can store any property value.
7328   if (map->is_dictionary_map()) return map;
7329
7330   // Migrate to the newest map before storing the property.
7331   map = Update(map);
7332
7333   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7334
7335   if (descriptors->CanHoldValue(descriptor, *value)) return map;
7336
7337   Isolate* isolate = map->GetIsolate();
7338   PropertyAttributes attributes =
7339       descriptors->GetDetails(descriptor).attributes();
7340   Representation representation = value->OptimalRepresentation();
7341   Handle<HeapType> type = value->OptimalType(isolate, representation);
7342
7343   return ReconfigureProperty(map, descriptor, kData, attributes, representation,
7344                              type, FORCE_FIELD);
7345 }
7346
7347
7348 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7349                                           Handle<Object> value,
7350                                           PropertyAttributes attributes,
7351                                           StoreFromKeyed store_mode) {
7352   // Dictionary maps can always have additional data properties.
7353   if (map->is_dictionary_map()) return map;
7354
7355   // Migrate to the newest map before storing the property.
7356   map = Update(map);
7357
7358   int index = map->SearchTransition(kData, *name, attributes);
7359   if (index != TransitionArray::kNotFound) {
7360     Handle<Map> transition(map->GetTransition(index));
7361     int descriptor = transition->LastAdded();
7362
7363     DCHECK_EQ(attributes, transition->instance_descriptors()
7364                               ->GetDetails(descriptor)
7365                               .attributes());
7366
7367     return Map::PrepareForDataProperty(transition, descriptor, value);
7368   }
7369
7370   TransitionFlag flag = INSERT_TRANSITION;
7371   MaybeHandle<Map> maybe_map;
7372   if (value->IsJSFunction()) {
7373     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7374   } else if (!map->TooManyFastProperties(store_mode)) {
7375     Isolate* isolate = name->GetIsolate();
7376     Representation representation = value->OptimalRepresentation();
7377     Handle<HeapType> type = value->OptimalType(isolate, representation);
7378     maybe_map =
7379         Map::CopyWithField(map, name, type, attributes, representation, flag);
7380   }
7381
7382   Handle<Map> result;
7383   if (!maybe_map.ToHandle(&result)) {
7384 #if TRACE_MAPS
7385     if (FLAG_trace_maps) {
7386       Vector<char> name_buffer = Vector<char>::New(100);
7387       name->NameShortPrint(name_buffer);
7388       Vector<char> buffer = Vector<char>::New(128);
7389       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
7390       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
7391     }
7392 #endif
7393     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
7394                           "TooManyFastProperties");
7395   }
7396
7397   return result;
7398 }
7399
7400
7401 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
7402                                              PropertyKind kind,
7403                                              PropertyAttributes attributes) {
7404   // Dictionaries have to be reconfigured in-place.
7405   DCHECK(!map->is_dictionary_map());
7406
7407   if (!map->GetBackPointer()->IsMap()) {
7408     // There is no benefit from reconstructing transition tree for maps without
7409     // back pointers.
7410     return CopyGeneralizeAllRepresentations(
7411         map, descriptor, FORCE_FIELD, kind, attributes,
7412         "GenAll_AttributesMismatchProtoMap");
7413   }
7414
7415   if (FLAG_trace_generalization) {
7416     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
7417   }
7418
7419   Isolate* isolate = map->GetIsolate();
7420   Handle<Map> new_map = ReconfigureProperty(
7421       map, descriptor, kind, attributes, Representation::None(),
7422       HeapType::None(isolate), FORCE_FIELD);
7423   return new_map;
7424 }
7425
7426
7427 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
7428                                               Handle<Name> name,
7429                                               AccessorComponent component,
7430                                               Handle<Object> accessor,
7431                                               PropertyAttributes attributes) {
7432   Isolate* isolate = name->GetIsolate();
7433
7434   // Dictionary maps can always have additional data properties.
7435   if (map->is_dictionary_map()) {
7436     // For global objects, property cells are inlined. We need to change the
7437     // map.
7438     if (map->IsGlobalObjectMap()) return Copy(map, "GlobalAccessor");
7439     return map;
7440   }
7441
7442   // Migrate to the newest map before transitioning to the new property.
7443   map = Update(map);
7444
7445   PropertyNormalizationMode mode = map->is_prototype_map()
7446                                        ? KEEP_INOBJECT_PROPERTIES
7447                                        : CLEAR_INOBJECT_PROPERTIES;
7448
7449   int index = map->SearchTransition(kAccessor, *name, attributes);
7450   if (index != TransitionArray::kNotFound) {
7451     Handle<Map> transition(map->GetTransition(index));
7452     DescriptorArray* descriptors = transition->instance_descriptors();
7453     int descriptor = transition->LastAdded();
7454     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7455
7456     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7457     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7458
7459     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7460     if (!maybe_pair->IsAccessorPair()) {
7461       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
7462     }
7463
7464     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
7465     if (pair->get(component) != *accessor) {
7466       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
7467     }
7468
7469     return transition;
7470   }
7471
7472   Handle<AccessorPair> pair;
7473   DescriptorArray* old_descriptors = map->instance_descriptors();
7474   int descriptor = old_descriptors->SearchWithCache(*name, *map);
7475   if (descriptor != DescriptorArray::kNotFound) {
7476     if (descriptor != map->LastAdded()) {
7477       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
7478     }
7479     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
7480     if (old_details.type() != ACCESSOR_CONSTANT) {
7481       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
7482     }
7483
7484     if (old_details.attributes() != attributes) {
7485       return Map::Normalize(map, mode, "AccessorsWithAttributes");
7486     }
7487
7488     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
7489     if (!maybe_pair->IsAccessorPair()) {
7490       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
7491     }
7492
7493     Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
7494     if (current == *accessor) return map;
7495
7496     if (!current->IsTheHole()) {
7497       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
7498     }
7499
7500     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
7501   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
7502              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
7503     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
7504   } else {
7505     pair = isolate->factory()->NewAccessorPair();
7506   }
7507
7508   pair->set(component, *accessor);
7509   TransitionFlag flag = INSERT_TRANSITION;
7510   AccessorConstantDescriptor new_desc(name, pair, attributes);
7511   return Map::CopyInsertDescriptor(map, &new_desc, flag);
7512 }
7513
7514
7515 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7516                                    Descriptor* descriptor,
7517                                    TransitionFlag flag) {
7518   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7519
7520   // Ensure the key is unique.
7521   descriptor->KeyToUniqueName();
7522
7523   if (flag == INSERT_TRANSITION &&
7524       map->owns_descriptors() &&
7525       map->CanHaveMoreTransitions()) {
7526     return ShareDescriptor(map, descriptors, descriptor);
7527   }
7528
7529   int nof = map->NumberOfOwnDescriptors();
7530   Handle<DescriptorArray> new_descriptors =
7531       DescriptorArray::CopyUpTo(descriptors, nof, 1);
7532   new_descriptors->Append(descriptor);
7533
7534   Handle<LayoutDescriptor> new_layout_descriptor =
7535       FLAG_unbox_double_fields
7536           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
7537           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
7538
7539   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7540                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
7541                                 SIMPLE_PROPERTY_TRANSITION);
7542 }
7543
7544
7545 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7546                                       Descriptor* descriptor,
7547                                       TransitionFlag flag) {
7548   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7549
7550   // Ensure the key is unique.
7551   descriptor->KeyToUniqueName();
7552
7553   // We replace the key if it is already present.
7554   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7555   if (index != DescriptorArray::kNotFound) {
7556     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7557   }
7558   return CopyAddDescriptor(map, descriptor, flag);
7559 }
7560
7561
7562 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7563     Handle<DescriptorArray> desc,
7564     int enumeration_index,
7565     int slack) {
7566   return DescriptorArray::CopyUpToAddAttributes(
7567       desc, enumeration_index, NONE, slack);
7568 }
7569
7570
7571 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7572     Handle<DescriptorArray> desc,
7573     int enumeration_index,
7574     PropertyAttributes attributes,
7575     int slack) {
7576   if (enumeration_index + slack == 0) {
7577     return desc->GetIsolate()->factory()->empty_descriptor_array();
7578   }
7579
7580   int size = enumeration_index;
7581
7582   Handle<DescriptorArray> descriptors =
7583       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7584   DescriptorArray::WhitenessWitness witness(*descriptors);
7585
7586   if (attributes != NONE) {
7587     for (int i = 0; i < size; ++i) {
7588       Object* value = desc->GetValue(i);
7589       Name* key = desc->GetKey(i);
7590       PropertyDetails details = desc->GetDetails(i);
7591       // Bulk attribute changes never affect private properties.
7592       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7593         int mask = DONT_DELETE | DONT_ENUM;
7594         // READ_ONLY is an invalid attribute for JS setters/getters.
7595         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
7596           mask |= READ_ONLY;
7597         }
7598         details = details.CopyAddAttributes(
7599             static_cast<PropertyAttributes>(attributes & mask));
7600       }
7601       Descriptor inner_desc(
7602           handle(key), handle(value, desc->GetIsolate()), details);
7603       descriptors->Set(i, &inner_desc, witness);
7604     }
7605   } else {
7606     for (int i = 0; i < size; ++i) {
7607       descriptors->CopyFrom(i, *desc, witness);
7608     }
7609   }
7610
7611   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7612
7613   return descriptors;
7614 }
7615
7616
7617 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7618                                        Handle<DescriptorArray> descriptors,
7619                                        Descriptor* descriptor,
7620                                        int insertion_index,
7621                                        TransitionFlag flag) {
7622   // Ensure the key is unique.
7623   descriptor->KeyToUniqueName();
7624
7625   Handle<Name> key = descriptor->GetKey();
7626   DCHECK(*key == descriptors->GetKey(insertion_index));
7627
7628   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7629       descriptors, map->NumberOfOwnDescriptors());
7630
7631   new_descriptors->Replace(insertion_index, descriptor);
7632   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
7633       map, new_descriptors, new_descriptors->number_of_descriptors());
7634
7635   SimpleTransitionFlag simple_flag =
7636       (insertion_index == descriptors->number_of_descriptors() - 1)
7637           ? SIMPLE_PROPERTY_TRANSITION
7638           : PROPERTY_TRANSITION;
7639   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7640                                 flag, key, "CopyReplaceDescriptor",
7641                                 simple_flag);
7642 }
7643
7644
7645 void Map::UpdateCodeCache(Handle<Map> map,
7646                           Handle<Name> name,
7647                           Handle<Code> code) {
7648   Isolate* isolate = map->GetIsolate();
7649   HandleScope scope(isolate);
7650   // Allocate the code cache if not present.
7651   if (map->code_cache()->IsFixedArray()) {
7652     Handle<Object> result = isolate->factory()->NewCodeCache();
7653     map->set_code_cache(*result);
7654   }
7655
7656   // Update the code cache.
7657   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7658   CodeCache::Update(code_cache, name, code);
7659 }
7660
7661
7662 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7663   // Do a lookup if a code cache exists.
7664   if (!code_cache()->IsFixedArray()) {
7665     return CodeCache::cast(code_cache())->Lookup(name, flags);
7666   } else {
7667     return GetHeap()->undefined_value();
7668   }
7669 }
7670
7671
7672 int Map::IndexInCodeCache(Object* name, Code* code) {
7673   // Get the internal index if a code cache exists.
7674   if (!code_cache()->IsFixedArray()) {
7675     return CodeCache::cast(code_cache())->GetIndex(name, code);
7676   }
7677   return -1;
7678 }
7679
7680
7681 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7682   // No GC is supposed to happen between a call to IndexInCodeCache and
7683   // RemoveFromCodeCache so the code cache must be there.
7684   DCHECK(!code_cache()->IsFixedArray());
7685   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7686 }
7687
7688
7689 // An iterator over all map transitions in an descriptor array, reusing the
7690 // constructor field of the map while it is running. Negative values in
7691 // the constructor field indicate an active map transition iteration. The
7692 // original constructor is restored after iterating over all entries.
7693 class IntrusiveMapTransitionIterator {
7694  public:
7695   IntrusiveMapTransitionIterator(
7696       Map* map, TransitionArray* transition_array, Object* constructor)
7697       : map_(map),
7698         transition_array_(transition_array),
7699         constructor_(constructor) { }
7700
7701   void StartIfNotStarted() {
7702     DCHECK(!(*IteratorField())->IsSmi() || IsIterating());
7703     if (!(*IteratorField())->IsSmi()) {
7704       DCHECK(*IteratorField() == constructor_);
7705       *IteratorField() = Smi::FromInt(-1);
7706     }
7707   }
7708
7709   bool IsIterating() {
7710     return (*IteratorField())->IsSmi() &&
7711            Smi::cast(*IteratorField())->value() < 0;
7712   }
7713
7714   Map* Next() {
7715     DCHECK(IsIterating());
7716     int value = Smi::cast(*IteratorField())->value();
7717     int index = -value - 1;
7718     int number_of_transitions = transition_array_->number_of_transitions();
7719     if (index < number_of_transitions) {
7720       *IteratorField() = Smi::FromInt(value - 1);
7721       return transition_array_->GetTarget(index);
7722     }
7723
7724     *IteratorField() = constructor_;
7725     return NULL;
7726   }
7727
7728  private:
7729   Object** IteratorField() {
7730     return HeapObject::RawField(map_, Map::kConstructorOffset);
7731   }
7732
7733   Map* map_;
7734   TransitionArray* transition_array_;
7735   Object* constructor_;
7736 };
7737
7738
7739 // An iterator over all prototype transitions, reusing the constructor field
7740 // of the map while it is running.  Positive values in the constructor field
7741 // indicate an active prototype transition iteration. The original constructor
7742 // is restored after iterating over all entries.
7743 class IntrusivePrototypeTransitionIterator {
7744  public:
7745   IntrusivePrototypeTransitionIterator(
7746       Map* map, HeapObject* proto_trans, Object* constructor)
7747       : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7748
7749   void StartIfNotStarted() {
7750     if (!(*IteratorField())->IsSmi()) {
7751       DCHECK(*IteratorField() == constructor_);
7752       *IteratorField() = Smi::FromInt(0);
7753     }
7754   }
7755
7756   bool IsIterating() {
7757     return (*IteratorField())->IsSmi() &&
7758            Smi::cast(*IteratorField())->value() >= 0;
7759   }
7760
7761   Map* Next() {
7762     DCHECK(IsIterating());
7763     int transitionNumber = Smi::cast(*IteratorField())->value();
7764     if (transitionNumber < NumberOfTransitions()) {
7765       *IteratorField() = Smi::FromInt(transitionNumber + 1);
7766       return GetTransition(transitionNumber);
7767     }
7768     *IteratorField() = constructor_;
7769     return NULL;
7770   }
7771
7772  private:
7773   Object** IteratorField() {
7774     return HeapObject::RawField(map_, Map::kConstructorOffset);
7775   }
7776
7777   int NumberOfTransitions() {
7778     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7779     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7780     return Smi::cast(num)->value();
7781   }
7782
7783   Map* GetTransition(int transitionNumber) {
7784     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7785     int index = Map::kProtoTransitionHeaderSize + transitionNumber;
7786     return Map::cast(proto_trans->get(index));
7787   }
7788
7789   Map* map_;
7790   HeapObject* proto_trans_;
7791   Object* constructor_;
7792 };
7793
7794
7795 // To traverse the transition tree iteratively, we have to store two kinds of
7796 // information in a map: The parent map in the traversal and which children of a
7797 // node have already been visited. To do this without additional memory, we
7798 // temporarily reuse two fields with known values:
7799 //
7800 //  (1) The map of the map temporarily holds the parent, and is restored to the
7801 //      meta map afterwards.
7802 //
7803 //  (2) The info which children have already been visited depends on which part
7804 //      of the map we currently iterate. We use the constructor field of the
7805 //      map to store the current index. We can do that because the constructor
7806 //      is the same for all involved maps.
7807 //
7808 //    (a) If we currently follow normal map transitions, we temporarily store
7809 //        the current index in the constructor field, and restore it to the
7810 //        original constructor afterwards. Note that a single descriptor can
7811 //        have 0, 1, or 2 transitions.
7812 //
7813 //    (b) If we currently follow prototype transitions, we temporarily store
7814 //        the current index in the constructor field, and restore it to the
7815 //        original constructor afterwards.
7816 //
7817 // Note that the child iterator is just a concatenation of two iterators: One
7818 // iterating over map transitions and one iterating over prototype transisitons.
7819 class TraversableMap : public Map {
7820  public:
7821   // Record the parent in the traversal within this map. Note that this destroys
7822   // this map's map!
7823   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7824
7825   // Reset the current map's map, returning the parent previously stored in it.
7826   TraversableMap* GetAndResetParent() {
7827     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7828     set_map_no_write_barrier(GetHeap()->meta_map());
7829     return old_parent;
7830   }
7831
7832   // If we have an unvisited child map, return that one and advance. If we have
7833   // none, return NULL and restore the overwritten constructor field.
7834   TraversableMap* ChildIteratorNext(Object* constructor) {
7835     if (!HasTransitionArray()) return NULL;
7836
7837     TransitionArray* transition_array = transitions();
7838     if (transition_array->HasPrototypeTransitions()) {
7839       HeapObject* proto_transitions =
7840           transition_array->GetPrototypeTransitions();
7841       IntrusivePrototypeTransitionIterator proto_iterator(this,
7842                                                           proto_transitions,
7843                                                           constructor);
7844       proto_iterator.StartIfNotStarted();
7845       if (proto_iterator.IsIterating()) {
7846         Map* next = proto_iterator.Next();
7847         if (next != NULL) return static_cast<TraversableMap*>(next);
7848       }
7849     }
7850
7851     IntrusiveMapTransitionIterator transition_iterator(this,
7852                                                        transition_array,
7853                                                        constructor);
7854     transition_iterator.StartIfNotStarted();
7855     if (transition_iterator.IsIterating()) {
7856       Map* next = transition_iterator.Next();
7857       if (next != NULL) return static_cast<TraversableMap*>(next);
7858     }
7859
7860     return NULL;
7861   }
7862 };
7863
7864
7865 // Traverse the transition tree in postorder without using the C++ stack by
7866 // doing pointer reversal.
7867 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7868   // Make sure that we do not allocate in the callback.
7869   DisallowHeapAllocation no_allocation;
7870
7871   TraversableMap* current = static_cast<TraversableMap*>(this);
7872   // Get the root constructor here to restore it later when finished iterating
7873   // over maps.
7874   Object* root_constructor = constructor();
7875   while (true) {
7876     TraversableMap* child = current->ChildIteratorNext(root_constructor);
7877     if (child != NULL) {
7878       child->SetParent(current);
7879       current = child;
7880     } else {
7881       TraversableMap* parent = current->GetAndResetParent();
7882       callback(current, data);
7883       if (current == this) break;
7884       current = parent;
7885     }
7886   }
7887 }
7888
7889
7890 void CodeCache::Update(
7891     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7892   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7893   // a large number and therefore they need to go into a hash table. They are
7894   // used to load global properties from cells.
7895   if (code->type() == Code::NORMAL) {
7896     // Make sure that a hash table is allocated for the normal load code cache.
7897     if (code_cache->normal_type_cache()->IsUndefined()) {
7898       Handle<Object> result =
7899           CodeCacheHashTable::New(code_cache->GetIsolate(),
7900                                   CodeCacheHashTable::kInitialSize);
7901       code_cache->set_normal_type_cache(*result);
7902     }
7903     UpdateNormalTypeCache(code_cache, name, code);
7904   } else {
7905     DCHECK(code_cache->default_cache()->IsFixedArray());
7906     UpdateDefaultCache(code_cache, name, code);
7907   }
7908 }
7909
7910
7911 void CodeCache::UpdateDefaultCache(
7912     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7913   // When updating the default code cache we disregard the type encoded in the
7914   // flags. This allows call constant stubs to overwrite call field
7915   // stubs, etc.
7916   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7917
7918   // First check whether we can update existing code cache without
7919   // extending it.
7920   Handle<FixedArray> cache = handle(code_cache->default_cache());
7921   int length = cache->length();
7922   {
7923     DisallowHeapAllocation no_alloc;
7924     int deleted_index = -1;
7925     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7926       Object* key = cache->get(i);
7927       if (key->IsNull()) {
7928         if (deleted_index < 0) deleted_index = i;
7929         continue;
7930       }
7931       if (key->IsUndefined()) {
7932         if (deleted_index >= 0) i = deleted_index;
7933         cache->set(i + kCodeCacheEntryNameOffset, *name);
7934         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7935         return;
7936       }
7937       if (name->Equals(Name::cast(key))) {
7938         Code::Flags found =
7939             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7940         if (Code::RemoveTypeFromFlags(found) == flags) {
7941           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7942           return;
7943         }
7944       }
7945     }
7946
7947     // Reached the end of the code cache.  If there were deleted
7948     // elements, reuse the space for the first of them.
7949     if (deleted_index >= 0) {
7950       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7951       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7952       return;
7953     }
7954   }
7955
7956   // Extend the code cache with some new entries (at least one). Must be a
7957   // multiple of the entry size.
7958   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7959   new_length = new_length - new_length % kCodeCacheEntrySize;
7960   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7961   cache = FixedArray::CopySize(cache, new_length);
7962
7963   // Add the (name, code) pair to the new cache.
7964   cache->set(length + kCodeCacheEntryNameOffset, *name);
7965   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7966   code_cache->set_default_cache(*cache);
7967 }
7968
7969
7970 void CodeCache::UpdateNormalTypeCache(
7971     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7972   // Adding a new entry can cause a new cache to be allocated.
7973   Handle<CodeCacheHashTable> cache(
7974       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7975   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7976   code_cache->set_normal_type_cache(*new_cache);
7977 }
7978
7979
7980 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7981   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7982   if (result->IsCode()) {
7983     if (Code::cast(result)->flags() == flags) return result;
7984     return GetHeap()->undefined_value();
7985   }
7986   return LookupNormalTypeCache(name, flags);
7987 }
7988
7989
7990 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7991   FixedArray* cache = default_cache();
7992   int length = cache->length();
7993   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7994     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7995     // Skip deleted elements.
7996     if (key->IsNull()) continue;
7997     if (key->IsUndefined()) return key;
7998     if (name->Equals(Name::cast(key))) {
7999       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
8000       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
8001         return code;
8002       }
8003     }
8004   }
8005   return GetHeap()->undefined_value();
8006 }
8007
8008
8009 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
8010   if (!normal_type_cache()->IsUndefined()) {
8011     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
8012     return cache->Lookup(name, flags);
8013   } else {
8014     return GetHeap()->undefined_value();
8015   }
8016 }
8017
8018
8019 int CodeCache::GetIndex(Object* name, Code* code) {
8020   if (code->type() == Code::NORMAL) {
8021     if (normal_type_cache()->IsUndefined()) return -1;
8022     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
8023     return cache->GetIndex(Name::cast(name), code->flags());
8024   }
8025
8026   FixedArray* array = default_cache();
8027   int len = array->length();
8028   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
8029     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
8030   }
8031   return -1;
8032 }
8033
8034
8035 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
8036   if (code->type() == Code::NORMAL) {
8037     DCHECK(!normal_type_cache()->IsUndefined());
8038     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
8039     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
8040     cache->RemoveByIndex(index);
8041   } else {
8042     FixedArray* array = default_cache();
8043     DCHECK(array->length() >= index && array->get(index)->IsCode());
8044     // Use null instead of undefined for deleted elements to distinguish
8045     // deleted elements from unused elements.  This distinction is used
8046     // when looking up in the cache and when updating the cache.
8047     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
8048     array->set_null(index - 1);  // Name.
8049     array->set_null(index);  // Code.
8050   }
8051 }
8052
8053
8054 // The key in the code cache hash table consists of the property name and the
8055 // code object. The actual match is on the name and the code flags. If a key
8056 // is created using the flags and not a code object it can only be used for
8057 // lookup not to create a new entry.
8058 class CodeCacheHashTableKey : public HashTableKey {
8059  public:
8060   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
8061       : name_(name), flags_(flags), code_() { }
8062
8063   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
8064       : name_(name), flags_(code->flags()), code_(code) { }
8065
8066   bool IsMatch(Object* other) OVERRIDE {
8067     if (!other->IsFixedArray()) return false;
8068     FixedArray* pair = FixedArray::cast(other);
8069     Name* name = Name::cast(pair->get(0));
8070     Code::Flags flags = Code::cast(pair->get(1))->flags();
8071     if (flags != flags_) {
8072       return false;
8073     }
8074     return name_->Equals(name);
8075   }
8076
8077   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
8078     return name->Hash() ^ flags;
8079   }
8080
8081   uint32_t Hash() OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
8082
8083   uint32_t HashForObject(Object* obj) OVERRIDE {
8084     FixedArray* pair = FixedArray::cast(obj);
8085     Name* name = Name::cast(pair->get(0));
8086     Code* code = Code::cast(pair->get(1));
8087     return NameFlagsHashHelper(name, code->flags());
8088   }
8089
8090   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
8091     Handle<Code> code = code_.ToHandleChecked();
8092     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
8093     pair->set(0, *name_);
8094     pair->set(1, *code);
8095     return pair;
8096   }
8097
8098  private:
8099   Handle<Name> name_;
8100   Code::Flags flags_;
8101   // TODO(jkummerow): We should be able to get by without this.
8102   MaybeHandle<Code> code_;
8103 };
8104
8105
8106 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
8107   DisallowHeapAllocation no_alloc;
8108   CodeCacheHashTableKey key(handle(name), flags);
8109   int entry = FindEntry(&key);
8110   if (entry == kNotFound) return GetHeap()->undefined_value();
8111   return get(EntryToIndex(entry) + 1);
8112 }
8113
8114
8115 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
8116     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
8117   CodeCacheHashTableKey key(name, code);
8118
8119   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
8120
8121   int entry = new_cache->FindInsertionEntry(key.Hash());
8122   Handle<Object> k = key.AsHandle(cache->GetIsolate());
8123
8124   new_cache->set(EntryToIndex(entry), *k);
8125   new_cache->set(EntryToIndex(entry) + 1, *code);
8126   new_cache->ElementAdded();
8127   return new_cache;
8128 }
8129
8130
8131 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
8132   DisallowHeapAllocation no_alloc;
8133   CodeCacheHashTableKey key(handle(name), flags);
8134   int entry = FindEntry(&key);
8135   return (entry == kNotFound) ? -1 : entry;
8136 }
8137
8138
8139 void CodeCacheHashTable::RemoveByIndex(int index) {
8140   DCHECK(index >= 0);
8141   Heap* heap = GetHeap();
8142   set(EntryToIndex(index), heap->the_hole_value());
8143   set(EntryToIndex(index) + 1, heap->the_hole_value());
8144   ElementRemoved();
8145 }
8146
8147
8148 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
8149                                   MapHandleList* maps,
8150                                   Code::Flags flags,
8151                                   Handle<Code> code) {
8152   Isolate* isolate = code_cache->GetIsolate();
8153   if (code_cache->cache()->IsUndefined()) {
8154     Handle<PolymorphicCodeCacheHashTable> result =
8155         PolymorphicCodeCacheHashTable::New(
8156             isolate,
8157             PolymorphicCodeCacheHashTable::kInitialSize);
8158     code_cache->set_cache(*result);
8159   } else {
8160     // This entry shouldn't be contained in the cache yet.
8161     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
8162                ->Lookup(maps, flags)->IsUndefined());
8163   }
8164   Handle<PolymorphicCodeCacheHashTable> hash_table =
8165       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
8166   Handle<PolymorphicCodeCacheHashTable> new_cache =
8167       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
8168   code_cache->set_cache(*new_cache);
8169 }
8170
8171
8172 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
8173                                             Code::Flags flags) {
8174   if (!cache()->IsUndefined()) {
8175     PolymorphicCodeCacheHashTable* hash_table =
8176         PolymorphicCodeCacheHashTable::cast(cache());
8177     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
8178   } else {
8179     return GetIsolate()->factory()->undefined_value();
8180   }
8181 }
8182
8183
8184 // Despite their name, object of this class are not stored in the actual
8185 // hash table; instead they're temporarily used for lookups. It is therefore
8186 // safe to have a weak (non-owning) pointer to a MapList as a member field.
8187 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
8188  public:
8189   // Callers must ensure that |maps| outlives the newly constructed object.
8190   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
8191       : maps_(maps),
8192         code_flags_(code_flags) {}
8193
8194   bool IsMatch(Object* other) OVERRIDE {
8195     MapHandleList other_maps(kDefaultListAllocationSize);
8196     int other_flags;
8197     FromObject(other, &other_flags, &other_maps);
8198     if (code_flags_ != other_flags) return false;
8199     if (maps_->length() != other_maps.length()) return false;
8200     // Compare just the hashes first because it's faster.
8201     int this_hash = MapsHashHelper(maps_, code_flags_);
8202     int other_hash = MapsHashHelper(&other_maps, other_flags);
8203     if (this_hash != other_hash) return false;
8204
8205     // Full comparison: for each map in maps_, look for an equivalent map in
8206     // other_maps. This implementation is slow, but probably good enough for
8207     // now because the lists are short (<= 4 elements currently).
8208     for (int i = 0; i < maps_->length(); ++i) {
8209       bool match_found = false;
8210       for (int j = 0; j < other_maps.length(); ++j) {
8211         if (*(maps_->at(i)) == *(other_maps.at(j))) {
8212           match_found = true;
8213           break;
8214         }
8215       }
8216       if (!match_found) return false;
8217     }
8218     return true;
8219   }
8220
8221   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
8222     uint32_t hash = code_flags;
8223     for (int i = 0; i < maps->length(); ++i) {
8224       hash ^= maps->at(i)->Hash();
8225     }
8226     return hash;
8227   }
8228
8229   uint32_t Hash() OVERRIDE {
8230     return MapsHashHelper(maps_, code_flags_);
8231   }
8232
8233   uint32_t HashForObject(Object* obj) OVERRIDE {
8234     MapHandleList other_maps(kDefaultListAllocationSize);
8235     int other_flags;
8236     FromObject(obj, &other_flags, &other_maps);
8237     return MapsHashHelper(&other_maps, other_flags);
8238   }
8239
8240   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
8241     // The maps in |maps_| must be copied to a newly allocated FixedArray,
8242     // both because the referenced MapList is short-lived, and because C++
8243     // objects can't be stored in the heap anyway.
8244     Handle<FixedArray> list =
8245         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
8246     list->set(0, Smi::FromInt(code_flags_));
8247     for (int i = 0; i < maps_->length(); ++i) {
8248       list->set(i + 1, *maps_->at(i));
8249     }
8250     return list;
8251   }
8252
8253  private:
8254   static MapHandleList* FromObject(Object* obj,
8255                                    int* code_flags,
8256                                    MapHandleList* maps) {
8257     FixedArray* list = FixedArray::cast(obj);
8258     maps->Rewind(0);
8259     *code_flags = Smi::cast(list->get(0))->value();
8260     for (int i = 1; i < list->length(); ++i) {
8261       maps->Add(Handle<Map>(Map::cast(list->get(i))));
8262     }
8263     return maps;
8264   }
8265
8266   MapHandleList* maps_;  // weak.
8267   int code_flags_;
8268   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
8269 };
8270
8271
8272 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
8273                                               int code_kind) {
8274   DisallowHeapAllocation no_alloc;
8275   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8276   int entry = FindEntry(&key);
8277   if (entry == kNotFound) return GetHeap()->undefined_value();
8278   return get(EntryToIndex(entry) + 1);
8279 }
8280
8281
8282 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
8283       Handle<PolymorphicCodeCacheHashTable> hash_table,
8284       MapHandleList* maps,
8285       int code_kind,
8286       Handle<Code> code) {
8287   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8288   Handle<PolymorphicCodeCacheHashTable> cache =
8289       EnsureCapacity(hash_table, 1, &key);
8290   int entry = cache->FindInsertionEntry(key.Hash());
8291
8292   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
8293   cache->set(EntryToIndex(entry), *obj);
8294   cache->set(EntryToIndex(entry) + 1, *code);
8295   cache->ElementAdded();
8296   return cache;
8297 }
8298
8299
8300 void FixedArray::Shrink(int new_length) {
8301   DCHECK(0 <= new_length && new_length <= length());
8302   if (new_length < length()) {
8303     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(
8304         this, length() - new_length);
8305   }
8306 }
8307
8308
8309 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8310     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
8311   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
8312   ElementsAccessor* accessor = array->GetElementsAccessor();
8313   Handle<FixedArray> result;
8314   ASSIGN_RETURN_ON_EXCEPTION(
8315       array->GetIsolate(), result,
8316       accessor->AddElementsToFixedArray(array, array, content, filter),
8317       FixedArray);
8318
8319 #ifdef ENABLE_SLOW_DCHECKS
8320   if (FLAG_enable_slow_asserts) {
8321     DisallowHeapAllocation no_allocation;
8322     for (int i = 0; i < result->length(); i++) {
8323       Object* current = result->get(i);
8324       DCHECK(current->IsNumber() || current->IsName());
8325     }
8326   }
8327 #endif
8328   return result;
8329 }
8330
8331
8332 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8333                                                 Handle<FixedArray> second) {
8334   ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
8335   Handle<FixedArray> result;
8336   ASSIGN_RETURN_ON_EXCEPTION(
8337       first->GetIsolate(), result,
8338       accessor->AddElementsToFixedArray(
8339           Handle<Object>::null(),    // receiver
8340           Handle<JSObject>::null(),  // holder
8341           first, Handle<FixedArrayBase>::cast(second), ALL_KEYS),
8342       FixedArray);
8343
8344 #ifdef ENABLE_SLOW_DCHECKS
8345   if (FLAG_enable_slow_asserts) {
8346     DisallowHeapAllocation no_allocation;
8347     for (int i = 0; i < result->length(); i++) {
8348       Object* current = result->get(i);
8349       DCHECK(current->IsNumber() || current->IsName());
8350     }
8351   }
8352 #endif
8353   return result;
8354 }
8355
8356
8357 Handle<FixedArray> FixedArray::CopySize(
8358     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
8359   Isolate* isolate = array->GetIsolate();
8360   if (new_length == 0) return isolate->factory()->empty_fixed_array();
8361   Handle<FixedArray> result =
8362       isolate->factory()->NewFixedArray(new_length, pretenure);
8363   // Copy the content
8364   DisallowHeapAllocation no_gc;
8365   int len = array->length();
8366   if (new_length < len) len = new_length;
8367   // We are taking the map from the old fixed array so the map is sure to
8368   // be an immortal immutable object.
8369   result->set_map_no_write_barrier(array->map());
8370   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
8371   for (int i = 0; i < len; i++) {
8372     result->set(i, array->get(i), mode);
8373   }
8374   return result;
8375 }
8376
8377
8378 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8379   DisallowHeapAllocation no_gc;
8380   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8381   for (int index = 0; index < len; index++) {
8382     dest->set(dest_pos+index, get(pos+index), mode);
8383   }
8384 }
8385
8386
8387 #ifdef DEBUG
8388 bool FixedArray::IsEqualTo(FixedArray* other) {
8389   if (length() != other->length()) return false;
8390   for (int i = 0 ; i < length(); ++i) {
8391     if (get(i) != other->get(i)) return false;
8392   }
8393   return true;
8394 }
8395 #endif
8396
8397
8398 // static
8399 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
8400                          Handle<HeapObject> value) {
8401   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
8402   Handle<WeakCell> cell =
8403       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
8404                      : array->GetIsolate()->factory()->NewWeakCell(value);
8405   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
8406   if (FLAG_trace_weak_arrays) {
8407     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8408   }
8409   array->set_last_used_index(index);
8410 }
8411
8412
8413 // static
8414 Handle<WeakFixedArray> WeakFixedArray::Add(
8415     Handle<Object> maybe_array, Handle<HeapObject> value,
8416     SearchForDuplicates search_for_duplicates) {
8417   Handle<WeakFixedArray> array =
8418       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8419           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8420           : Handle<WeakFixedArray>::cast(maybe_array);
8421
8422   if (search_for_duplicates == kAddIfNotFound) {
8423     for (int i = 0; i < array->Length(); ++i) {
8424       if (array->Get(i) == *value) return array;
8425     }
8426   } else {
8427 #ifdef DEBUG
8428     for (int i = 0; i < array->Length(); ++i) {
8429       DCHECK_NE(*value, array->Get(i));
8430     }
8431 #endif
8432   }
8433
8434   // Try to store the new entry if there's room. Optimize for consecutive
8435   // accesses.
8436   int first_index = array->last_used_index();
8437   for (int i = first_index;;) {
8438     if (array->IsEmptySlot((i))) {
8439       WeakFixedArray::Set(array, i, value);
8440       return array;
8441     }
8442     if (FLAG_trace_weak_arrays) {
8443       PrintF("[WeakFixedArray: searching for free slot]\n");
8444     }
8445     i = (i + 1) % array->Length();
8446     if (i == first_index) break;
8447   }
8448
8449   // No usable slot found, grow the array.
8450   int new_length = array->Length() + (array->Length() >> 1) + 4;
8451   Handle<WeakFixedArray> new_array =
8452       Allocate(array->GetIsolate(), new_length, array);
8453   if (FLAG_trace_weak_arrays) {
8454     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8455   }
8456   WeakFixedArray::Set(new_array, array->Length(), value);
8457   return new_array;
8458 }
8459
8460
8461 void WeakFixedArray::Remove(Handle<HeapObject> value) {
8462   // Optimize for the most recently added element to be removed again.
8463   int first_index = last_used_index();
8464   for (int i = first_index;;) {
8465     if (Get(i) == *value) {
8466       clear(i);
8467       // Users of WeakFixedArray should make sure that there are no duplicates,
8468       // they can use Add(..., kAddIfNotFound) if necessary.
8469       return;
8470     }
8471     i = (i + 1) % Length();
8472     if (i == first_index) break;
8473   }
8474 }
8475
8476
8477 // static
8478 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8479     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8480   DCHECK(0 <= size);
8481   Handle<FixedArray> result =
8482       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8483   Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
8484   if (initialize_from.is_null()) {
8485     for (int i = 0; i < result->length(); ++i) {
8486       result->set(i, Smi::FromInt(0));
8487     }
8488   } else {
8489     DCHECK(initialize_from->Length() <= size);
8490     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
8491     int target_index = kFirstIndex;
8492     for (int source_index = kFirstIndex; source_index < raw_source->length();
8493          ++source_index) {
8494       // The act of allocating might have caused entries in the source array
8495       // to be cleared. Copy only what's needed.
8496       if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
8497       result->set(target_index++, raw_source->get(source_index));
8498     }
8499     casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
8500     for (; target_index < result->length(); ++target_index) {
8501       result->set(target_index, Smi::FromInt(0));
8502     }
8503   }
8504   return casted_result;
8505 }
8506
8507
8508 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8509                                                   int number_of_descriptors,
8510                                                   int slack) {
8511   DCHECK(0 <= number_of_descriptors);
8512   Factory* factory = isolate->factory();
8513   // Do not use DescriptorArray::cast on incomplete object.
8514   int size = number_of_descriptors + slack;
8515   if (size == 0) return factory->empty_descriptor_array();
8516   // Allocate the array of keys.
8517   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8518
8519   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8520   result->set(kEnumCacheIndex, Smi::FromInt(0));
8521   return Handle<DescriptorArray>::cast(result);
8522 }
8523
8524
8525 void DescriptorArray::ClearEnumCache() {
8526   set(kEnumCacheIndex, Smi::FromInt(0));
8527 }
8528
8529
8530 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8531   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8532   Set(index, descriptor);
8533 }
8534
8535
8536 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8537                                    FixedArray* new_cache,
8538                                    Object* new_index_cache) {
8539   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8540   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8541   DCHECK(!IsEmpty());
8542   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8543   FixedArray::cast(bridge_storage)->
8544     set(kEnumCacheBridgeCacheIndex, new_cache);
8545   FixedArray::cast(bridge_storage)->
8546     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8547   set(kEnumCacheIndex, bridge_storage);
8548 }
8549
8550
8551 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8552                                const WhitenessWitness& witness) {
8553   Object* value = src->GetValue(index);
8554   PropertyDetails details = src->GetDetails(index);
8555   Descriptor desc(handle(src->GetKey(index)),
8556                   handle(value, src->GetIsolate()),
8557                   details);
8558   Set(index, &desc, witness);
8559 }
8560
8561
8562 // We need the whiteness witness since sort will reshuffle the entries in the
8563 // descriptor array. If the descriptor array were to be black, the shuffling
8564 // would move a slot that was already recorded as pointing into an evacuation
8565 // candidate. This would result in missing updates upon evacuation.
8566 void DescriptorArray::Sort() {
8567   // In-place heap sort.
8568   int len = number_of_descriptors();
8569   // Reset sorting since the descriptor array might contain invalid pointers.
8570   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8571   // Bottom-up max-heap construction.
8572   // Index of the last node with children
8573   const int max_parent_index = (len / 2) - 1;
8574   for (int i = max_parent_index; i >= 0; --i) {
8575     int parent_index = i;
8576     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8577     while (parent_index <= max_parent_index) {
8578       int child_index = 2 * parent_index + 1;
8579       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8580       if (child_index + 1 < len) {
8581         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8582         if (right_child_hash > child_hash) {
8583           child_index++;
8584           child_hash = right_child_hash;
8585         }
8586       }
8587       if (child_hash <= parent_hash) break;
8588       SwapSortedKeys(parent_index, child_index);
8589       // Now element at child_index could be < its children.
8590       parent_index = child_index;  // parent_hash remains correct.
8591     }
8592   }
8593
8594   // Extract elements and create sorted array.
8595   for (int i = len - 1; i > 0; --i) {
8596     // Put max element at the back of the array.
8597     SwapSortedKeys(0, i);
8598     // Shift down the new top element.
8599     int parent_index = 0;
8600     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8601     const int max_parent_index = (i / 2) - 1;
8602     while (parent_index <= max_parent_index) {
8603       int child_index = parent_index * 2 + 1;
8604       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8605       if (child_index + 1 < i) {
8606         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8607         if (right_child_hash > child_hash) {
8608           child_index++;
8609           child_hash = right_child_hash;
8610         }
8611       }
8612       if (child_hash <= parent_hash) break;
8613       SwapSortedKeys(parent_index, child_index);
8614       parent_index = child_index;
8615     }
8616   }
8617   DCHECK(IsSortedNoDuplicates());
8618 }
8619
8620
8621 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8622   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8623   copy->set_getter(pair->getter());
8624   copy->set_setter(pair->setter());
8625   return copy;
8626 }
8627
8628
8629 Object* AccessorPair::GetComponent(AccessorComponent component) {
8630   Object* accessor = get(component);
8631   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8632 }
8633
8634
8635 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8636     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
8637   return Handle<DeoptimizationInputData>::cast(
8638       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
8639                                         pretenure));
8640 }
8641
8642
8643 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8644     Isolate* isolate,
8645     int number_of_deopt_points,
8646     PretenureFlag pretenure) {
8647   Handle<FixedArray> result;
8648   if (number_of_deopt_points == 0) {
8649     result = isolate->factory()->empty_fixed_array();
8650   } else {
8651     result = isolate->factory()->NewFixedArray(
8652         LengthOfFixedArray(number_of_deopt_points), pretenure);
8653   }
8654   return Handle<DeoptimizationOutputData>::cast(result);
8655 }
8656
8657
8658 #ifdef DEBUG
8659 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8660   if (IsEmpty()) return other->IsEmpty();
8661   if (other->IsEmpty()) return false;
8662   if (length() != other->length()) return false;
8663   for (int i = 0; i < length(); ++i) {
8664     if (get(i) != other->get(i)) return false;
8665   }
8666   return true;
8667 }
8668 #endif
8669
8670
8671 bool String::LooksValid() {
8672   if (!GetIsolate()->heap()->Contains(this)) return false;
8673   return true;
8674 }
8675
8676
8677 String::FlatContent String::GetFlatContent() {
8678   DCHECK(!AllowHeapAllocation::IsAllowed());
8679   int length = this->length();
8680   StringShape shape(this);
8681   String* string = this;
8682   int offset = 0;
8683   if (shape.representation_tag() == kConsStringTag) {
8684     ConsString* cons = ConsString::cast(string);
8685     if (cons->second()->length() != 0) {
8686       return FlatContent();
8687     }
8688     string = cons->first();
8689     shape = StringShape(string);
8690   }
8691   if (shape.representation_tag() == kSlicedStringTag) {
8692     SlicedString* slice = SlicedString::cast(string);
8693     offset = slice->offset();
8694     string = slice->parent();
8695     shape = StringShape(string);
8696     DCHECK(shape.representation_tag() != kConsStringTag &&
8697            shape.representation_tag() != kSlicedStringTag);
8698   }
8699   if (shape.encoding_tag() == kOneByteStringTag) {
8700     const uint8_t* start;
8701     if (shape.representation_tag() == kSeqStringTag) {
8702       start = SeqOneByteString::cast(string)->GetChars();
8703     } else {
8704       start = ExternalOneByteString::cast(string)->GetChars();
8705     }
8706     return FlatContent(start + offset, length);
8707   } else {
8708     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8709     const uc16* start;
8710     if (shape.representation_tag() == kSeqStringTag) {
8711       start = SeqTwoByteString::cast(string)->GetChars();
8712     } else {
8713       start = ExternalTwoByteString::cast(string)->GetChars();
8714     }
8715     return FlatContent(start + offset, length);
8716   }
8717 }
8718
8719
8720 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8721                                           RobustnessFlag robust_flag,
8722                                           int offset,
8723                                           int length,
8724                                           int* length_return) {
8725   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8726     return SmartArrayPointer<char>(NULL);
8727   }
8728   // Negative length means the to the end of the string.
8729   if (length < 0) length = kMaxInt - offset;
8730
8731   // Compute the size of the UTF-8 string. Start at the specified offset.
8732   StringCharacterStream stream(this, offset);
8733   int character_position = offset;
8734   int utf8_bytes = 0;
8735   int last = unibrow::Utf16::kNoPreviousCharacter;
8736   while (stream.HasMore() && character_position++ < offset + length) {
8737     uint16_t character = stream.GetNext();
8738     utf8_bytes += unibrow::Utf8::Length(character, last);
8739     last = character;
8740   }
8741
8742   if (length_return) {
8743     *length_return = utf8_bytes;
8744   }
8745
8746   char* result = NewArray<char>(utf8_bytes + 1);
8747
8748   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8749   stream.Reset(this, offset);
8750   character_position = offset;
8751   int utf8_byte_position = 0;
8752   last = unibrow::Utf16::kNoPreviousCharacter;
8753   while (stream.HasMore() && character_position++ < offset + length) {
8754     uint16_t character = stream.GetNext();
8755     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8756       character = ' ';
8757     }
8758     utf8_byte_position +=
8759         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8760     last = character;
8761   }
8762   result[utf8_byte_position] = 0;
8763   return SmartArrayPointer<char>(result);
8764 }
8765
8766
8767 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8768                                           RobustnessFlag robust_flag,
8769                                           int* length_return) {
8770   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8771 }
8772
8773
8774 const uc16* String::GetTwoByteData(unsigned start) {
8775   DCHECK(!IsOneByteRepresentationUnderneath());
8776   switch (StringShape(this).representation_tag()) {
8777     case kSeqStringTag:
8778       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8779     case kExternalStringTag:
8780       return ExternalTwoByteString::cast(this)->
8781         ExternalTwoByteStringGetData(start);
8782     case kSlicedStringTag: {
8783       SlicedString* slice = SlicedString::cast(this);
8784       return slice->parent()->GetTwoByteData(start + slice->offset());
8785     }
8786     case kConsStringTag:
8787       UNREACHABLE();
8788       return NULL;
8789   }
8790   UNREACHABLE();
8791   return NULL;
8792 }
8793
8794
8795 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8796   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8797     return SmartArrayPointer<uc16>();
8798   }
8799   StringCharacterStream stream(this);
8800
8801   uc16* result = NewArray<uc16>(length() + 1);
8802
8803   int i = 0;
8804   while (stream.HasMore()) {
8805     uint16_t character = stream.GetNext();
8806     result[i++] = character;
8807   }
8808   result[i] = 0;
8809   return SmartArrayPointer<uc16>(result);
8810 }
8811
8812
8813 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8814   return reinterpret_cast<uc16*>(
8815       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8816 }
8817
8818
8819 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8820   Relocatable* current = isolate->relocatable_top();
8821   while (current != NULL) {
8822     current->PostGarbageCollection();
8823     current = current->prev_;
8824   }
8825 }
8826
8827
8828 // Reserve space for statics needing saving and restoring.
8829 int Relocatable::ArchiveSpacePerThread() {
8830   return sizeof(Relocatable*);  // NOLINT
8831 }
8832
8833
8834 // Archive statics that are thread-local.
8835 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8836   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8837   isolate->set_relocatable_top(NULL);
8838   return to + ArchiveSpacePerThread();
8839 }
8840
8841
8842 // Restore statics that are thread-local.
8843 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8844   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8845   return from + ArchiveSpacePerThread();
8846 }
8847
8848
8849 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8850   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8851   Iterate(v, top);
8852   return thread_storage + ArchiveSpacePerThread();
8853 }
8854
8855
8856 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8857   Iterate(v, isolate->relocatable_top());
8858 }
8859
8860
8861 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8862   Relocatable* current = top;
8863   while (current != NULL) {
8864     current->IterateInstance(v);
8865     current = current->prev_;
8866   }
8867 }
8868
8869
8870 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8871     : Relocatable(isolate),
8872       str_(str.location()),
8873       length_(str->length()) {
8874   PostGarbageCollection();
8875 }
8876
8877
8878 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8879     : Relocatable(isolate),
8880       str_(0),
8881       is_one_byte_(true),
8882       length_(input.length()),
8883       start_(input.start()) {}
8884
8885
8886 void FlatStringReader::PostGarbageCollection() {
8887   if (str_ == NULL) return;
8888   Handle<String> str(str_);
8889   DCHECK(str->IsFlat());
8890   DisallowHeapAllocation no_gc;
8891   // This does not actually prevent the vector from being relocated later.
8892   String::FlatContent content = str->GetFlatContent();
8893   DCHECK(content.IsFlat());
8894   is_one_byte_ = content.IsOneByte();
8895   if (is_one_byte_) {
8896     start_ = content.ToOneByteVector().start();
8897   } else {
8898     start_ = content.ToUC16Vector().start();
8899   }
8900 }
8901
8902
8903 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
8904   DCHECK(cons_string != NULL);
8905   root_ = cons_string;
8906   consumed_ = offset;
8907   // Force stack blown condition to trigger restart.
8908   depth_ = 1;
8909   maximum_depth_ = kStackSize + depth_;
8910   DCHECK(StackBlown());
8911 }
8912
8913
8914 String* ConsStringIterator::Continue(int* offset_out) {
8915   DCHECK(depth_ != 0);
8916   DCHECK_EQ(0, *offset_out);
8917   bool blew_stack = StackBlown();
8918   String* string = NULL;
8919   // Get the next leaf if there is one.
8920   if (!blew_stack) string = NextLeaf(&blew_stack);
8921   // Restart search from root.
8922   if (blew_stack) {
8923     DCHECK(string == NULL);
8924     string = Search(offset_out);
8925   }
8926   // Ensure future calls return null immediately.
8927   if (string == NULL) Reset(NULL);
8928   return string;
8929 }
8930
8931
8932 String* ConsStringIterator::Search(int* offset_out) {
8933   ConsString* cons_string = root_;
8934   // Reset the stack, pushing the root string.
8935   depth_ = 1;
8936   maximum_depth_ = 1;
8937   frames_[0] = cons_string;
8938   const int consumed = consumed_;
8939   int offset = 0;
8940   while (true) {
8941     // Loop until the string is found which contains the target offset.
8942     String* string = cons_string->first();
8943     int length = string->length();
8944     int32_t type;
8945     if (consumed < offset + length) {
8946       // Target offset is in the left branch.
8947       // Keep going if we're still in a ConString.
8948       type = string->map()->instance_type();
8949       if ((type & kStringRepresentationMask) == kConsStringTag) {
8950         cons_string = ConsString::cast(string);
8951         PushLeft(cons_string);
8952         continue;
8953       }
8954       // Tell the stack we're done descending.
8955       AdjustMaximumDepth();
8956     } else {
8957       // Descend right.
8958       // Update progress through the string.
8959       offset += length;
8960       // Keep going if we're still in a ConString.
8961       string = cons_string->second();
8962       type = string->map()->instance_type();
8963       if ((type & kStringRepresentationMask) == kConsStringTag) {
8964         cons_string = ConsString::cast(string);
8965         PushRight(cons_string);
8966         continue;
8967       }
8968       // Need this to be updated for the current string.
8969       length = string->length();
8970       // Account for the possibility of an empty right leaf.
8971       // This happens only if we have asked for an offset outside the string.
8972       if (length == 0) {
8973         // Reset so future operations will return null immediately.
8974         Reset(NULL);
8975         return NULL;
8976       }
8977       // Tell the stack we're done descending.
8978       AdjustMaximumDepth();
8979       // Pop stack so next iteration is in correct place.
8980       Pop();
8981     }
8982     DCHECK(length != 0);
8983     // Adjust return values and exit.
8984     consumed_ = offset + length;
8985     *offset_out = consumed - offset;
8986     return string;
8987   }
8988   UNREACHABLE();
8989   return NULL;
8990 }
8991
8992
8993 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
8994   while (true) {
8995     // Tree traversal complete.
8996     if (depth_ == 0) {
8997       *blew_stack = false;
8998       return NULL;
8999     }
9000     // We've lost track of higher nodes.
9001     if (StackBlown()) {
9002       *blew_stack = true;
9003       return NULL;
9004     }
9005     // Go right.
9006     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
9007     String* string = cons_string->second();
9008     int32_t type = string->map()->instance_type();
9009     if ((type & kStringRepresentationMask) != kConsStringTag) {
9010       // Pop stack so next iteration is in correct place.
9011       Pop();
9012       int length = string->length();
9013       // Could be a flattened ConsString.
9014       if (length == 0) continue;
9015       consumed_ += length;
9016       return string;
9017     }
9018     cons_string = ConsString::cast(string);
9019     PushRight(cons_string);
9020     // Need to traverse all the way left.
9021     while (true) {
9022       // Continue left.
9023       string = cons_string->first();
9024       type = string->map()->instance_type();
9025       if ((type & kStringRepresentationMask) != kConsStringTag) {
9026         AdjustMaximumDepth();
9027         int length = string->length();
9028         DCHECK(length != 0);
9029         consumed_ += length;
9030         return string;
9031       }
9032       cons_string = ConsString::cast(string);
9033       PushLeft(cons_string);
9034     }
9035   }
9036   UNREACHABLE();
9037   return NULL;
9038 }
9039
9040
9041 uint16_t ConsString::ConsStringGet(int index) {
9042   DCHECK(index >= 0 && index < this->length());
9043
9044   // Check for a flattened cons string
9045   if (second()->length() == 0) {
9046     String* left = first();
9047     return left->Get(index);
9048   }
9049
9050   String* string = String::cast(this);
9051
9052   while (true) {
9053     if (StringShape(string).IsCons()) {
9054       ConsString* cons_string = ConsString::cast(string);
9055       String* left = cons_string->first();
9056       if (left->length() > index) {
9057         string = left;
9058       } else {
9059         index -= left->length();
9060         string = cons_string->second();
9061       }
9062     } else {
9063       return string->Get(index);
9064     }
9065   }
9066
9067   UNREACHABLE();
9068   return 0;
9069 }
9070
9071
9072 uint16_t SlicedString::SlicedStringGet(int index) {
9073   return parent()->Get(offset() + index);
9074 }
9075
9076
9077 template <typename sinkchar>
9078 void String::WriteToFlat(String* src,
9079                          sinkchar* sink,
9080                          int f,
9081                          int t) {
9082   String* source = src;
9083   int from = f;
9084   int to = t;
9085   while (true) {
9086     DCHECK(0 <= from && from <= to && to <= source->length());
9087     switch (StringShape(source).full_representation_tag()) {
9088       case kOneByteStringTag | kExternalStringTag: {
9089         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
9090                   to - from);
9091         return;
9092       }
9093       case kTwoByteStringTag | kExternalStringTag: {
9094         const uc16* data =
9095             ExternalTwoByteString::cast(source)->GetChars();
9096         CopyChars(sink,
9097                   data + from,
9098                   to - from);
9099         return;
9100       }
9101       case kOneByteStringTag | kSeqStringTag: {
9102         CopyChars(sink,
9103                   SeqOneByteString::cast(source)->GetChars() + from,
9104                   to - from);
9105         return;
9106       }
9107       case kTwoByteStringTag | kSeqStringTag: {
9108         CopyChars(sink,
9109                   SeqTwoByteString::cast(source)->GetChars() + from,
9110                   to - from);
9111         return;
9112       }
9113       case kOneByteStringTag | kConsStringTag:
9114       case kTwoByteStringTag | kConsStringTag: {
9115         ConsString* cons_string = ConsString::cast(source);
9116         String* first = cons_string->first();
9117         int boundary = first->length();
9118         if (to - boundary >= boundary - from) {
9119           // Right hand side is longer.  Recurse over left.
9120           if (from < boundary) {
9121             WriteToFlat(first, sink, from, boundary);
9122             sink += boundary - from;
9123             from = 0;
9124           } else {
9125             from -= boundary;
9126           }
9127           to -= boundary;
9128           source = cons_string->second();
9129         } else {
9130           // Left hand side is longer.  Recurse over right.
9131           if (to > boundary) {
9132             String* second = cons_string->second();
9133             // When repeatedly appending to a string, we get a cons string that
9134             // is unbalanced to the left, a list, essentially.  We inline the
9135             // common case of sequential one-byte right child.
9136             if (to - boundary == 1) {
9137               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
9138             } else if (second->IsSeqOneByteString()) {
9139               CopyChars(sink + boundary - from,
9140                         SeqOneByteString::cast(second)->GetChars(),
9141                         to - boundary);
9142             } else {
9143               WriteToFlat(second,
9144                           sink + boundary - from,
9145                           0,
9146                           to - boundary);
9147             }
9148             to = boundary;
9149           }
9150           source = first;
9151         }
9152         break;
9153       }
9154       case kOneByteStringTag | kSlicedStringTag:
9155       case kTwoByteStringTag | kSlicedStringTag: {
9156         SlicedString* slice = SlicedString::cast(source);
9157         unsigned offset = slice->offset();
9158         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
9159         return;
9160       }
9161     }
9162   }
9163 }
9164
9165
9166
9167 template <typename SourceChar>
9168 static void CalculateLineEndsImpl(Isolate* isolate,
9169                                   List<int>* line_ends,
9170                                   Vector<const SourceChar> src,
9171                                   bool include_ending_line) {
9172   const int src_len = src.length();
9173   UnicodeCache* cache = isolate->unicode_cache();
9174   for (int i = 0; i < src_len - 1; i++) {
9175     SourceChar current = src[i];
9176     SourceChar next = src[i + 1];
9177     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
9178   }
9179
9180   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
9181     line_ends->Add(src_len - 1);
9182   } else if (include_ending_line) {
9183     // Even if the last line misses a line end, it is counted.
9184     line_ends->Add(src_len);
9185   }
9186 }
9187
9188
9189 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
9190                                              bool include_ending_line) {
9191   src = Flatten(src);
9192   // Rough estimate of line count based on a roughly estimated average
9193   // length of (unpacked) code.
9194   int line_count_estimate = src->length() >> 4;
9195   List<int> line_ends(line_count_estimate);
9196   Isolate* isolate = src->GetIsolate();
9197   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
9198     // Dispatch on type of strings.
9199     String::FlatContent content = src->GetFlatContent();
9200     DCHECK(content.IsFlat());
9201     if (content.IsOneByte()) {
9202       CalculateLineEndsImpl(isolate,
9203                             &line_ends,
9204                             content.ToOneByteVector(),
9205                             include_ending_line);
9206     } else {
9207       CalculateLineEndsImpl(isolate,
9208                             &line_ends,
9209                             content.ToUC16Vector(),
9210                             include_ending_line);
9211     }
9212   }
9213   int line_count = line_ends.length();
9214   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
9215   for (int i = 0; i < line_count; i++) {
9216     array->set(i, Smi::FromInt(line_ends[i]));
9217   }
9218   return array;
9219 }
9220
9221
9222 // Compares the contents of two strings by reading and comparing
9223 // int-sized blocks of characters.
9224 template <typename Char>
9225 static inline bool CompareRawStringContents(const Char* const a,
9226                                             const Char* const b,
9227                                             int length) {
9228   return CompareChars(a, b, length) == 0;
9229 }
9230
9231
9232 template<typename Chars1, typename Chars2>
9233 class RawStringComparator : public AllStatic {
9234  public:
9235   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
9236     DCHECK(sizeof(Chars1) != sizeof(Chars2));
9237     for (int i = 0; i < len; i++) {
9238       if (a[i] != b[i]) {
9239         return false;
9240       }
9241     }
9242     return true;
9243   }
9244 };
9245
9246
9247 template<>
9248 class RawStringComparator<uint16_t, uint16_t> {
9249  public:
9250   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
9251     return CompareRawStringContents(a, b, len);
9252   }
9253 };
9254
9255
9256 template<>
9257 class RawStringComparator<uint8_t, uint8_t> {
9258  public:
9259   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
9260     return CompareRawStringContents(a, b, len);
9261   }
9262 };
9263
9264
9265 class StringComparator {
9266   class State {
9267    public:
9268     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
9269
9270     void Init(String* string) {
9271       ConsString* cons_string = String::VisitFlat(this, string);
9272       iter_.Reset(cons_string);
9273       if (cons_string != NULL) {
9274         int offset;
9275         string = iter_.Next(&offset);
9276         String::VisitFlat(this, string, offset);
9277       }
9278     }
9279
9280     inline void VisitOneByteString(const uint8_t* chars, int length) {
9281       is_one_byte_ = true;
9282       buffer8_ = chars;
9283       length_ = length;
9284     }
9285
9286     inline void VisitTwoByteString(const uint16_t* chars, int length) {
9287       is_one_byte_ = false;
9288       buffer16_ = chars;
9289       length_ = length;
9290     }
9291
9292     void Advance(int consumed) {
9293       DCHECK(consumed <= length_);
9294       // Still in buffer.
9295       if (length_ != consumed) {
9296         if (is_one_byte_) {
9297           buffer8_ += consumed;
9298         } else {
9299           buffer16_ += consumed;
9300         }
9301         length_ -= consumed;
9302         return;
9303       }
9304       // Advance state.
9305       int offset;
9306       String* next = iter_.Next(&offset);
9307       DCHECK_EQ(0, offset);
9308       DCHECK(next != NULL);
9309       String::VisitFlat(this, next);
9310     }
9311
9312     ConsStringIterator iter_;
9313     bool is_one_byte_;
9314     int length_;
9315     union {
9316       const uint8_t* buffer8_;
9317       const uint16_t* buffer16_;
9318     };
9319
9320    private:
9321     DISALLOW_COPY_AND_ASSIGN(State);
9322   };
9323
9324  public:
9325   inline StringComparator() {}
9326
9327   template<typename Chars1, typename Chars2>
9328   static inline bool Equals(State* state_1, State* state_2, int to_check) {
9329     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
9330     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
9331     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
9332   }
9333
9334   bool Equals(String* string_1, String* string_2) {
9335     int length = string_1->length();
9336     state_1_.Init(string_1);
9337     state_2_.Init(string_2);
9338     while (true) {
9339       int to_check = Min(state_1_.length_, state_2_.length_);
9340       DCHECK(to_check > 0 && to_check <= length);
9341       bool is_equal;
9342       if (state_1_.is_one_byte_) {
9343         if (state_2_.is_one_byte_) {
9344           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
9345         } else {
9346           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
9347         }
9348       } else {
9349         if (state_2_.is_one_byte_) {
9350           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
9351         } else {
9352           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
9353         }
9354       }
9355       // Looping done.
9356       if (!is_equal) return false;
9357       length -= to_check;
9358       // Exit condition. Strings are equal.
9359       if (length == 0) return true;
9360       state_1_.Advance(to_check);
9361       state_2_.Advance(to_check);
9362     }
9363   }
9364
9365  private:
9366   State state_1_;
9367   State state_2_;
9368
9369   DISALLOW_COPY_AND_ASSIGN(StringComparator);
9370 };
9371
9372
9373 bool String::SlowEquals(String* other) {
9374   DisallowHeapAllocation no_gc;
9375   // Fast check: negative check with lengths.
9376   int len = length();
9377   if (len != other->length()) return false;
9378   if (len == 0) return true;
9379
9380   // Fast check: if hash code is computed for both strings
9381   // a fast negative check can be performed.
9382   if (HasHashCode() && other->HasHashCode()) {
9383 #ifdef ENABLE_SLOW_DCHECKS
9384     if (FLAG_enable_slow_asserts) {
9385       if (Hash() != other->Hash()) {
9386         bool found_difference = false;
9387         for (int i = 0; i < len; i++) {
9388           if (Get(i) != other->Get(i)) {
9389             found_difference = true;
9390             break;
9391           }
9392         }
9393         DCHECK(found_difference);
9394       }
9395     }
9396 #endif
9397     if (Hash() != other->Hash()) return false;
9398   }
9399
9400   // We know the strings are both non-empty. Compare the first chars
9401   // before we try to flatten the strings.
9402   if (this->Get(0) != other->Get(0)) return false;
9403
9404   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
9405     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
9406     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
9407     return CompareRawStringContents(str1, str2, len);
9408   }
9409
9410   StringComparator comparator;
9411   return comparator.Equals(this, other);
9412 }
9413
9414
9415 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
9416   // Fast check: negative check with lengths.
9417   int one_length = one->length();
9418   if (one_length != two->length()) return false;
9419   if (one_length == 0) return true;
9420
9421   // Fast check: if hash code is computed for both strings
9422   // a fast negative check can be performed.
9423   if (one->HasHashCode() && two->HasHashCode()) {
9424 #ifdef ENABLE_SLOW_DCHECKS
9425     if (FLAG_enable_slow_asserts) {
9426       if (one->Hash() != two->Hash()) {
9427         bool found_difference = false;
9428         for (int i = 0; i < one_length; i++) {
9429           if (one->Get(i) != two->Get(i)) {
9430             found_difference = true;
9431             break;
9432           }
9433         }
9434         DCHECK(found_difference);
9435       }
9436     }
9437 #endif
9438     if (one->Hash() != two->Hash()) return false;
9439   }
9440
9441   // We know the strings are both non-empty. Compare the first chars
9442   // before we try to flatten the strings.
9443   if (one->Get(0) != two->Get(0)) return false;
9444
9445   one = String::Flatten(one);
9446   two = String::Flatten(two);
9447
9448   DisallowHeapAllocation no_gc;
9449   String::FlatContent flat1 = one->GetFlatContent();
9450   String::FlatContent flat2 = two->GetFlatContent();
9451
9452   if (flat1.IsOneByte() && flat2.IsOneByte()) {
9453       return CompareRawStringContents(flat1.ToOneByteVector().start(),
9454                                       flat2.ToOneByteVector().start(),
9455                                       one_length);
9456   } else {
9457     for (int i = 0; i < one_length; i++) {
9458       if (flat1.Get(i) != flat2.Get(i)) return false;
9459     }
9460     return true;
9461   }
9462 }
9463
9464
9465 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9466   int slen = length();
9467   // Can't check exact length equality, but we can check bounds.
9468   int str_len = str.length();
9469   if (!allow_prefix_match &&
9470       (str_len < slen ||
9471           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9472     return false;
9473   }
9474   int i;
9475   size_t remaining_in_str = static_cast<size_t>(str_len);
9476   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9477   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9478     size_t cursor = 0;
9479     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9480     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9481     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9482       if (i > slen - 1) return false;
9483       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9484       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9485     } else {
9486       if (Get(i) != r) return false;
9487     }
9488     utf8_data += cursor;
9489     remaining_in_str -= cursor;
9490   }
9491   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9492 }
9493
9494
9495 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9496   int slen = length();
9497   if (str.length() != slen) return false;
9498   DisallowHeapAllocation no_gc;
9499   FlatContent content = GetFlatContent();
9500   if (content.IsOneByte()) {
9501     return CompareChars(content.ToOneByteVector().start(),
9502                         str.start(), slen) == 0;
9503   }
9504   for (int i = 0; i < slen; i++) {
9505     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9506   }
9507   return true;
9508 }
9509
9510
9511 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9512   int slen = length();
9513   if (str.length() != slen) return false;
9514   DisallowHeapAllocation no_gc;
9515   FlatContent content = GetFlatContent();
9516   if (content.IsTwoByte()) {
9517     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9518   }
9519   for (int i = 0; i < slen; i++) {
9520     if (Get(i) != str[i]) return false;
9521   }
9522   return true;
9523 }
9524
9525
9526 uint32_t String::ComputeAndSetHash() {
9527   // Should only be called if hash code has not yet been computed.
9528   DCHECK(!HasHashCode());
9529
9530   // Store the hash code in the object.
9531   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9532   set_hash_field(field);
9533
9534   // Check the hash code is there.
9535   DCHECK(HasHashCode());
9536   uint32_t result = field >> kHashShift;
9537   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9538   return result;
9539 }
9540
9541
9542 bool String::ComputeArrayIndex(uint32_t* index) {
9543   int length = this->length();
9544   if (length == 0 || length > kMaxArrayIndexSize) return false;
9545   StringCharacterStream stream(this);
9546   return StringToArrayIndex(&stream, index);
9547 }
9548
9549
9550 bool String::SlowAsArrayIndex(uint32_t* index) {
9551   if (length() <= kMaxCachedArrayIndexLength) {
9552     Hash();  // force computation of hash code
9553     uint32_t field = hash_field();
9554     if ((field & kIsNotArrayIndexMask) != 0) return false;
9555     // Isolate the array index form the full hash field.
9556     *index = ArrayIndexValueBits::decode(field);
9557     return true;
9558   } else {
9559     return ComputeArrayIndex(index);
9560   }
9561 }
9562
9563
9564 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9565   int new_size, old_size;
9566   int old_length = string->length();
9567   if (old_length <= new_length) return string;
9568
9569   if (string->IsSeqOneByteString()) {
9570     old_size = SeqOneByteString::SizeFor(old_length);
9571     new_size = SeqOneByteString::SizeFor(new_length);
9572   } else {
9573     DCHECK(string->IsSeqTwoByteString());
9574     old_size = SeqTwoByteString::SizeFor(old_length);
9575     new_size = SeqTwoByteString::SizeFor(new_length);
9576   }
9577
9578   int delta = old_size - new_size;
9579
9580   Address start_of_string = string->address();
9581   DCHECK_OBJECT_ALIGNED(start_of_string);
9582   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9583
9584   Heap* heap = string->GetHeap();
9585   NewSpace* newspace = heap->new_space();
9586   if (newspace->Contains(start_of_string) &&
9587       newspace->top() == start_of_string + old_size) {
9588     // Last allocated object in new space.  Simply lower allocation top.
9589     newspace->set_top(start_of_string + new_size);
9590   } else {
9591     // Sizes are pointer size aligned, so that we can use filler objects
9592     // that are a multiple of pointer size.
9593     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9594   }
9595   heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9596
9597   // We are storing the new length using release store after creating a filler
9598   // for the left-over space to avoid races with the sweeper thread.
9599   string->synchronized_set_length(new_length);
9600
9601   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9602   return string;
9603 }
9604
9605
9606 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9607   // For array indexes mix the length into the hash as an array index could
9608   // be zero.
9609   DCHECK(length > 0);
9610   DCHECK(length <= String::kMaxArrayIndexSize);
9611   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9612          (1 << String::kArrayIndexValueBits));
9613
9614   value <<= String::ArrayIndexValueBits::kShift;
9615   value |= length << String::ArrayIndexLengthBits::kShift;
9616
9617   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9618   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9619          (value & String::kContainsCachedArrayIndexMask) == 0);
9620   return value;
9621 }
9622
9623
9624 uint32_t StringHasher::GetHashField() {
9625   if (length_ <= String::kMaxHashCalcLength) {
9626     if (is_array_index_) {
9627       return MakeArrayIndexHash(array_index_, length_);
9628     }
9629     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9630            String::kIsNotArrayIndexMask;
9631   } else {
9632     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9633   }
9634 }
9635
9636
9637 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9638                                        uint32_t seed,
9639                                        int* utf16_length_out) {
9640   int vector_length = chars.length();
9641   // Handle some edge cases
9642   if (vector_length <= 1) {
9643     DCHECK(vector_length == 0 ||
9644            static_cast<uint8_t>(chars.start()[0]) <=
9645                unibrow::Utf8::kMaxOneByteChar);
9646     *utf16_length_out = vector_length;
9647     return HashSequentialString(chars.start(), vector_length, seed);
9648   }
9649   // Start with a fake length which won't affect computation.
9650   // It will be updated later.
9651   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9652   size_t remaining = static_cast<size_t>(vector_length);
9653   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9654   int utf16_length = 0;
9655   bool is_index = true;
9656   DCHECK(hasher.is_array_index_);
9657   while (remaining > 0) {
9658     size_t consumed = 0;
9659     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9660     DCHECK(consumed > 0 && consumed <= remaining);
9661     stream += consumed;
9662     remaining -= consumed;
9663     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9664     utf16_length += is_two_characters ? 2 : 1;
9665     // No need to keep hashing. But we do need to calculate utf16_length.
9666     if (utf16_length > String::kMaxHashCalcLength) continue;
9667     if (is_two_characters) {
9668       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9669       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9670       hasher.AddCharacter(c1);
9671       hasher.AddCharacter(c2);
9672       if (is_index) is_index = hasher.UpdateIndex(c1);
9673       if (is_index) is_index = hasher.UpdateIndex(c2);
9674     } else {
9675       hasher.AddCharacter(c);
9676       if (is_index) is_index = hasher.UpdateIndex(c);
9677     }
9678   }
9679   *utf16_length_out = static_cast<int>(utf16_length);
9680   // Must set length here so that hash computation is correct.
9681   hasher.length_ = utf16_length;
9682   return hasher.GetHashField();
9683 }
9684
9685
9686 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
9687   // Run small ConsStrings through ConsStringIterator.
9688   if (cons_string->length() < 64) {
9689     ConsStringIterator iter(cons_string);
9690     int offset;
9691     String* string;
9692     while (nullptr != (string = iter.Next(&offset))) {
9693       DCHECK_EQ(0, offset);
9694       String::VisitFlat(this, string, 0);
9695     }
9696     return;
9697   }
9698   // Slow case.
9699   const int max_length = String::kMaxHashCalcLength;
9700   int length = std::min(cons_string->length(), max_length);
9701   if (cons_string->HasOnlyOneByteChars()) {
9702     uint8_t* buffer = new uint8_t[length];
9703     String::WriteToFlat(cons_string, buffer, 0, length);
9704     AddCharacters(buffer, length);
9705     delete[] buffer;
9706   } else {
9707     uint16_t* buffer = new uint16_t[length];
9708     String::WriteToFlat(cons_string, buffer, 0, length);
9709     AddCharacters(buffer, length);
9710     delete[] buffer;
9711   }
9712 }
9713
9714
9715 void String::PrintOn(FILE* file) {
9716   int length = this->length();
9717   for (int i = 0; i < length; i++) {
9718     PrintF(file, "%c", Get(i));
9719   }
9720 }
9721
9722
9723 inline static uint32_t ObjectAddressForHashing(Object* object) {
9724   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9725   return value & MemoryChunk::kAlignmentMask;
9726 }
9727
9728
9729 int Map::Hash() {
9730   // For performance reasons we only hash the 3 most variable fields of a map:
9731   // constructor, prototype and bit_field2. For predictability reasons we
9732   // use objects' offsets in respective pages for hashing instead of raw
9733   // addresses.
9734
9735   // Shift away the tag.
9736   int hash = ObjectAddressForHashing(constructor()) >> 2;
9737
9738   // XOR-ing the prototype and constructor directly yields too many zero bits
9739   // when the two pointers are close (which is fairly common).
9740   // To avoid this we shift the prototype bits relatively to the constructor.
9741   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9742
9743   return hash ^ (hash >> 16) ^ bit_field2();
9744 }
9745
9746
9747 static bool CheckEquivalent(Map* first, Map* second) {
9748   return first->constructor() == second->constructor() &&
9749          first->prototype() == second->prototype() &&
9750          first->instance_type() == second->instance_type() &&
9751          first->bit_field() == second->bit_field() &&
9752          first->is_extensible() == second->is_extensible() &&
9753          first->has_instance_call_handler() ==
9754              second->has_instance_call_handler();
9755 }
9756
9757
9758 bool Map::EquivalentToForTransition(Map* other) {
9759   return CheckEquivalent(this, other);
9760 }
9761
9762
9763 bool Map::EquivalentToForNormalization(Map* other,
9764                                        PropertyNormalizationMode mode) {
9765   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9766       ? 0 : other->inobject_properties();
9767   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
9768          inobject_properties() == properties;
9769 }
9770
9771
9772 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9773   // Unfortunately the serializer relies on pointers within an object being
9774   // visited in-order, so we have to iterate both the code and heap pointers in
9775   // the small section before doing so in the extended section.
9776   for (int s = 0; s <= final_section(); ++s) {
9777     LayoutSection section = static_cast<LayoutSection>(s);
9778     ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR,
9779                                           section);
9780     while (!code_iter.is_finished()) {
9781       v->VisitCodeEntry(reinterpret_cast<Address>(
9782           RawFieldOfElementAt(code_iter.next_index())));
9783     }
9784
9785     ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR,
9786                                           section);
9787     while (!heap_iter.is_finished()) {
9788       v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9789     }
9790   }
9791 }
9792
9793
9794 void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) {
9795   Type type[] = { CODE_PTR, HEAP_PTR };
9796   Address default_value[] = {
9797         isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9798         reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9799
9800   for (int i = 0; i < 2; ++i) {
9801     for (int s = 0; s <= final_section(); ++s) {
9802       LayoutSection section = static_cast<LayoutSection>(s);
9803       if (number_of_entries(type[i], section) > 0) {
9804         int offset = OffsetOfElementAt(first_index(type[i], section));
9805         MemsetPointer(
9806           reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9807           default_value[i],
9808           number_of_entries(type[i], section));
9809       }
9810     }
9811   }
9812 }
9813
9814
9815 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9816   // Iterate over all fields in the body but take care in dealing with
9817   // the code entry.
9818   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9819   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9820   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9821 }
9822
9823
9824 void JSFunction::MarkForOptimization() {
9825   Isolate* isolate = GetIsolate();
9826   DCHECK(isolate->use_crankshaft());
9827   DCHECK(!IsOptimized());
9828   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9829   set_code_no_write_barrier(
9830       isolate->builtins()->builtin(Builtins::kCompileOptimized));
9831   // No write barrier required, since the builtin is part of the root set.
9832 }
9833
9834
9835 void JSFunction::AttemptConcurrentOptimization() {
9836   Isolate* isolate = GetIsolate();
9837   if (!isolate->concurrent_recompilation_enabled() ||
9838       isolate->bootstrapper()->IsActive()) {
9839     MarkForOptimization();
9840     return;
9841   }
9842   if (isolate->concurrent_osr_enabled() &&
9843       isolate->optimizing_compiler_thread()->IsQueuedForOSR(this)) {
9844     // Do not attempt regular recompilation if we already queued this for OSR.
9845     // TODO(yangguo): This is necessary so that we don't install optimized
9846     // code on a function that is already optimized, since OSR and regular
9847     // recompilation race.  This goes away as soon as OSR becomes one-shot.
9848     return;
9849   }
9850   DCHECK(isolate->use_crankshaft());
9851   DCHECK(!IsInOptimizationQueue());
9852   DCHECK(is_compiled() || isolate->debug()->has_break_points());
9853   DCHECK(!IsOptimized());
9854   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9855   DCHECK(isolate->concurrent_recompilation_enabled());
9856   if (FLAG_trace_concurrent_recompilation) {
9857     PrintF("  ** Marking ");
9858     ShortPrint();
9859     PrintF(" for concurrent recompilation.\n");
9860   }
9861   set_code_no_write_barrier(
9862       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9863   // No write barrier required, since the builtin is part of the root set.
9864 }
9865
9866
9867 Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9868   Isolate* isolate = function->GetIsolate();
9869   Handle<Map> map(function->map());
9870   Handle<SharedFunctionInfo> shared(function->shared());
9871   Handle<Context> context(function->context());
9872   Handle<JSFunction> clone =
9873       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9874
9875   if (shared->bound()) {
9876     clone->set_function_bindings(function->function_bindings());
9877   }
9878
9879   // In typical case, __proto__ of ``function`` is the default Function
9880   // prototype, which means that SetPrototype below is a no-op.
9881   // In rare cases when that is not true, we mutate the clone's __proto__.
9882   Handle<Object> original_prototype(map->prototype(), isolate);
9883   if (*original_prototype != clone->map()->prototype()) {
9884     JSObject::SetPrototype(clone, original_prototype, false).Assert();
9885   }
9886
9887   return clone;
9888 }
9889
9890
9891 void SharedFunctionInfo::AddToOptimizedCodeMap(
9892     Handle<SharedFunctionInfo> shared,
9893     Handle<Context> native_context,
9894     Handle<Code> code,
9895     Handle<FixedArray> literals,
9896     BailoutId osr_ast_id) {
9897   Isolate* isolate = shared->GetIsolate();
9898   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9899   DCHECK(native_context->IsNativeContext());
9900   STATIC_ASSERT(kEntryLength == 4);
9901   Handle<FixedArray> new_code_map;
9902   Handle<Object> value(shared->optimized_code_map(), isolate);
9903   int old_length;
9904   if (value->IsSmi()) {
9905     // No optimized code map.
9906     DCHECK_EQ(0, Smi::cast(*value)->value());
9907     // Create 3 entries per context {context, code, literals}.
9908     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9909     old_length = kEntriesStart;
9910   } else {
9911     // Copy old map and append one new entry.
9912     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9913     DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9914     old_length = old_code_map->length();
9915     new_code_map = FixedArray::CopySize(
9916         old_code_map, old_length + kEntryLength);
9917     // Zap the old map for the sake of the heap verifier.
9918     if (Heap::ShouldZapGarbage()) {
9919       Object** data = old_code_map->data_start();
9920       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9921     }
9922   }
9923   new_code_map->set(old_length + kContextOffset, *native_context);
9924   new_code_map->set(old_length + kCachedCodeOffset, *code);
9925   new_code_map->set(old_length + kLiteralsOffset, *literals);
9926   new_code_map->set(old_length + kOsrAstIdOffset,
9927                     Smi::FromInt(osr_ast_id.ToInt()));
9928
9929 #ifdef DEBUG
9930   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9931     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9932     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9933     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9934            Code::OPTIMIZED_FUNCTION);
9935     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9936     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9937   }
9938 #endif
9939   shared->set_optimized_code_map(*new_code_map);
9940 }
9941
9942
9943 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9944   DCHECK(index > kEntriesStart);
9945   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9946   if (!bound()) {
9947     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9948     DCHECK_NOT_NULL(cached_literals);
9949     return cached_literals;
9950   }
9951   return NULL;
9952 }
9953
9954
9955 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9956   DCHECK(index > kEntriesStart);
9957   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9958   Code* code = Code::cast(code_map->get(index));
9959   DCHECK_NOT_NULL(code);
9960   return code;
9961 }
9962
9963
9964 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9965   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9966
9967   // If the next map link slot is already used then the function was
9968   // enqueued with code flushing and we remove it now.
9969   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9970     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9971     flusher->EvictOptimizedCodeMap(this);
9972   }
9973
9974   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9975   set_optimized_code_map(Smi::FromInt(0));
9976 }
9977
9978
9979 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9980                                                    const char* reason) {
9981   DisallowHeapAllocation no_gc;
9982   if (optimized_code_map()->IsSmi()) return;
9983
9984   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9985   int dst = kEntriesStart;
9986   int length = code_map->length();
9987   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9988     DCHECK(code_map->get(src)->IsNativeContext());
9989     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9990       // Evict the src entry by not copying it to the dst entry.
9991       if (FLAG_trace_opt) {
9992         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9993         ShortPrint();
9994         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9995         if (osr.IsNone()) {
9996           PrintF("]\n");
9997         } else {
9998           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9999         }
10000       }
10001     } else {
10002       // Keep the src entry by copying it to the dst entry.
10003       if (dst != src) {
10004         code_map->set(dst + kContextOffset,
10005                       code_map->get(src + kContextOffset));
10006         code_map->set(dst + kCachedCodeOffset,
10007                       code_map->get(src + kCachedCodeOffset));
10008         code_map->set(dst + kLiteralsOffset,
10009                       code_map->get(src + kLiteralsOffset));
10010         code_map->set(dst + kOsrAstIdOffset,
10011                       code_map->get(src + kOsrAstIdOffset));
10012       }
10013       dst += kEntryLength;
10014     }
10015   }
10016   if (dst != length) {
10017     // Always trim even when array is cleared because of heap verifier.
10018     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(code_map, length - dst);
10019     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
10020   }
10021 }
10022
10023
10024 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
10025   FixedArray* code_map = FixedArray::cast(optimized_code_map());
10026   DCHECK(shrink_by % kEntryLength == 0);
10027   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
10028   // Always trim even when array is cleared because of heap verifier.
10029   GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
10030   if (code_map->length() == kEntriesStart) {
10031     ClearOptimizedCodeMap();
10032   }
10033 }
10034
10035
10036 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
10037                                    PrototypeOptimizationMode mode) {
10038   if (object->IsGlobalObject()) return;
10039   if (object->IsJSGlobalProxy()) return;
10040   if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
10041     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
10042     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
10043                                   "NormalizeAsPrototype");
10044   }
10045   bool has_just_copied_map = false;
10046   if (!object->HasFastProperties()) {
10047     JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
10048     has_just_copied_map = true;
10049   }
10050   if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
10051       !object->map()->is_prototype_map()) {
10052     if (!has_just_copied_map) {
10053       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
10054       JSObject::MigrateToMap(object, new_map);
10055     }
10056     if (object->map()->constructor()->IsJSFunction()) {
10057       JSFunction* constructor = JSFunction::cast(object->map()->constructor());
10058       // Replace the pointer to the exact constructor with the Object function
10059       // from the same context if undetectable from JS. This is to avoid keeping
10060       // memory alive unnecessarily.
10061       if (!constructor->shared()->IsApiFunction() &&
10062           object->class_name() ==
10063               object->GetIsolate()->heap()->Object_string()) {
10064         Context* context = constructor->context()->native_context();
10065         JSFunction* object_function = context->object_function();
10066         object->map()->set_constructor(object_function);
10067       }
10068     }
10069     object->map()->set_is_prototype_map(true);
10070   }
10071 }
10072
10073
10074 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
10075   if (!object->map()->is_prototype_map()) return;
10076   OptimizeAsPrototype(object, FAST_PROTOTYPE);
10077 }
10078
10079
10080 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
10081                                      Handle<HeapObject> user) {
10082   DCHECK(FLAG_track_prototype_users);
10083   Isolate* isolate = prototype->GetIsolate();
10084   Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
10085
10086   // Get prototype users array, create it if it doesn't exist yet.
10087   Handle<Object> maybe_array =
10088       JSObject::GetProperty(prototype, symbol).ToHandleChecked();
10089
10090   Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user);
10091   if (!maybe_array.is_identical_to(new_array)) {
10092     JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array,
10093                                              DONT_ENUM).Assert();
10094   }
10095 }
10096
10097
10098 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
10099                                        Handle<HeapObject> user) {
10100   Isolate* isolate = prototype->GetIsolate();
10101   Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
10102
10103   Handle<Object> maybe_array =
10104       JSObject::GetProperty(prototype, symbol).ToHandleChecked();
10105   if (!maybe_array->IsWeakFixedArray()) return;
10106   Handle<WeakFixedArray>::cast(maybe_array)->Remove(user);
10107 }
10108
10109
10110 void Map::SetPrototype(Handle<Object> prototype,
10111                        PrototypeOptimizationMode proto_mode) {
10112   if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
10113     Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
10114     JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
10115   }
10116   if (prototype->IsJSObject()) {
10117     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
10118     if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
10119       JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
10120     }
10121     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
10122   }
10123   WriteBarrierMode wb_mode =
10124       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
10125   set_prototype(*prototype, wb_mode);
10126 }
10127
10128
10129 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
10130   if (!FLAG_track_prototype_users) return false;
10131   if (this->is_prototype_map()) return true;
10132   if (this->is_dictionary_map()) return false;
10133   Object* back = GetBackPointer();
10134   if (!back->IsMap()) return true;
10135   if (Map::cast(back)->prototype() != *prototype) return true;
10136   return false;
10137 }
10138
10139
10140 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
10141   if (!FLAG_track_prototype_users) return false;
10142   if (this->is_prototype_map()) return true;
10143   if (GetBackPointer()->IsMap()) return true;
10144   return false;
10145 }
10146
10147
10148 Handle<Object> CacheInitialJSArrayMaps(
10149     Handle<Context> native_context, Handle<Map> initial_map) {
10150   // Replace all of the cached initial array maps in the native context with
10151   // the appropriate transitioned elements kind maps.
10152   Factory* factory = native_context->GetIsolate()->factory();
10153   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10154       kElementsKindCount, TENURED);
10155
10156   Handle<Map> current_map = initial_map;
10157   ElementsKind kind = current_map->elements_kind();
10158   DCHECK(kind == GetInitialFastElementsKind());
10159   maps->set(kind, *current_map);
10160   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
10161        i < kFastElementsKindCount; ++i) {
10162     Handle<Map> new_map;
10163     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
10164     if (current_map->HasElementsTransition()) {
10165       new_map = handle(current_map->elements_transition_map());
10166       DCHECK(new_map->elements_kind() == next_kind);
10167     } else {
10168       new_map = Map::CopyAsElementsKind(
10169           current_map, next_kind, INSERT_TRANSITION);
10170     }
10171     maps->set(next_kind, *new_map);
10172     current_map = new_map;
10173   }
10174   native_context->set_js_array_maps(*maps);
10175   return initial_map;
10176 }
10177
10178
10179 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
10180                                       Handle<Object> value) {
10181   Isolate* isolate = function->GetIsolate();
10182
10183   DCHECK(value->IsJSReceiver());
10184
10185   // Now some logic for the maps of the objects that are created by using this
10186   // function as a constructor.
10187   if (function->has_initial_map()) {
10188     // If the function has allocated the initial map replace it with a
10189     // copy containing the new prototype.  Also complete any in-object
10190     // slack tracking that is in progress at this point because it is
10191     // still tracking the old copy.
10192     if (function->IsInobjectSlackTrackingInProgress()) {
10193       function->CompleteInobjectSlackTracking();
10194     }
10195
10196     Handle<Map> initial_map(function->initial_map(), isolate);
10197
10198     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
10199         initial_map->instance_type() == JS_OBJECT_TYPE) {
10200       // Put the value in the initial map field until an initial map is needed.
10201       // At that point, a new initial map is created and the prototype is put
10202       // into the initial map where it belongs.
10203       function->set_prototype_or_initial_map(*value);
10204     } else {
10205       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
10206       JSFunction::SetInitialMap(function, new_map, value);
10207
10208       // If the function is used as the global Array function, cache the
10209       // initial map (and transitioned versions) in the native context.
10210       Context* native_context = function->context()->native_context();
10211       Object* array_function =
10212           native_context->get(Context::ARRAY_FUNCTION_INDEX);
10213       if (array_function->IsJSFunction() &&
10214           *function == JSFunction::cast(array_function)) {
10215         CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
10216       }
10217     }
10218
10219     // Deoptimize all code that embeds the previous initial map.
10220     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
10221         isolate, DependentCode::kInitialMapChangedGroup);
10222   } else {
10223     // Put the value in the initial map field until an initial map is
10224     // needed.  At that point, a new initial map is created and the
10225     // prototype is put into the initial map where it belongs.
10226     function->set_prototype_or_initial_map(*value);
10227   }
10228   isolate->heap()->ClearInstanceofCache();
10229 }
10230
10231
10232 void JSFunction::SetPrototype(Handle<JSFunction> function,
10233                               Handle<Object> value) {
10234   DCHECK(function->should_have_prototype());
10235   Handle<Object> construct_prototype = value;
10236
10237   // If the value is not a JSReceiver, store the value in the map's
10238   // constructor field so it can be accessed.  Also, set the prototype
10239   // used for constructing objects to the original object prototype.
10240   // See ECMA-262 13.2.2.
10241   if (!value->IsJSReceiver()) {
10242     // Copy the map so this does not affect unrelated functions.
10243     // Remove map transitions because they point to maps with a
10244     // different prototype.
10245     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
10246
10247     JSObject::MigrateToMap(function, new_map);
10248     new_map->set_constructor(*value);
10249     new_map->set_non_instance_prototype(true);
10250     Isolate* isolate = new_map->GetIsolate();
10251     construct_prototype = handle(
10252         isolate->context()->native_context()->initial_object_prototype(),
10253         isolate);
10254   } else {
10255     function->map()->set_non_instance_prototype(false);
10256   }
10257
10258   return SetInstancePrototype(function, construct_prototype);
10259 }
10260
10261
10262 bool JSFunction::RemovePrototype() {
10263   Context* native_context = context()->native_context();
10264   Map* no_prototype_map =
10265       is_strict(shared()->language_mode())
10266           ? native_context->strict_function_without_prototype_map()
10267           : native_context->sloppy_function_without_prototype_map();
10268
10269   if (map() == no_prototype_map) return true;
10270
10271 #ifdef DEBUG
10272   if (map() != (is_strict(shared()->language_mode())
10273                     ? native_context->strict_function_map()
10274                     : native_context->sloppy_function_map())) {
10275     return false;
10276   }
10277 #endif
10278
10279   set_map(no_prototype_map);
10280   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
10281   return true;
10282 }
10283
10284
10285 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
10286                                Handle<Object> prototype) {
10287   if (map->prototype() != *prototype) {
10288     map->SetPrototype(prototype, FAST_PROTOTYPE);
10289   }
10290   function->set_prototype_or_initial_map(*map);
10291   map->set_constructor(*function);
10292 #if TRACE_MAPS
10293   if (FLAG_trace_maps) {
10294     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
10295            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
10296            function->shared()->DebugName()->ToCString().get());
10297   }
10298 #endif
10299 }
10300
10301
10302 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
10303   if (function->has_initial_map()) return;
10304   Isolate* isolate = function->GetIsolate();
10305
10306   // First create a new map with the size and number of in-object properties
10307   // suggested by the function.
10308   InstanceType instance_type;
10309   int instance_size;
10310   int in_object_properties;
10311   if (function->shared()->is_generator()) {
10312     instance_type = JS_GENERATOR_OBJECT_TYPE;
10313     instance_size = JSGeneratorObject::kSize;
10314     in_object_properties = 0;
10315   } else {
10316     instance_type = JS_OBJECT_TYPE;
10317     instance_size = function->shared()->CalculateInstanceSize();
10318     in_object_properties = function->shared()->CalculateInObjectProperties();
10319   }
10320   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10321
10322   // Fetch or allocate prototype.
10323   Handle<Object> prototype;
10324   if (function->has_instance_prototype()) {
10325     prototype = handle(function->instance_prototype(), isolate);
10326   } else {
10327     prototype = isolate->factory()->NewFunctionPrototype(function);
10328   }
10329   map->set_inobject_properties(in_object_properties);
10330   map->set_unused_property_fields(in_object_properties);
10331   DCHECK(map->has_fast_object_elements());
10332
10333   // Finally link initial map and constructor function.
10334   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10335
10336   if (!function->shared()->is_generator()) {
10337     function->StartInobjectSlackTracking();
10338   }
10339 }
10340
10341
10342 void JSFunction::SetInstanceClassName(String* name) {
10343   shared()->set_instance_class_name(name);
10344 }
10345
10346
10347 void JSFunction::PrintName(FILE* out) {
10348   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10349   PrintF(out, "%s", name.get());
10350 }
10351
10352
10353 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
10354   return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
10355 }
10356
10357
10358 // The filter is a pattern that matches function names in this way:
10359 //   "*"      all; the default
10360 //   "-"      all but the top-level function
10361 //   "-name"  all but the function "name"
10362 //   ""       only the top-level function
10363 //   "name"   only the function "name"
10364 //   "name*"  only functions starting with "name"
10365 //   "~"      none; the tilde is not an identifier
10366 bool JSFunction::PassesFilter(const char* raw_filter) {
10367   if (*raw_filter == '*') return true;
10368   String* name = shared()->DebugName();
10369   Vector<const char> filter = CStrVector(raw_filter);
10370   if (filter.length() == 0) return name->length() == 0;
10371   if (filter[0] == '-') {
10372     // Negative filter.
10373     if (filter.length() == 1) {
10374       return (name->length() != 0);
10375     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10376       return false;
10377     }
10378     if (filter[filter.length() - 1] == '*' &&
10379         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10380       return false;
10381     }
10382     return true;
10383
10384   } else if (name->IsUtf8EqualTo(filter)) {
10385     return true;
10386   }
10387   if (filter[filter.length() - 1] == '*' &&
10388       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10389     return true;
10390   }
10391   return false;
10392 }
10393
10394
10395 void Oddball::Initialize(Isolate* isolate,
10396                          Handle<Oddball> oddball,
10397                          const char* to_string,
10398                          Handle<Object> to_number,
10399                          byte kind) {
10400   Handle<String> internalized_to_string =
10401       isolate->factory()->InternalizeUtf8String(to_string);
10402   oddball->set_to_string(*internalized_to_string);
10403   oddball->set_to_number(*to_number);
10404   oddball->set_kind(kind);
10405 }
10406
10407
10408 void Script::InitLineEnds(Handle<Script> script) {
10409   if (!script->line_ends()->IsUndefined()) return;
10410
10411   Isolate* isolate = script->GetIsolate();
10412
10413   if (!script->source()->IsString()) {
10414     DCHECK(script->source()->IsUndefined());
10415     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10416     script->set_line_ends(*empty);
10417     DCHECK(script->line_ends()->IsFixedArray());
10418     return;
10419   }
10420
10421   Handle<String> src(String::cast(script->source()), isolate);
10422
10423   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10424
10425   if (*array != isolate->heap()->empty_fixed_array()) {
10426     array->set_map(isolate->heap()->fixed_cow_array_map());
10427   }
10428
10429   script->set_line_ends(*array);
10430   DCHECK(script->line_ends()->IsFixedArray());
10431 }
10432
10433
10434 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10435   int line_number = GetLineNumber(script, code_pos);
10436   if (line_number == -1) return -1;
10437
10438   DisallowHeapAllocation no_allocation;
10439   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10440   line_number = line_number - script->line_offset()->value();
10441   if (line_number == 0) return code_pos + script->column_offset()->value();
10442   int prev_line_end_pos =
10443       Smi::cast(line_ends_array->get(line_number - 1))->value();
10444   return code_pos - (prev_line_end_pos + 1);
10445 }
10446
10447
10448 int Script::GetLineNumberWithArray(int position) {
10449   DisallowHeapAllocation no_allocation;
10450   FixedArray* line_ends = FixedArray::cast(this->line_ends());
10451   int upper = line_ends->length() - 1;
10452   if (upper < 0) return -1;
10453   int offset = line_offset()->value();
10454
10455   if (position > Smi::cast(line_ends->get(upper))->value()) {
10456     return upper + 1 + offset;
10457   }
10458   if (position <= Smi::cast(line_ends->get(0))->value()) return offset;
10459
10460   int lower = 1;
10461   // Binary search.
10462   while (true) {
10463     int mid = (lower + upper) / 2;
10464     if (position <= Smi::cast(line_ends->get(mid - 1))->value()) {
10465       upper = mid - 1;
10466     } else if (position > Smi::cast(line_ends->get(mid))->value()) {
10467       lower = mid + 1;
10468     } else {
10469       return mid + offset;
10470     }
10471   }
10472   return -1;
10473 }
10474
10475
10476 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10477   InitLineEnds(script);
10478   return script->GetLineNumberWithArray(code_pos);
10479 }
10480
10481
10482 int Script::GetLineNumber(int code_pos) {
10483   DisallowHeapAllocation no_allocation;
10484   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10485
10486   // Slow mode: we do not have line_ends. We have to iterate through source.
10487   if (!source()->IsString()) return -1;
10488
10489   String* source_string = String::cast(source());
10490   int line = 0;
10491   int len = source_string->length();
10492   for (int pos = 0; pos < len; pos++) {
10493     if (pos == code_pos) break;
10494     if (source_string->Get(pos) == '\n') line++;
10495   }
10496   return line;
10497 }
10498
10499
10500 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10501   Isolate* isolate = script->GetIsolate();
10502   Handle<String> name_or_source_url_key =
10503       isolate->factory()->InternalizeOneByteString(
10504           STATIC_CHAR_VECTOR("nameOrSourceURL"));
10505   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10506   Handle<Object> property = Object::GetProperty(
10507       script_wrapper, name_or_source_url_key).ToHandleChecked();
10508   DCHECK(property->IsJSFunction());
10509   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10510   Handle<Object> result;
10511   // Do not check against pending exception, since this function may be called
10512   // when an exception has already been pending.
10513   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10514     return isolate->factory()->undefined_value();
10515   }
10516   return result;
10517 }
10518
10519
10520 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10521   Isolate* isolate = script->GetIsolate();
10522   if (!script->wrapper()->IsUndefined()) {
10523     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
10524     if (!cell->cleared()) {
10525       // Return a handle for the existing script wrapper from the cache.
10526       return handle(JSObject::cast(cell->value()));
10527     }
10528     // If we found an empty WeakCell, that means the script wrapper was
10529     // GCed.  We are not notified directly of that, so we decrement here
10530     // so that we at least don't count double for any given script.
10531     isolate->counters()->script_wrappers()->Decrement();
10532   }
10533   // Construct a new script wrapper.
10534   isolate->counters()->script_wrappers()->Increment();
10535   Handle<JSFunction> constructor = isolate->script_function();
10536   Handle<JSValue> result =
10537       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10538   result->set_value(*script);
10539   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
10540   script->set_wrapper(*cell);
10541   return result;
10542 }
10543
10544
10545 String* SharedFunctionInfo::DebugName() {
10546   Object* n = name();
10547   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10548   return String::cast(n);
10549 }
10550
10551
10552 bool SharedFunctionInfo::HasSourceCode() const {
10553   return !script()->IsUndefined() &&
10554          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10555 }
10556
10557
10558 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10559   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10560   Handle<String> source(String::cast(Script::cast(script())->source()));
10561   return GetIsolate()->factory()->NewSubString(
10562       source, start_position(), end_position());
10563 }
10564
10565
10566 bool SharedFunctionInfo::IsInlineable() {
10567   // Check that the function has a script associated with it.
10568   if (!script()->IsScript()) return false;
10569   if (optimization_disabled()) return false;
10570   // If we never ran this (unlikely) then lets try to optimize it.
10571   if (code()->kind() != Code::FUNCTION) return true;
10572   return code()->optimizable();
10573 }
10574
10575
10576 int SharedFunctionInfo::SourceSize() {
10577   return end_position() - start_position();
10578 }
10579
10580
10581 int SharedFunctionInfo::CalculateInstanceSize() {
10582   int instance_size =
10583       JSObject::kHeaderSize +
10584       expected_nof_properties() * kPointerSize;
10585   if (instance_size > JSObject::kMaxInstanceSize) {
10586     instance_size = JSObject::kMaxInstanceSize;
10587   }
10588   return instance_size;
10589 }
10590
10591
10592 int SharedFunctionInfo::CalculateInObjectProperties() {
10593   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10594 }
10595
10596
10597 // Output the source code without any allocation in the heap.
10598 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
10599   const SharedFunctionInfo* s = v.value;
10600   // For some native functions there is no source.
10601   if (!s->HasSourceCode()) return os << "<No Source>";
10602
10603   // Get the source for the script which this function came from.
10604   // Don't use String::cast because we don't want more assertion errors while
10605   // we are already creating a stack dump.
10606   String* script_source =
10607       reinterpret_cast<String*>(Script::cast(s->script())->source());
10608
10609   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10610
10611   if (!s->is_toplevel()) {
10612     os << "function ";
10613     Object* name = s->name();
10614     if (name->IsString() && String::cast(name)->length() > 0) {
10615       String::cast(name)->PrintUC16(os);
10616     }
10617   }
10618
10619   int len = s->end_position() - s->start_position();
10620   if (len <= v.max_length || v.max_length < 0) {
10621     script_source->PrintUC16(os, s->start_position(), s->end_position());
10622     return os;
10623   } else {
10624     script_source->PrintUC16(os, s->start_position(),
10625                              s->start_position() + v.max_length);
10626     return os << "...\n";
10627   }
10628 }
10629
10630
10631 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10632   if (code->instruction_size() != recompiled->instruction_size()) return false;
10633   ByteArray* code_relocation = code->relocation_info();
10634   ByteArray* recompiled_relocation = recompiled->relocation_info();
10635   int length = code_relocation->length();
10636   if (length != recompiled_relocation->length()) return false;
10637   int compare = memcmp(code_relocation->GetDataStartAddress(),
10638                        recompiled_relocation->GetDataStartAddress(),
10639                        length);
10640   return compare == 0;
10641 }
10642
10643
10644 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10645   DCHECK(!has_deoptimization_support());
10646   DisallowHeapAllocation no_allocation;
10647   Code* code = this->code();
10648   if (IsCodeEquivalent(code, recompiled)) {
10649     // Copy the deoptimization data from the recompiled code.
10650     code->set_deoptimization_data(recompiled->deoptimization_data());
10651     code->set_has_deoptimization_support(true);
10652   } else {
10653     // TODO(3025757): In case the recompiled isn't equivalent to the
10654     // old code, we have to replace it. We should try to avoid this
10655     // altogether because it flushes valuable type feedback by
10656     // effectively resetting all IC state.
10657     ReplaceCode(recompiled);
10658   }
10659   DCHECK(has_deoptimization_support());
10660 }
10661
10662
10663 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10664   // Disable optimization for the shared function info and mark the
10665   // code as non-optimizable. The marker on the shared function info
10666   // is there because we flush non-optimized code thereby loosing the
10667   // non-optimizable information for the code. When the code is
10668   // regenerated and set on the shared function info it is marked as
10669   // non-optimizable if optimization is disabled for the shared
10670   // function info.
10671   DCHECK(reason != kNoReason);
10672   set_optimization_disabled(true);
10673   set_disable_optimization_reason(reason);
10674   // Code should be the lazy compilation stub or else unoptimized.  If the
10675   // latter, disable optimization for the code too.
10676   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10677   if (code()->kind() == Code::FUNCTION) {
10678     code()->set_optimizable(false);
10679   }
10680   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10681   if (FLAG_trace_opt) {
10682     PrintF("[disabled optimization for ");
10683     ShortPrint();
10684     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10685   }
10686 }
10687
10688
10689 void SharedFunctionInfo::InitFromFunctionLiteral(
10690     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
10691   shared_info->set_length(lit->scope()->default_function_length());
10692   if (IsSubclassConstructor(lit->kind())) {
10693     shared_info->set_internal_formal_parameter_count(lit->parameter_count() +
10694                                                      1);
10695   } else {
10696     shared_info->set_internal_formal_parameter_count(lit->parameter_count());
10697   }
10698   shared_info->set_function_token_position(lit->function_token_position());
10699   shared_info->set_start_position(lit->start_position());
10700   shared_info->set_end_position(lit->end_position());
10701   shared_info->set_is_expression(lit->is_expression());
10702   shared_info->set_is_anonymous(lit->is_anonymous());
10703   shared_info->set_inferred_name(*lit->inferred_name());
10704   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
10705   shared_info->set_allows_lazy_compilation_without_context(
10706       lit->AllowsLazyCompilationWithoutContext());
10707   shared_info->set_language_mode(lit->language_mode());
10708   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
10709   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
10710   shared_info->set_ast_node_count(lit->ast_node_count());
10711   shared_info->set_is_function(lit->is_function());
10712   if (lit->dont_optimize_reason() != kNoReason) {
10713     shared_info->DisableOptimization(lit->dont_optimize_reason());
10714   }
10715   shared_info->set_dont_cache(
10716       lit->flags()->Contains(AstPropertiesFlag::kDontCache));
10717   shared_info->set_kind(lit->kind());
10718   shared_info->set_uses_super_property(lit->uses_super_property());
10719   shared_info->set_asm_function(lit->scope()->asm_function());
10720 }
10721
10722
10723 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10724   DCHECK(!id.IsNone());
10725   Code* unoptimized = code();
10726   DeoptimizationOutputData* data =
10727       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10728   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10729   USE(ignore);
10730   return true;  // Return true if there was no DCHECK.
10731 }
10732
10733
10734 void JSFunction::StartInobjectSlackTracking() {
10735   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10736
10737   Map* map = initial_map();
10738
10739   // No tracking during the snapshot construction phase.
10740   Isolate* isolate = GetIsolate();
10741   if (isolate->serializer_enabled()) return;
10742
10743   if (map->unused_property_fields() == 0) return;
10744
10745   map->set_counter(Map::kSlackTrackingCounterStart);
10746 }
10747
10748
10749 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10750   code()->ClearInlineCaches();
10751   // If we clear ICs, we need to clear the type feedback vector too, since
10752   // CallICs are synced with a feedback vector slot.
10753   ClearTypeFeedbackInfo();
10754   set_ic_age(new_ic_age);
10755   if (code()->kind() == Code::FUNCTION) {
10756     code()->set_profiler_ticks(0);
10757     if (optimization_disabled() &&
10758         opt_count() >= FLAG_max_opt_count) {
10759       // Re-enable optimizations if they were disabled due to opt_count limit.
10760       set_optimization_disabled(false);
10761       code()->set_optimizable(true);
10762     }
10763     set_opt_count(0);
10764     set_deopt_count(0);
10765   }
10766 }
10767
10768
10769 static void GetMinInobjectSlack(Map* map, void* data) {
10770   int slack = map->unused_property_fields();
10771   if (*reinterpret_cast<int*>(data) > slack) {
10772     *reinterpret_cast<int*>(data) = slack;
10773   }
10774 }
10775
10776
10777 static void ShrinkInstanceSize(Map* map, void* data) {
10778   int slack = *reinterpret_cast<int*>(data);
10779   map->set_inobject_properties(map->inobject_properties() - slack);
10780   map->set_unused_property_fields(map->unused_property_fields() - slack);
10781   map->set_instance_size(map->instance_size() - slack * kPointerSize);
10782
10783   // Visitor id might depend on the instance size, recalculate it.
10784   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
10785 }
10786
10787
10788 void JSFunction::CompleteInobjectSlackTracking() {
10789   DCHECK(has_initial_map());
10790   Map* map = initial_map();
10791
10792   DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
10793   map->set_counter(Map::kRetainingCounterStart);
10794
10795   int slack = map->unused_property_fields();
10796   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
10797   if (slack != 0) {
10798     // Resize the initial map and all maps in its transition tree.
10799     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
10800   }
10801 }
10802
10803
10804 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
10805                                                BailoutId osr_ast_id) {
10806   DisallowHeapAllocation no_gc;
10807   DCHECK(native_context->IsNativeContext());
10808   if (!FLAG_cache_optimized_code) return -1;
10809   Object* value = optimized_code_map();
10810   if (!value->IsSmi()) {
10811     FixedArray* optimized_code_map = FixedArray::cast(value);
10812     int length = optimized_code_map->length();
10813     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10814     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10815       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10816           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10817         return i + kCachedCodeOffset;
10818       }
10819     }
10820     if (FLAG_trace_opt) {
10821       PrintF("[didn't find optimized code in optimized code map for ");
10822       ShortPrint();
10823       PrintF("]\n");
10824     }
10825   }
10826   return -1;
10827 }
10828
10829
10830 #define DECLARE_TAG(ignore1, name, ignore2) name,
10831 const char* const VisitorSynchronization::kTags[
10832     VisitorSynchronization::kNumberOfSyncTags] = {
10833   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10834 };
10835 #undef DECLARE_TAG
10836
10837
10838 #define DECLARE_TAG(ignore1, ignore2, name) name,
10839 const char* const VisitorSynchronization::kTagNames[
10840     VisitorSynchronization::kNumberOfSyncTags] = {
10841   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10842 };
10843 #undef DECLARE_TAG
10844
10845
10846 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10847   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10848   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10849   Object* old_target = target;
10850   VisitPointer(&target);
10851   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10852 }
10853
10854
10855 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10856   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10857   Object* stub = rinfo->code_age_stub();
10858   if (stub) {
10859     VisitPointer(&stub);
10860   }
10861 }
10862
10863
10864 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10865   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10866   Object* old_code = code;
10867   VisitPointer(&code);
10868   if (code != old_code) {
10869     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10870   }
10871 }
10872
10873
10874 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10875   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10876   Object* cell = rinfo->target_cell();
10877   Object* old_cell = cell;
10878   VisitPointer(&cell);
10879   if (cell != old_cell) {
10880     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10881   }
10882 }
10883
10884
10885 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10886   DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10887           rinfo->IsPatchedReturnSequence()) ||
10888          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10889           rinfo->IsPatchedDebugBreakSlotSequence()));
10890   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10891   Object* old_target = target;
10892   VisitPointer(&target);
10893   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10894 }
10895
10896
10897 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10898   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10899   Object* p = rinfo->target_object();
10900   VisitPointer(&p);
10901 }
10902
10903
10904 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10905   Address p = rinfo->target_reference();
10906   VisitExternalReference(&p);
10907 }
10908
10909
10910 void Code::InvalidateRelocation() {
10911   InvalidateEmbeddedObjects();
10912   set_relocation_info(GetHeap()->empty_byte_array());
10913 }
10914
10915
10916 void Code::InvalidateEmbeddedObjects() {
10917   Object* undefined = GetHeap()->undefined_value();
10918   Cell* undefined_cell = GetHeap()->undefined_cell();
10919   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10920                   RelocInfo::ModeMask(RelocInfo::CELL);
10921   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10922     RelocInfo::Mode mode = it.rinfo()->rmode();
10923     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10924       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10925     } else if (mode == RelocInfo::CELL) {
10926       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10927     }
10928   }
10929 }
10930
10931
10932 void Code::Relocate(intptr_t delta) {
10933   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10934     it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10935   }
10936   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10937 }
10938
10939
10940 void Code::CopyFrom(const CodeDesc& desc) {
10941   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10942
10943   // copy code
10944   CopyBytes(instruction_start(), desc.buffer,
10945             static_cast<size_t>(desc.instr_size));
10946
10947   // copy reloc info
10948   CopyBytes(relocation_start(),
10949             desc.buffer + desc.buffer_size - desc.reloc_size,
10950             static_cast<size_t>(desc.reloc_size));
10951
10952   // unbox handles and relocate
10953   intptr_t delta = instruction_start() - desc.buffer;
10954   int mode_mask = RelocInfo::kCodeTargetMask |
10955                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10956                   RelocInfo::ModeMask(RelocInfo::CELL) |
10957                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10958                   RelocInfo::kApplyMask;
10959   // Needed to find target_object and runtime_entry on X64
10960   Assembler* origin = desc.origin;
10961   AllowDeferredHandleDereference embedding_raw_address;
10962   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10963     RelocInfo::Mode mode = it.rinfo()->rmode();
10964     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10965       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10966       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10967     } else if (mode == RelocInfo::CELL) {
10968       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10969       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10970     } else if (RelocInfo::IsCodeTarget(mode)) {
10971       // rewrite code handles in inline cache targets to direct
10972       // pointers to the first instruction in the code object
10973       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10974       Code* code = Code::cast(*p);
10975       it.rinfo()->set_target_address(code->instruction_start(),
10976                                      SKIP_WRITE_BARRIER,
10977                                      SKIP_ICACHE_FLUSH);
10978     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10979       Address p = it.rinfo()->target_runtime_entry(origin);
10980       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10981                                            SKIP_ICACHE_FLUSH);
10982     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10983       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10984       Code* code = Code::cast(*p);
10985       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10986     } else {
10987       it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10988     }
10989   }
10990   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10991 }
10992
10993
10994 // Locate the source position which is closest to the address in the code. This
10995 // is using the source position information embedded in the relocation info.
10996 // The position returned is relative to the beginning of the script where the
10997 // source for this function is found.
10998 int Code::SourcePosition(Address pc) {
10999   int distance = kMaxInt;
11000   int position = RelocInfo::kNoPosition;  // Initially no position found.
11001   // Run through all the relocation info to find the best matching source
11002   // position. All the code needs to be considered as the sequence of the
11003   // instructions in the code does not necessarily follow the same order as the
11004   // source.
11005   RelocIterator it(this, RelocInfo::kPositionMask);
11006   while (!it.done()) {
11007     // Only look at positions after the current pc.
11008     if (it.rinfo()->pc() < pc) {
11009       // Get position and distance.
11010
11011       int dist = static_cast<int>(pc - it.rinfo()->pc());
11012       int pos = static_cast<int>(it.rinfo()->data());
11013       // If this position is closer than the current candidate or if it has the
11014       // same distance as the current candidate and the position is higher then
11015       // this position is the new candidate.
11016       if ((dist < distance) ||
11017           (dist == distance && pos > position)) {
11018         position = pos;
11019         distance = dist;
11020       }
11021     }
11022     it.next();
11023   }
11024   return position;
11025 }
11026
11027
11028 // Same as Code::SourcePosition above except it only looks for statement
11029 // positions.
11030 int Code::SourceStatementPosition(Address pc) {
11031   // First find the position as close as possible using all position
11032   // information.
11033   int position = SourcePosition(pc);
11034   // Now find the closest statement position before the position.
11035   int statement_position = 0;
11036   RelocIterator it(this, RelocInfo::kPositionMask);
11037   while (!it.done()) {
11038     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
11039       int p = static_cast<int>(it.rinfo()->data());
11040       if (statement_position < p && p <= position) {
11041         statement_position = p;
11042       }
11043     }
11044     it.next();
11045   }
11046   return statement_position;
11047 }
11048
11049
11050 SafepointEntry Code::GetSafepointEntry(Address pc) {
11051   SafepointTable table(this);
11052   return table.FindEntry(pc);
11053 }
11054
11055
11056 Object* Code::FindNthObject(int n, Map* match_map) {
11057   DCHECK(is_inline_cache_stub());
11058   DisallowHeapAllocation no_allocation;
11059   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11060   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11061     RelocInfo* info = it.rinfo();
11062     Object* object = info->target_object();
11063     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
11064     if (object->IsHeapObject()) {
11065       if (HeapObject::cast(object)->map() == match_map) {
11066         if (--n == 0) return object;
11067       }
11068     }
11069   }
11070   return NULL;
11071 }
11072
11073
11074 AllocationSite* Code::FindFirstAllocationSite() {
11075   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
11076   return (result != NULL) ? AllocationSite::cast(result) : NULL;
11077 }
11078
11079
11080 Map* Code::FindFirstMap() {
11081   Object* result = FindNthObject(1, GetHeap()->meta_map());
11082   return (result != NULL) ? Map::cast(result) : NULL;
11083 }
11084
11085
11086 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
11087   DCHECK(is_inline_cache_stub() || is_handler());
11088   DisallowHeapAllocation no_allocation;
11089   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11090   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
11091   int current_pattern = 0;
11092   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11093     RelocInfo* info = it.rinfo();
11094     Object* object = info->target_object();
11095     if (object->IsHeapObject()) {
11096       if (object->IsWeakCell()) {
11097         object = HeapObject::cast(WeakCell::cast(object)->value());
11098       }
11099       Map* map = HeapObject::cast(object)->map();
11100       if (map == *pattern.find_[current_pattern]) {
11101         info->set_target_object(*pattern.replace_[current_pattern]);
11102         if (++current_pattern == pattern.count_) return;
11103       }
11104     }
11105   }
11106   UNREACHABLE();
11107 }
11108
11109
11110 void Code::FindAllMaps(MapHandleList* maps) {
11111   DCHECK(is_inline_cache_stub());
11112   DisallowHeapAllocation no_allocation;
11113   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11114   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11115     RelocInfo* info = it.rinfo();
11116     Object* object = info->target_object();
11117     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
11118     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
11119   }
11120 }
11121
11122
11123 Code* Code::FindFirstHandler() {
11124   DCHECK(is_inline_cache_stub());
11125   DisallowHeapAllocation no_allocation;
11126   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11127              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11128   bool skip_next_handler = false;
11129   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11130     RelocInfo* info = it.rinfo();
11131     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11132       Object* obj = info->target_object();
11133       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
11134     } else {
11135       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11136       if (code->kind() == Code::HANDLER) {
11137         if (!skip_next_handler) return code;
11138         skip_next_handler = false;
11139       }
11140     }
11141   }
11142   return NULL;
11143 }
11144
11145
11146 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
11147   DCHECK(is_inline_cache_stub());
11148   DisallowHeapAllocation no_allocation;
11149   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11150              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11151   bool skip_next_handler = false;
11152   int i = 0;
11153   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11154     if (i == length) return true;
11155     RelocInfo* info = it.rinfo();
11156     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11157       Object* obj = info->target_object();
11158       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
11159     } else {
11160       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11161       // IC stubs with handlers never contain non-handler code objects before
11162       // handler targets.
11163       if (code->kind() != Code::HANDLER) break;
11164       if (!skip_next_handler) {
11165         code_list->Add(Handle<Code>(code));
11166         i++;
11167       }
11168       skip_next_handler = false;
11169     }
11170   }
11171   return i == length;
11172 }
11173
11174
11175 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
11176   DCHECK(is_inline_cache_stub());
11177   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11178              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11179   bool return_next = false;
11180   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11181     RelocInfo* info = it.rinfo();
11182     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11183       Object* object = info->target_object();
11184       if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
11185       if (object == map) return_next = true;
11186     } else if (return_next) {
11187       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11188       DCHECK(code->kind() == Code::HANDLER);
11189       return handle(code);
11190     }
11191   }
11192   return MaybeHandle<Code>();
11193 }
11194
11195
11196 Name* Code::FindFirstName() {
11197   DCHECK(is_inline_cache_stub());
11198   DisallowHeapAllocation no_allocation;
11199   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11200   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11201     RelocInfo* info = it.rinfo();
11202     Object* object = info->target_object();
11203     if (object->IsName()) return Name::cast(object);
11204   }
11205   return NULL;
11206 }
11207
11208
11209 void Code::ClearInlineCaches() {
11210   ClearInlineCaches(NULL);
11211 }
11212
11213
11214 void Code::ClearInlineCaches(Code::Kind kind) {
11215   ClearInlineCaches(&kind);
11216 }
11217
11218
11219 void Code::ClearInlineCaches(Code::Kind* kind) {
11220   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11221              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
11222              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
11223   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11224     RelocInfo* info = it.rinfo();
11225     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
11226     if (target->is_inline_cache_stub()) {
11227       if (kind == NULL || *kind == target->kind()) {
11228         IC::Clear(this->GetIsolate(), info->pc(),
11229                   info->host()->constant_pool());
11230       }
11231     }
11232   }
11233 }
11234
11235
11236 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
11237   feedback_vector()->ClearSlots(this);
11238   feedback_vector()->ClearICSlots(this);
11239 }
11240
11241
11242 void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
11243   feedback_vector()->ClearSlots(this);
11244   feedback_vector()->ClearICSlotsAtGCTime(this);
11245 }
11246
11247
11248 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
11249   DisallowHeapAllocation no_gc;
11250   DCHECK(kind() == FUNCTION);
11251   BackEdgeTable back_edges(this, &no_gc);
11252   for (uint32_t i = 0; i < back_edges.length(); i++) {
11253     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
11254   }
11255   return BailoutId::None();
11256 }
11257
11258
11259 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
11260   DisallowHeapAllocation no_gc;
11261   DCHECK(kind() == FUNCTION);
11262   BackEdgeTable back_edges(this, &no_gc);
11263   for (uint32_t i = 0; i < back_edges.length(); i++) {
11264     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
11265   }
11266   UNREACHABLE();  // We expect to find the back edge.
11267   return 0;
11268 }
11269
11270
11271 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
11272   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
11273 }
11274
11275
11276 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
11277   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
11278       NO_MARKING_PARITY);
11279 }
11280
11281
11282 static Code::Age EffectiveAge(Code::Age age) {
11283   if (age == Code::kNotExecutedCodeAge) {
11284     // Treat that's never been executed as old immediately.
11285     age = Code::kIsOldCodeAge;
11286   } else if (age == Code::kExecutedOnceCodeAge) {
11287     // Pre-age code that has only been executed once.
11288     age = Code::kPreAgedCodeAge;
11289   }
11290   return age;
11291 }
11292
11293
11294 void Code::MakeYoung(Isolate* isolate) {
11295   byte* sequence = FindCodeAgeSequence();
11296   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
11297 }
11298
11299
11300 void Code::MakeOlder(MarkingParity current_parity) {
11301   byte* sequence = FindCodeAgeSequence();
11302   if (sequence != NULL) {
11303     Age age;
11304     MarkingParity code_parity;
11305     Isolate* isolate = GetIsolate();
11306     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11307     age = EffectiveAge(age);
11308     if (age != kLastCodeAge && code_parity != current_parity) {
11309       PatchPlatformCodeAge(isolate,
11310                            sequence,
11311                            static_cast<Age>(age + 1),
11312                            current_parity);
11313     }
11314   }
11315 }
11316
11317
11318 bool Code::IsOld() {
11319   return GetAge() >= kIsOldCodeAge;
11320 }
11321
11322
11323 byte* Code::FindCodeAgeSequence() {
11324   return FLAG_age_code &&
11325       prologue_offset() != Code::kPrologueOffsetNotSet &&
11326       (kind() == OPTIMIZED_FUNCTION ||
11327        (kind() == FUNCTION && !has_debug_break_slots()))
11328       ? instruction_start() + prologue_offset()
11329       : NULL;
11330 }
11331
11332
11333 Code::Age Code::GetAge() {
11334   return EffectiveAge(GetRawAge());
11335 }
11336
11337
11338 Code::Age Code::GetRawAge() {
11339   byte* sequence = FindCodeAgeSequence();
11340   if (sequence == NULL) {
11341     return kNoAgeCodeAge;
11342   }
11343   Age age;
11344   MarkingParity parity;
11345   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11346   return age;
11347 }
11348
11349
11350 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11351                                MarkingParity* parity) {
11352   Isolate* isolate = code->GetIsolate();
11353   Builtins* builtins = isolate->builtins();
11354   Code* stub = NULL;
11355 #define HANDLE_CODE_AGE(AGE)                                            \
11356   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11357   if (code == stub) {                                                   \
11358     *age = k##AGE##CodeAge;                                             \
11359     *parity = EVEN_MARKING_PARITY;                                      \
11360     return;                                                             \
11361   }                                                                     \
11362   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11363   if (code == stub) {                                                   \
11364     *age = k##AGE##CodeAge;                                             \
11365     *parity = ODD_MARKING_PARITY;                                       \
11366     return;                                                             \
11367   }
11368   CODE_AGE_LIST(HANDLE_CODE_AGE)
11369 #undef HANDLE_CODE_AGE
11370   stub = *builtins->MarkCodeAsExecutedOnce();
11371   if (code == stub) {
11372     *age = kNotExecutedCodeAge;
11373     *parity = NO_MARKING_PARITY;
11374     return;
11375   }
11376   stub = *builtins->MarkCodeAsExecutedTwice();
11377   if (code == stub) {
11378     *age = kExecutedOnceCodeAge;
11379     *parity = NO_MARKING_PARITY;
11380     return;
11381   }
11382   UNREACHABLE();
11383 }
11384
11385
11386 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11387   Builtins* builtins = isolate->builtins();
11388   switch (age) {
11389 #define HANDLE_CODE_AGE(AGE)                                            \
11390     case k##AGE##CodeAge: {                                             \
11391       Code* stub = parity == EVEN_MARKING_PARITY                        \
11392           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11393           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11394       return stub;                                                      \
11395     }
11396     CODE_AGE_LIST(HANDLE_CODE_AGE)
11397 #undef HANDLE_CODE_AGE
11398     case kNotExecutedCodeAge: {
11399       DCHECK(parity == NO_MARKING_PARITY);
11400       return *builtins->MarkCodeAsExecutedOnce();
11401     }
11402     case kExecutedOnceCodeAge: {
11403       DCHECK(parity == NO_MARKING_PARITY);
11404       return *builtins->MarkCodeAsExecutedTwice();
11405     }
11406     default:
11407       UNREACHABLE();
11408       break;
11409   }
11410   return NULL;
11411 }
11412
11413
11414 void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
11415   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, bailout_id);
11416   if (info.deopt_reason != Deoptimizer::kNoReason || info.raw_position != 0) {
11417     PrintF(out, "            ;;; deoptimize at %d: %s\n", info.raw_position,
11418            Deoptimizer::GetDeoptReason(info.deopt_reason));
11419   }
11420 }
11421
11422
11423 bool Code::CanDeoptAt(Address pc) {
11424   DeoptimizationInputData* deopt_data =
11425       DeoptimizationInputData::cast(deoptimization_data());
11426   Address code_start_address = instruction_start();
11427   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11428     if (deopt_data->Pc(i)->value() == -1) continue;
11429     Address address = code_start_address + deopt_data->Pc(i)->value();
11430     if (address == pc) return true;
11431   }
11432   return false;
11433 }
11434
11435
11436 // Identify kind of code.
11437 const char* Code::Kind2String(Kind kind) {
11438   switch (kind) {
11439 #define CASE(name) case name: return #name;
11440     CODE_KIND_LIST(CASE)
11441 #undef CASE
11442     case NUMBER_OF_KINDS: break;
11443   }
11444   UNREACHABLE();
11445   return NULL;
11446 }
11447
11448
11449 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
11450   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
11451   WeakCell* raw_cell = code->CachedWeakCell();
11452   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
11453   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
11454   DeoptimizationInputData::cast(code->deoptimization_data())
11455       ->SetWeakCellCache(*cell);
11456   return cell;
11457 }
11458
11459
11460 WeakCell* Code::CachedWeakCell() {
11461   DCHECK(kind() == OPTIMIZED_FUNCTION);
11462   Object* weak_cell_cache =
11463       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
11464   if (weak_cell_cache->IsWeakCell()) {
11465     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
11466     return WeakCell::cast(weak_cell_cache);
11467   }
11468   return NULL;
11469 }
11470
11471
11472 #ifdef ENABLE_DISASSEMBLER
11473
11474 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11475     std::ostream& os) {  // NOLINT
11476   disasm::NameConverter converter;
11477   int deopt_count = DeoptCount();
11478   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11479   if (0 != deopt_count) {
11480     os << " index  ast id    argc     pc";
11481     if (FLAG_print_code_verbose) os << "  commands";
11482     os << "\n";
11483   }
11484   for (int i = 0; i < deopt_count; i++) {
11485     // TODO(svenpanne) Add some basic formatting to our streams.
11486     Vector<char> buf1 = Vector<char>::New(128);
11487     SNPrintF(buf1, "%6d  %6d  %6d %6d", i, AstId(i).ToInt(),
11488              ArgumentsStackHeight(i)->value(), Pc(i)->value());
11489     os << buf1.start();
11490
11491     if (!FLAG_print_code_verbose) {
11492       os << "\n";
11493       continue;
11494     }
11495     // Print details of the frame translation.
11496     int translation_index = TranslationIndex(i)->value();
11497     TranslationIterator iterator(TranslationByteArray(), translation_index);
11498     Translation::Opcode opcode =
11499         static_cast<Translation::Opcode>(iterator.Next());
11500     DCHECK(Translation::BEGIN == opcode);
11501     int frame_count = iterator.Next();
11502     int jsframe_count = iterator.Next();
11503     os << "  " << Translation::StringFor(opcode)
11504        << " {frame count=" << frame_count
11505        << ", js frame count=" << jsframe_count << "}\n";
11506
11507     while (iterator.HasNext() &&
11508            Translation::BEGIN !=
11509            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11510       Vector<char> buf2 = Vector<char>::New(128);
11511       SNPrintF(buf2, "%27s    %s ", "", Translation::StringFor(opcode));
11512       os << buf2.start();
11513
11514       switch (opcode) {
11515         case Translation::BEGIN:
11516           UNREACHABLE();
11517           break;
11518
11519         case Translation::JS_FRAME: {
11520           int ast_id = iterator.Next();
11521           int function_id = iterator.Next();
11522           unsigned height = iterator.Next();
11523           os << "{ast_id=" << ast_id << ", function=";
11524           if (function_id != Translation::kSelfLiteralId) {
11525             Object* function = LiteralArray()->get(function_id);
11526             os << Brief(JSFunction::cast(function)->shared()->DebugName());
11527           } else {
11528             os << "<self>";
11529           }
11530           os << ", height=" << height << "}";
11531           break;
11532         }
11533
11534         case Translation::COMPILED_STUB_FRAME: {
11535           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11536           os << "{kind=" << stub_kind << "}";
11537           break;
11538         }
11539
11540         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11541         case Translation::CONSTRUCT_STUB_FRAME: {
11542           int function_id = iterator.Next();
11543           JSFunction* function =
11544               JSFunction::cast(LiteralArray()->get(function_id));
11545           unsigned height = iterator.Next();
11546           os << "{function=" << Brief(function->shared()->DebugName())
11547              << ", height=" << height << "}";
11548           break;
11549         }
11550
11551         case Translation::GETTER_STUB_FRAME:
11552         case Translation::SETTER_STUB_FRAME: {
11553           int function_id = iterator.Next();
11554           JSFunction* function =
11555               JSFunction::cast(LiteralArray()->get(function_id));
11556           os << "{function=" << Brief(function->shared()->DebugName()) << "}";
11557           break;
11558         }
11559
11560         case Translation::REGISTER: {
11561           int reg_code = iterator.Next();
11562           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11563           break;
11564         }
11565
11566         case Translation::INT32_REGISTER: {
11567           int reg_code = iterator.Next();
11568           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11569           break;
11570         }
11571
11572         case Translation::UINT32_REGISTER: {
11573           int reg_code = iterator.Next();
11574           os << "{input=" << converter.NameOfCPURegister(reg_code)
11575              << " (unsigned)}";
11576           break;
11577         }
11578
11579         case Translation::DOUBLE_REGISTER: {
11580           int reg_code = iterator.Next();
11581           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11582              << "}";
11583           break;
11584         }
11585
11586         case Translation::STACK_SLOT: {
11587           int input_slot_index = iterator.Next();
11588           os << "{input=" << input_slot_index << "}";
11589           break;
11590         }
11591
11592         case Translation::INT32_STACK_SLOT: {
11593           int input_slot_index = iterator.Next();
11594           os << "{input=" << input_slot_index << "}";
11595           break;
11596         }
11597
11598         case Translation::UINT32_STACK_SLOT: {
11599           int input_slot_index = iterator.Next();
11600           os << "{input=" << input_slot_index << " (unsigned)}";
11601           break;
11602         }
11603
11604         case Translation::DOUBLE_STACK_SLOT: {
11605           int input_slot_index = iterator.Next();
11606           os << "{input=" << input_slot_index << "}";
11607           break;
11608         }
11609
11610         case Translation::LITERAL: {
11611           unsigned literal_index = iterator.Next();
11612           os << "{literal_id=" << literal_index << "}";
11613           break;
11614         }
11615
11616         case Translation::DUPLICATED_OBJECT: {
11617           int object_index = iterator.Next();
11618           os << "{object_index=" << object_index << "}";
11619           break;
11620         }
11621
11622         case Translation::ARGUMENTS_OBJECT:
11623         case Translation::CAPTURED_OBJECT: {
11624           int args_length = iterator.Next();
11625           os << "{length=" << args_length << "}";
11626           break;
11627         }
11628       }
11629       os << "\n";
11630     }
11631   }
11632 }
11633
11634
11635 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11636     std::ostream& os) {  // NOLINT
11637   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11638      << ")\n";
11639   if (this->DeoptPoints() == 0) return;
11640
11641   os << "ast id        pc  state\n";
11642   for (int i = 0; i < this->DeoptPoints(); i++) {
11643     int pc_and_state = this->PcAndState(i)->value();
11644     // TODO(svenpanne) Add some basic formatting to our streams.
11645     Vector<char> buf = Vector<char>::New(100);
11646     SNPrintF(buf, "%6d  %8d  %s\n", this->AstId(i).ToInt(),
11647              FullCodeGenerator::PcField::decode(pc_and_state),
11648              FullCodeGenerator::State2String(
11649                  FullCodeGenerator::StateField::decode(pc_and_state)));
11650     os << buf.start();
11651   }
11652 }
11653
11654
11655 const char* Code::ICState2String(InlineCacheState state) {
11656   switch (state) {
11657     case UNINITIALIZED: return "UNINITIALIZED";
11658     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11659     case MONOMORPHIC: return "MONOMORPHIC";
11660     case PROTOTYPE_FAILURE:
11661       return "PROTOTYPE_FAILURE";
11662     case POLYMORPHIC: return "POLYMORPHIC";
11663     case MEGAMORPHIC: return "MEGAMORPHIC";
11664     case GENERIC: return "GENERIC";
11665     case DEBUG_STUB: return "DEBUG_STUB";
11666     case DEFAULT:
11667       return "DEFAULT";
11668   }
11669   UNREACHABLE();
11670   return NULL;
11671 }
11672
11673
11674 const char* Code::StubType2String(StubType type) {
11675   switch (type) {
11676     case NORMAL: return "NORMAL";
11677     case FAST: return "FAST";
11678   }
11679   UNREACHABLE();  // keep the compiler happy
11680   return NULL;
11681 }
11682
11683
11684 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
11685                              Kind kind, ExtraICState extra) {
11686   os << "extra_ic_state = ";
11687   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
11688       is_strict(static_cast<LanguageMode>(extra))) {
11689     os << "STRICT\n";
11690   } else {
11691     os << extra << "\n";
11692   }
11693 }
11694
11695
11696 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
11697   os << "kind = " << Kind2String(kind()) << "\n";
11698   if (IsCodeStubOrIC()) {
11699     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11700     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11701   }
11702   if (is_inline_cache_stub()) {
11703     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11704     PrintExtraICState(os, kind(), extra_ic_state());
11705     if (ic_state() == MONOMORPHIC) {
11706       os << "type = " << StubType2String(type()) << "\n";
11707     }
11708     if (is_compare_ic_stub()) {
11709       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11710       CompareICStub stub(stub_key(), GetIsolate());
11711       os << "compare_state = " << CompareICState::GetStateName(stub.left())
11712          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
11713          << CompareICState::GetStateName(stub.state()) << "\n";
11714       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
11715     }
11716   }
11717   if ((name != NULL) && (name[0] != '\0')) {
11718     os << "name = " << name << "\n";
11719   }
11720   if (kind() == OPTIMIZED_FUNCTION) {
11721     os << "stack_slots = " << stack_slots() << "\n";
11722   }
11723
11724   os << "Instructions (size = " << instruction_size() << ")\n";
11725   {
11726     Isolate* isolate = GetIsolate();
11727     int decode_size = is_crankshafted()
11728                           ? static_cast<int>(safepoint_table_offset())
11729                           : instruction_size();
11730     // If there might be a back edge table, stop before reaching it.
11731     if (kind() == Code::FUNCTION) {
11732       decode_size =
11733           Min(decode_size, static_cast<int>(back_edge_table_offset()));
11734     }
11735     byte* begin = instruction_start();
11736     byte* end = begin + decode_size;
11737     Disassembler::Decode(isolate, &os, begin, end, this);
11738   }
11739   os << "\n";
11740
11741   if (kind() == FUNCTION) {
11742     DeoptimizationOutputData* data =
11743         DeoptimizationOutputData::cast(this->deoptimization_data());
11744     data->DeoptimizationOutputDataPrint(os);
11745   } else if (kind() == OPTIMIZED_FUNCTION) {
11746     DeoptimizationInputData* data =
11747         DeoptimizationInputData::cast(this->deoptimization_data());
11748     data->DeoptimizationInputDataPrint(os);
11749   }
11750   os << "\n";
11751
11752   if (is_crankshafted()) {
11753     SafepointTable table(this);
11754     os << "Safepoints (size = " << table.size() << ")\n";
11755     for (unsigned i = 0; i < table.length(); i++) {
11756       unsigned pc_offset = table.GetPcOffset(i);
11757       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
11758       // TODO(svenpanne) Add some basic formatting to our streams.
11759       Vector<char> buf1 = Vector<char>::New(30);
11760       SNPrintF(buf1, "%4d", pc_offset);
11761       os << buf1.start() << "  ";
11762       table.PrintEntry(i, os);
11763       os << " (sp -> fp)  ";
11764       SafepointEntry entry = table.GetEntry(i);
11765       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11766         Vector<char> buf2 = Vector<char>::New(30);
11767         SNPrintF(buf2, "%6d", entry.deoptimization_index());
11768         os << buf2.start();
11769       } else {
11770         os << "<none>";
11771       }
11772       if (entry.argument_count() > 0) {
11773         os << " argc: " << entry.argument_count();
11774       }
11775       os << "\n";
11776     }
11777     os << "\n";
11778   } else if (kind() == FUNCTION) {
11779     unsigned offset = back_edge_table_offset();
11780     // If there is no back edge table, the "table start" will be at or after
11781     // (due to alignment) the end of the instruction stream.
11782     if (static_cast<int>(offset) < instruction_size()) {
11783       DisallowHeapAllocation no_gc;
11784       BackEdgeTable back_edges(this, &no_gc);
11785
11786       os << "Back edges (size = " << back_edges.length() << ")\n";
11787       os << "ast_id  pc_offset  loop_depth\n";
11788
11789       for (uint32_t i = 0; i < back_edges.length(); i++) {
11790         Vector<char> buf = Vector<char>::New(100);
11791         SNPrintF(buf, "%6d  %9u  %10u\n", back_edges.ast_id(i).ToInt(),
11792                  back_edges.pc_offset(i), back_edges.loop_depth(i));
11793         os << buf.start();
11794       }
11795
11796       os << "\n";
11797     }
11798 #ifdef OBJECT_PRINT
11799     if (!type_feedback_info()->IsUndefined()) {
11800       OFStream os(stdout);
11801       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11802       os << "\n";
11803     }
11804 #endif
11805   }
11806
11807   os << "RelocInfo (size = " << relocation_size() << ")\n";
11808   for (RelocIterator it(this); !it.done(); it.next()) {
11809     it.rinfo()->Print(GetIsolate(), os);
11810   }
11811   os << "\n";
11812
11813 #ifdef OBJECT_PRINT
11814   if (FLAG_enable_ool_constant_pool) {
11815     ConstantPoolArray* pool = constant_pool();
11816     if (pool->length()) {
11817       os << "Constant Pool\n";
11818       pool->Print(os);
11819       os << "\n";
11820     }
11821   }
11822 #endif
11823 }
11824 #endif  // ENABLE_DISASSEMBLER
11825
11826
11827 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11828     Handle<JSObject> object,
11829     int capacity,
11830     int length,
11831     SetFastElementsCapacitySmiMode smi_mode) {
11832   // We should never end in here with a pixel or external array.
11833   DCHECK(!object->HasExternalArrayElements());
11834
11835   // Allocate a new fast elements backing store.
11836   Handle<FixedArray> new_elements =
11837       object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
11838
11839   ElementsKind elements_kind = object->GetElementsKind();
11840   ElementsKind new_elements_kind;
11841   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11842   // or if it's allowed and the old elements array contained only SMIs.
11843   bool has_fast_smi_elements =
11844       (smi_mode == kForceSmiElements) ||
11845       ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11846   if (has_fast_smi_elements) {
11847     if (IsHoleyElementsKind(elements_kind)) {
11848       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11849     } else {
11850       new_elements_kind = FAST_SMI_ELEMENTS;
11851     }
11852   } else {
11853     if (IsHoleyElementsKind(elements_kind)) {
11854       new_elements_kind = FAST_HOLEY_ELEMENTS;
11855     } else {
11856       new_elements_kind = FAST_ELEMENTS;
11857     }
11858   }
11859   Handle<FixedArrayBase> old_elements(object->elements());
11860   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11861   accessor->CopyElements(object, new_elements, elements_kind);
11862
11863   if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11864     Handle<Map> new_map = (new_elements_kind != elements_kind)
11865         ? GetElementsTransitionMap(object, new_elements_kind)
11866         : handle(object->map());
11867     JSObject::ValidateElements(object);
11868     JSObject::SetMapAndElements(object, new_map, new_elements);
11869
11870     // Transition through the allocation site as well if present.
11871     JSObject::UpdateAllocationSite(object, new_elements_kind);
11872   } else {
11873     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11874     parameter_map->set(1, *new_elements);
11875   }
11876
11877   if (FLAG_trace_elements_transitions) {
11878     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11879                             object->GetElementsKind(), new_elements);
11880   }
11881
11882   if (object->IsJSArray()) {
11883     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11884   }
11885   return new_elements;
11886 }
11887
11888
11889 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11890                                                       int capacity,
11891                                                       int length) {
11892   // We should never end in here with a pixel or external array.
11893   DCHECK(!object->HasExternalArrayElements());
11894
11895   Handle<FixedArrayBase> elems =
11896       object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11897
11898   ElementsKind elements_kind = object->GetElementsKind();
11899   CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11900   ElementsKind new_elements_kind = elements_kind;
11901   if (IsHoleyElementsKind(elements_kind)) {
11902     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11903   } else {
11904     new_elements_kind = FAST_DOUBLE_ELEMENTS;
11905   }
11906
11907   Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11908
11909   Handle<FixedArrayBase> old_elements(object->elements());
11910   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11911   accessor->CopyElements(object, elems, elements_kind);
11912
11913   JSObject::ValidateElements(object);
11914   JSObject::SetMapAndElements(object, new_map, elems);
11915
11916   if (FLAG_trace_elements_transitions) {
11917     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11918                             object->GetElementsKind(), elems);
11919   }
11920
11921   if (object->IsJSArray()) {
11922     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11923   }
11924 }
11925
11926
11927 // static
11928 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11929   DCHECK(capacity >= 0);
11930   array->GetIsolate()->factory()->NewJSArrayStorage(
11931       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11932 }
11933
11934
11935 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11936   ElementsAccessor* accessor = array->GetElementsAccessor();
11937   accessor->SetCapacityAndLength(array, required_size, required_size);
11938 }
11939
11940
11941 // Returns false if the passed-in index is marked non-configurable,
11942 // which will cause the ES5 truncation operation to halt, and thus
11943 // no further old values need be collected.
11944 static bool GetOldValue(Isolate* isolate,
11945                         Handle<JSObject> object,
11946                         uint32_t index,
11947                         List<Handle<Object> >* old_values,
11948                         List<uint32_t>* indices) {
11949   Maybe<PropertyAttributes> maybe =
11950       JSReceiver::GetOwnElementAttribute(object, index);
11951   DCHECK(maybe.has_value);
11952   DCHECK(maybe.value != ABSENT);
11953   if (maybe.value == DONT_DELETE) return false;
11954   Handle<Object> value;
11955   if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11956     value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11957   } else {
11958     value = Object::GetElement(isolate, object, index).ToHandleChecked();
11959   }
11960   old_values->Add(value);
11961   indices->Add(index);
11962   return true;
11963 }
11964
11965 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
11966     Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
11967     uint32_t add_count) {
11968   Isolate* isolate = object->GetIsolate();
11969   HandleScope scope(isolate);
11970   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11971   Handle<Object> add_count_object =
11972       isolate->factory()->NewNumberFromUint(add_count);
11973
11974   Handle<Object> args[] =
11975       { object, index_object, deleted, add_count_object };
11976
11977   return Execution::Call(
11978       isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
11979       isolate->factory()->undefined_value(), arraysize(args), args);
11980 }
11981
11982
11983 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
11984     Handle<JSArray> object) {
11985   Isolate* isolate = object->GetIsolate();
11986   HandleScope scope(isolate);
11987   Handle<Object> args[] = { object };
11988
11989   return Execution::Call(
11990       isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11991       isolate->factory()->undefined_value(), arraysize(args), args);
11992 }
11993
11994
11995 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
11996     Handle<JSArray> object) {
11997   Isolate* isolate = object->GetIsolate();
11998   HandleScope scope(isolate);
11999   Handle<Object> args[] = { object };
12000
12001   return Execution::Call(
12002       isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
12003       isolate->factory()->undefined_value(), arraysize(args), args);
12004 }
12005
12006
12007 MaybeHandle<Object> JSArray::SetElementsLength(
12008     Handle<JSArray> array,
12009     Handle<Object> new_length_handle) {
12010   if (array->HasFastElements()) {
12011     // If the new array won't fit in a some non-trivial fraction of the max old
12012     // space size, then force it to go dictionary mode.
12013     int max_fast_array_size = static_cast<int>(
12014         (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
12015     if (new_length_handle->IsNumber() &&
12016         NumberToInt32(*new_length_handle) >= max_fast_array_size) {
12017       NormalizeElements(array);
12018     }
12019   }
12020
12021   // We should never end in here with a pixel or external array.
12022   DCHECK(array->AllowsSetElementsLength());
12023   if (!array->map()->is_observed()) {
12024     return array->GetElementsAccessor()->SetLength(array, new_length_handle);
12025   }
12026
12027   Isolate* isolate = array->GetIsolate();
12028   List<uint32_t> indices;
12029   List<Handle<Object> > old_values;
12030   Handle<Object> old_length_handle(array->length(), isolate);
12031   uint32_t old_length = 0;
12032   CHECK(old_length_handle->ToArrayIndex(&old_length));
12033   uint32_t new_length = 0;
12034   CHECK(new_length_handle->ToArrayIndex(&new_length));
12035
12036   static const PropertyAttributes kNoAttrFilter = NONE;
12037   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
12038   if (num_elements > 0) {
12039     if (old_length == static_cast<uint32_t>(num_elements)) {
12040       // Simple case for arrays without holes.
12041       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
12042         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
12043       }
12044     } else {
12045       // For sparse arrays, only iterate over existing elements.
12046       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
12047       // the to-be-removed indices twice.
12048       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
12049       array->GetOwnElementKeys(*keys, kNoAttrFilter);
12050       while (num_elements-- > 0) {
12051         uint32_t index = NumberToUint32(keys->get(num_elements));
12052         if (index < new_length) break;
12053         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
12054       }
12055     }
12056   }
12057
12058   Handle<Object> hresult;
12059   ASSIGN_RETURN_ON_EXCEPTION(
12060       isolate, hresult,
12061       array->GetElementsAccessor()->SetLength(array, new_length_handle),
12062       Object);
12063
12064   CHECK(array->length()->ToArrayIndex(&new_length));
12065   if (old_length == new_length) return hresult;
12066
12067   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12068
12069   for (int i = 0; i < indices.length(); ++i) {
12070     // For deletions where the property was an accessor, old_values[i]
12071     // will be the hole, which instructs EnqueueChangeRecord to elide
12072     // the "oldValue" property.
12073     RETURN_ON_EXCEPTION(
12074         isolate,
12075         JSObject::EnqueueChangeRecord(
12076             array, "delete", isolate->factory()->Uint32ToString(indices[i]),
12077             old_values[i]),
12078         Object);
12079   }
12080   RETURN_ON_EXCEPTION(isolate,
12081                       JSObject::EnqueueChangeRecord(
12082                           array, "update", isolate->factory()->length_string(),
12083                           old_length_handle),
12084                       Object);
12085
12086   RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
12087
12088   uint32_t index = Min(old_length, new_length);
12089   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
12090   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
12091   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12092   if (delete_count > 0) {
12093     for (int i = indices.length() - 1; i >= 0; i--) {
12094       // Skip deletions where the property was an accessor, leaving holes
12095       // in the array of old values.
12096       if (old_values[i]->IsTheHole()) continue;
12097       JSObject::SetOwnElement(deleted, indices[i] - index, old_values[i],
12098                               SLOPPY).Assert();
12099     }
12100
12101     RETURN_ON_EXCEPTION(
12102         isolate,
12103         SetProperty(deleted, isolate->factory()->length_string(),
12104                     isolate->factory()->NewNumberFromUint(delete_count),
12105                     STRICT),
12106         Object);
12107   }
12108
12109   RETURN_ON_EXCEPTION(
12110       isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
12111
12112   return hresult;
12113 }
12114
12115
12116 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
12117                                         Handle<Object> prototype) {
12118   DisallowHeapAllocation no_gc;
12119   FixedArray* cache = map->GetPrototypeTransitions();
12120   int number_of_transitions = map->NumberOfProtoTransitions();
12121   for (int i = 0; i < number_of_transitions; i++) {
12122     Map* map = Map::cast(cache->get(kProtoTransitionHeaderSize + i));
12123     if (map->prototype() == *prototype) return handle(map);
12124   }
12125   return Handle<Map>();
12126 }
12127
12128
12129 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
12130                                         Handle<Object> prototype,
12131                                         Handle<Map> target_map) {
12132   DCHECK(target_map->IsMap());
12133   DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
12134   // Don't cache prototype transition if this map is either shared, or a map of
12135   // a prototype.
12136   if (map->is_prototype_map()) return map;
12137   if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
12138
12139   const int header = kProtoTransitionHeaderSize;
12140
12141   Handle<FixedArray> cache(map->GetPrototypeTransitions());
12142   int capacity = cache->length() - header;
12143   int transitions = map->NumberOfProtoTransitions() + 1;
12144
12145   if (transitions > capacity) {
12146     // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
12147     int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2);
12148     if (new_capacity == capacity) return map;
12149
12150     cache = FixedArray::CopySize(cache, header + new_capacity);
12151
12152     SetPrototypeTransitions(map, cache);
12153   }
12154
12155   // Reload number of transitions as GC might shrink them.
12156   int last = map->NumberOfProtoTransitions();
12157   int entry = header + last;
12158
12159   cache->set(entry, *target_map);
12160   map->SetNumberOfProtoTransitions(last + 1);
12161
12162   return map;
12163 }
12164
12165
12166 void Map::ZapTransitions() {
12167   TransitionArray* transition_array = transitions();
12168   // TODO(mstarzinger): Temporarily use a slower version instead of the faster
12169   // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
12170   Object** data = transition_array->data_start();
12171   Object* the_hole = GetHeap()->the_hole_value();
12172   int length = transition_array->length();
12173   for (int i = 0; i < length; i++) {
12174     data[i] = the_hole;
12175   }
12176 }
12177
12178
12179 void Map::ZapPrototypeTransitions() {
12180   FixedArray* proto_transitions = GetPrototypeTransitions();
12181   MemsetPointer(proto_transitions->data_start(),
12182                 GetHeap()->the_hole_value(),
12183                 proto_transitions->length());
12184 }
12185
12186
12187 // static
12188 void Map::AddDependentCompilationInfo(Handle<Map> map,
12189                                       DependentCode::DependencyGroup group,
12190                                       CompilationInfo* info) {
12191   Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
12192       handle(map->dependent_code(), info->isolate()), group,
12193       info->object_wrapper());
12194   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
12195   info->dependencies(group)->Add(map, info->zone());
12196 }
12197
12198
12199 // static
12200 void Map::AddDependentCode(Handle<Map> map,
12201                            DependentCode::DependencyGroup group,
12202                            Handle<Code> code) {
12203   Handle<WeakCell> cell = Code::WeakCellFor(code);
12204   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
12205       Handle<DependentCode>(map->dependent_code()), group, cell);
12206   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
12207 }
12208
12209
12210 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
12211   Recompute(entries);
12212 }
12213
12214
12215 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
12216   start_indexes_[0] = 0;
12217   for (int g = 1; g <= kGroupCount; g++) {
12218     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
12219     start_indexes_[g] = start_indexes_[g - 1] + count;
12220   }
12221 }
12222
12223
12224 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
12225                                         DependencyGroup group) {
12226   AllowDeferredHandleDereference dependencies_are_safe;
12227   if (group == DependentCode::kPropertyCellChangedGroup) {
12228     return Handle<PropertyCell>::cast(object)->dependent_code();
12229   } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
12230       group == DependentCode::kAllocationSiteTransitionChangedGroup) {
12231     return Handle<AllocationSite>::cast(object)->dependent_code();
12232   }
12233   return Handle<Map>::cast(object)->dependent_code();
12234 }
12235
12236
12237 Handle<DependentCode> DependentCode::InsertCompilationInfo(
12238     Handle<DependentCode> entries, DependencyGroup group,
12239     Handle<Foreign> info) {
12240   return Insert(entries, group, info);
12241 }
12242
12243
12244 Handle<DependentCode> DependentCode::InsertWeakCode(
12245     Handle<DependentCode> entries, DependencyGroup group,
12246     Handle<WeakCell> code_cell) {
12247   return Insert(entries, group, code_cell);
12248 }
12249
12250
12251 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
12252                                             DependencyGroup group,
12253                                             Handle<Object> object) {
12254   GroupStartIndexes starts(*entries);
12255   int start = starts.at(group);
12256   int end = starts.at(group + 1);
12257   int number_of_entries = starts.number_of_entries();
12258   // Check for existing entry to avoid duplicates.
12259   for (int i = start; i < end; i++) {
12260     if (entries->object_at(i) == *object) return entries;
12261   }
12262   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
12263     entries = EnsureSpace(entries);
12264     // The number of codes can change after Compact and GC.
12265     starts.Recompute(*entries);
12266     start = starts.at(group);
12267     end = starts.at(group + 1);
12268   }
12269
12270   entries->ExtendGroup(group);
12271   entries->set_object_at(end, *object);
12272   entries->set_number_of_entries(group, end + 1 - start);
12273   return entries;
12274 }
12275
12276
12277 Handle<DependentCode> DependentCode::EnsureSpace(
12278     Handle<DependentCode> entries) {
12279   if (entries->length() == 0) {
12280     entries = Handle<DependentCode>::cast(
12281         FixedArray::CopySize(entries, kCodesStartIndex + 1, TENURED));
12282     for (int g = 0; g < kGroupCount; g++) {
12283       entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
12284     }
12285     return entries;
12286   }
12287   if (entries->Compact()) return entries;
12288   GroupStartIndexes starts(*entries);
12289   int capacity =
12290       kCodesStartIndex + DependentCode::Grow(starts.number_of_entries());
12291   return Handle<DependentCode>::cast(
12292       FixedArray::CopySize(entries, capacity, TENURED));
12293 }
12294
12295
12296 bool DependentCode::Compact() {
12297   GroupStartIndexes starts(this);
12298   int n = 0;
12299   for (int g = 0; g < kGroupCount; g++) {
12300     int start = starts.at(g);
12301     int end = starts.at(g + 1);
12302     int count = 0;
12303     DCHECK(start >= n);
12304     for (int i = start; i < end; i++) {
12305       Object* obj = object_at(i);
12306       if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
12307         if (i != n + count) {
12308           copy(i, n + count);
12309         }
12310         count++;
12311       }
12312     }
12313     if (count != end - start) {
12314       set_number_of_entries(static_cast<DependencyGroup>(g), count);
12315     }
12316     n += count;
12317   }
12318   return n < starts.number_of_entries();
12319 }
12320
12321
12322 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
12323                                          WeakCell* code_cell) {
12324   DisallowHeapAllocation no_gc;
12325   GroupStartIndexes starts(this);
12326   int start = starts.at(group);
12327   int end = starts.at(group + 1);
12328   for (int i = start; i < end; i++) {
12329     if (object_at(i) == info) {
12330       set_object_at(i, code_cell);
12331       break;
12332     }
12333   }
12334
12335 #ifdef DEBUG
12336   for (int i = start; i < end; i++) {
12337     DCHECK(object_at(i) != info);
12338   }
12339 #endif
12340 }
12341
12342
12343 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
12344                                           Foreign* info) {
12345   DisallowHeapAllocation no_allocation;
12346   GroupStartIndexes starts(this);
12347   int start = starts.at(group);
12348   int end = starts.at(group + 1);
12349   // Find compilation info wrapper.
12350   int info_pos = -1;
12351   for (int i = start; i < end; i++) {
12352     if (object_at(i) == info) {
12353       info_pos = i;
12354       break;
12355     }
12356   }
12357   if (info_pos == -1) return;  // Not found.
12358   int gap = info_pos;
12359   // Use the last of each group to fill the gap in the previous group.
12360   for (int i = group; i < kGroupCount; i++) {
12361     int last_of_group = starts.at(i + 1) - 1;
12362     DCHECK(last_of_group >= gap);
12363     if (last_of_group == gap) continue;
12364     copy(last_of_group, gap);
12365     gap = last_of_group;
12366   }
12367   DCHECK(gap == starts.number_of_entries() - 1);
12368   clear_at(gap);  // Clear last gap.
12369   set_number_of_entries(group, end - start - 1);
12370
12371 #ifdef DEBUG
12372   for (int i = start; i < end - 1; i++) {
12373     DCHECK(object_at(i) != info);
12374   }
12375 #endif
12376 }
12377
12378
12379 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
12380   GroupStartIndexes starts(this);
12381   int start = starts.at(group);
12382   int end = starts.at(group + 1);
12383   for (int i = start; i < end; i++) {
12384     if (object_at(i) == code_cell) return true;
12385   }
12386   return false;
12387 }
12388
12389
12390 bool DependentCode::MarkCodeForDeoptimization(
12391     Isolate* isolate,
12392     DependentCode::DependencyGroup group) {
12393   DisallowHeapAllocation no_allocation_scope;
12394   DependentCode::GroupStartIndexes starts(this);
12395   int start = starts.at(group);
12396   int end = starts.at(group + 1);
12397   int code_entries = starts.number_of_entries();
12398   if (start == end) return false;
12399
12400   // Mark all the code that needs to be deoptimized.
12401   bool marked = false;
12402   bool invalidate_embedded_objects = group == kWeakCodeGroup;
12403   for (int i = start; i < end; i++) {
12404     Object* obj = object_at(i);
12405     if (obj->IsWeakCell()) {
12406       WeakCell* cell = WeakCell::cast(obj);
12407       if (cell->cleared()) continue;
12408       Code* code = Code::cast(cell->value());
12409       if (!code->marked_for_deoptimization()) {
12410         SetMarkedForDeoptimization(code, group);
12411         if (invalidate_embedded_objects) {
12412           code->InvalidateEmbeddedObjects();
12413         }
12414         marked = true;
12415       }
12416     } else {
12417       DCHECK(obj->IsForeign());
12418       CompilationInfo* info = reinterpret_cast<CompilationInfo*>(
12419           Foreign::cast(obj)->foreign_address());
12420       info->AbortDueToDependencyChange();
12421     }
12422   }
12423   // Compact the array by moving all subsequent groups to fill in the new holes.
12424   for (int src = end, dst = start; src < code_entries; src++, dst++) {
12425     copy(src, dst);
12426   }
12427   // Now the holes are at the end of the array, zap them for heap-verifier.
12428   int removed = end - start;
12429   for (int i = code_entries - removed; i < code_entries; i++) {
12430     clear_at(i);
12431   }
12432   set_number_of_entries(group, 0);
12433   return marked;
12434 }
12435
12436
12437 void DependentCode::DeoptimizeDependentCodeGroup(
12438     Isolate* isolate,
12439     DependentCode::DependencyGroup group) {
12440   DCHECK(AllowCodeDependencyChange::IsAllowed());
12441   DisallowHeapAllocation no_allocation_scope;
12442   bool marked = MarkCodeForDeoptimization(isolate, group);
12443   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
12444 }
12445
12446
12447 void DependentCode::SetMarkedForDeoptimization(Code* code,
12448                                                DependencyGroup group) {
12449   code->set_marked_for_deoptimization(true);
12450   if (FLAG_trace_deopt &&
12451       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
12452     DeoptimizationInputData* deopt_data =
12453         DeoptimizationInputData::cast(code->deoptimization_data());
12454     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
12455     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
12456                          " (opt #%d) for deoptimization, reason: %s]\n",
12457            reinterpret_cast<intptr_t>(code),
12458            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
12459   }
12460 }
12461
12462
12463 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
12464   switch (group) {
12465     case kWeakCodeGroup:
12466       return "weak-code";
12467     case kTransitionGroup:
12468       return "transition";
12469     case kPrototypeCheckGroup:
12470       return "prototype-check";
12471     case kElementsCantBeAddedGroup:
12472       return "elements-cant-be-added";
12473     case kPropertyCellChangedGroup:
12474       return "property-cell-changed";
12475     case kFieldTypeGroup:
12476       return "field-type";
12477     case kInitialMapChangedGroup:
12478       return "initial-map-changed";
12479     case kAllocationSiteTenuringChangedGroup:
12480       return "allocation-site-tenuring-changed";
12481     case kAllocationSiteTransitionChangedGroup:
12482       return "allocation-site-transition-changed";
12483   }
12484   UNREACHABLE();
12485   return "?";
12486 }
12487
12488
12489 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12490                                        Handle<Object> prototype,
12491                                        PrototypeOptimizationMode mode) {
12492   Handle<Map> new_map = GetPrototypeTransition(map, prototype);
12493   if (new_map.is_null()) {
12494     new_map = Copy(map, "TransitionToPrototype");
12495     PutPrototypeTransition(map, prototype, new_map);
12496     new_map->SetPrototype(prototype, mode);
12497   }
12498   return new_map;
12499 }
12500
12501
12502 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12503                                            Handle<Object> value,
12504                                            bool from_javascript) {
12505 #ifdef DEBUG
12506   int size = object->Size();
12507 #endif
12508
12509   Isolate* isolate = object->GetIsolate();
12510   Heap* heap = isolate->heap();
12511   // Silently ignore the change if value is not a JSObject or null.
12512   // SpiderMonkey behaves this way.
12513   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12514
12515   // From 8.6.2 Object Internal Methods
12516   // ...
12517   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12518   // [[Prototype]] internal properties of the object may not be modified.
12519   // ...
12520   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12521   // or [[Extensible]] must not violate the invariants defined in the preceding
12522   // paragraph.
12523   if (!object->map()->is_extensible()) {
12524     Handle<Object> args[] = { object };
12525     THROW_NEW_ERROR(isolate, NewTypeError("non_extensible_proto",
12526                                           HandleVector(args, arraysize(args))),
12527                     Object);
12528   }
12529
12530   // Before we can set the prototype we need to be sure
12531   // prototype cycles are prevented.
12532   // It is sufficient to validate that the receiver is not in the new prototype
12533   // chain.
12534   for (PrototypeIterator iter(isolate, *value,
12535                               PrototypeIterator::START_AT_RECEIVER);
12536        !iter.IsAtEnd(); iter.Advance()) {
12537     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12538       // Cycle detected.
12539       THROW_NEW_ERROR(isolate,
12540                       NewError("cyclic_proto", HandleVector<Object>(NULL, 0)),
12541                       Object);
12542     }
12543   }
12544
12545   bool dictionary_elements_in_chain =
12546       object->map()->DictionaryElementsInPrototypeChainOnly();
12547   Handle<JSObject> real_receiver = object;
12548
12549   if (from_javascript) {
12550     // Find the first object in the chain whose prototype object is not
12551     // hidden and set the new prototype on that object.
12552     PrototypeIterator iter(isolate, real_receiver);
12553     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12554       real_receiver =
12555           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12556       iter.Advance();
12557       if (!real_receiver->map()->is_extensible()) {
12558         Handle<Object> args[] = {object};
12559         THROW_NEW_ERROR(isolate,
12560                         NewTypeError("non_extensible_proto",
12561                                      HandleVector(args, arraysize(args))),
12562                         Object);
12563       }
12564     }
12565   }
12566
12567   // Set the new prototype of the object.
12568   Handle<Map> map(real_receiver->map());
12569
12570   // Nothing to do if prototype is already set.
12571   if (map->prototype() == *value) return value;
12572
12573   PrototypeOptimizationMode mode =
12574       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12575   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12576   DCHECK(new_map->prototype() == *value);
12577   JSObject::MigrateToMap(real_receiver, new_map);
12578
12579   if (from_javascript && !dictionary_elements_in_chain &&
12580       new_map->DictionaryElementsInPrototypeChainOnly()) {
12581     // If the prototype chain didn't previously have element callbacks, then
12582     // KeyedStoreICs need to be cleared to ensure any that involve this
12583     // map go generic.
12584     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12585   }
12586
12587   heap->ClearInstanceofCache();
12588   DCHECK(size == object->Size());
12589   return value;
12590 }
12591
12592
12593 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12594                                         Arguments* args,
12595                                         uint32_t first_arg,
12596                                         uint32_t arg_count,
12597                                         EnsureElementsMode mode) {
12598   // Elements in |Arguments| are ordered backwards (because they're on the
12599   // stack), but the method that's called here iterates over them in forward
12600   // direction.
12601   return EnsureCanContainElements(
12602       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12603 }
12604
12605
12606 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
12607     Handle<JSObject> object,
12608     uint32_t index) {
12609   if (object->IsJSGlobalProxy()) {
12610     PrototypeIterator iter(object->GetIsolate(), object);
12611     if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>();
12612     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12613     return GetOwnElementAccessorPair(
12614         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
12615   }
12616
12617   // Check for lookup interceptor.
12618   if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12619
12620   return object->GetElementsAccessor()->GetAccessorPair(object, index);
12621 }
12622
12623
12624 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12625     Handle<JSObject> object, uint32_t index, Handle<Object> value,
12626     PropertyAttributes attributes, LanguageMode language_mode,
12627     bool check_prototype, SetPropertyMode set_mode) {
12628   Isolate* isolate = object->GetIsolate();
12629
12630   // Make sure that the top context does not change when doing
12631   // callbacks or interceptor calls.
12632   AssertNoContextChange ncc(isolate);
12633
12634   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12635   if (!interceptor->setter()->IsUndefined()) {
12636     v8::IndexedPropertySetterCallback setter =
12637         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12638     LOG(isolate,
12639         ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12640     PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12641                                    *object);
12642     v8::Handle<v8::Value> result =
12643         args.Call(setter, index, v8::Utils::ToLocal(value));
12644     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12645     if (!result.IsEmpty()) return value;
12646   }
12647
12648   return SetElementWithoutInterceptor(object, index, value, attributes,
12649                                       language_mode, check_prototype, set_mode);
12650 }
12651
12652
12653 MaybeHandle<Object> JSObject::GetElementWithCallback(
12654     Handle<JSObject> object,
12655     Handle<Object> receiver,
12656     Handle<Object> structure,
12657     uint32_t index,
12658     Handle<Object> holder) {
12659   Isolate* isolate = object->GetIsolate();
12660   DCHECK(!structure->IsForeign());
12661   // api style callbacks.
12662   if (structure->IsExecutableAccessorInfo()) {
12663     Handle<ExecutableAccessorInfo> data =
12664         Handle<ExecutableAccessorInfo>::cast(structure);
12665     Object* fun_obj = data->getter();
12666     v8::AccessorNameGetterCallback call_fun =
12667         v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj);
12668     if (call_fun == NULL) return isolate->factory()->undefined_value();
12669     Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
12670     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12671     Handle<String> key = isolate->factory()->NumberToString(number);
12672     LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
12673     PropertyCallbackArguments
12674         args(isolate, data->data(), *receiver, *holder_handle);
12675     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
12676     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12677     if (result.IsEmpty()) return isolate->factory()->undefined_value();
12678     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12679     result_internal->VerifyApiCallResultType();
12680     // Rebox handle before return.
12681     return handle(*result_internal, isolate);
12682   }
12683
12684   // __defineGetter__ callback
12685   if (structure->IsAccessorPair()) {
12686     Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
12687                           isolate);
12688     if (getter->IsSpecFunction()) {
12689       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12690       return GetPropertyWithDefinedGetter(
12691           receiver, Handle<JSReceiver>::cast(getter));
12692     }
12693     // Getter is not a function.
12694     return isolate->factory()->undefined_value();
12695   }
12696
12697   UNREACHABLE();
12698   return MaybeHandle<Object>();
12699 }
12700
12701
12702 MaybeHandle<Object> JSObject::SetElementWithCallback(
12703     Handle<Object> object, Handle<Object> structure, uint32_t index,
12704     Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
12705   Isolate* isolate = holder->GetIsolate();
12706
12707   // We should never get here to initialize a const with the hole
12708   // value since a const declaration would conflict with the setter.
12709   DCHECK(!value->IsTheHole());
12710   DCHECK(!structure->IsForeign());
12711   if (structure->IsExecutableAccessorInfo()) {
12712     // api style callbacks
12713     Handle<ExecutableAccessorInfo> data =
12714         Handle<ExecutableAccessorInfo>::cast(structure);
12715     Object* call_obj = data->setter();
12716     v8::AccessorNameSetterCallback call_fun =
12717         v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
12718     if (call_fun == NULL) return value;
12719     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12720     Handle<String> key(isolate->factory()->NumberToString(number));
12721     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
12722     PropertyCallbackArguments
12723         args(isolate, data->data(), *object, *holder);
12724     args.Call(call_fun,
12725               v8::Utils::ToLocal(key),
12726               v8::Utils::ToLocal(value));
12727     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12728     return value;
12729   }
12730
12731   if (structure->IsAccessorPair()) {
12732     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12733     if (setter->IsSpecFunction()) {
12734       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12735       return SetPropertyWithDefinedSetter(
12736           object, Handle<JSReceiver>::cast(setter), value);
12737     } else {
12738       if (is_sloppy(language_mode)) return value;
12739       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12740       Handle<Object> args[] = {key, holder};
12741       THROW_NEW_ERROR(isolate,
12742                       NewTypeError("no_setter_in_callback",
12743                                    HandleVector(args, arraysize(args))),
12744                       Object);
12745     }
12746   }
12747
12748   UNREACHABLE();
12749   return MaybeHandle<Object>();
12750 }
12751
12752
12753 bool JSObject::HasFastArgumentsElements() {
12754   Heap* heap = GetHeap();
12755   if (!elements()->IsFixedArray()) return false;
12756   FixedArray* elements = FixedArray::cast(this->elements());
12757   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12758     return false;
12759   }
12760   FixedArray* arguments = FixedArray::cast(elements->get(1));
12761   return !arguments->IsDictionary();
12762 }
12763
12764
12765 bool JSObject::HasDictionaryArgumentsElements() {
12766   Heap* heap = GetHeap();
12767   if (!elements()->IsFixedArray()) return false;
12768   FixedArray* elements = FixedArray::cast(this->elements());
12769   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12770     return false;
12771   }
12772   FixedArray* arguments = FixedArray::cast(elements->get(1));
12773   return arguments->IsDictionary();
12774 }
12775
12776
12777 // Adding n elements in fast case is O(n*n).
12778 // Note: revisit design to have dual undefined values to capture absent
12779 // elements.
12780 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12781                                              uint32_t index,
12782                                              Handle<Object> value,
12783                                              LanguageMode language_mode,
12784                                              bool check_prototype) {
12785   DCHECK(object->HasFastSmiOrObjectElements() ||
12786          object->HasFastArgumentsElements());
12787
12788   Isolate* isolate = object->GetIsolate();
12789
12790   // Array optimizations rely on the prototype lookups of Array objects always
12791   // returning undefined. If there is a store to the initial prototype object,
12792   // make sure all of these optimizations are invalidated.
12793   if (isolate->is_initial_object_prototype(*object) ||
12794       isolate->is_initial_array_prototype(*object)) {
12795     object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
12796         DependentCode::kElementsCantBeAddedGroup);
12797   }
12798
12799   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12800   if (backing_store->map() ==
12801       isolate->heap()->sloppy_arguments_elements_map()) {
12802     backing_store = handle(FixedArray::cast(backing_store->get(1)));
12803   } else {
12804     backing_store = EnsureWritableFastElements(object);
12805   }
12806   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12807
12808   if (check_prototype &&
12809       (index >= capacity || backing_store->get(index)->IsTheHole())) {
12810     bool found;
12811     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12812         object, index, value, &found, language_mode);
12813     if (found) return result;
12814   }
12815
12816   uint32_t new_capacity = capacity;
12817   // Check if the length property of this object needs to be updated.
12818   uint32_t array_length = 0;
12819   bool must_update_array_length = false;
12820   bool introduces_holes = true;
12821   if (object->IsJSArray()) {
12822     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12823     introduces_holes = index > array_length;
12824     if (index >= array_length) {
12825       must_update_array_length = true;
12826       array_length = index + 1;
12827     }
12828   } else {
12829     introduces_holes = index >= capacity;
12830   }
12831
12832   // If the array is growing, and it's not growth by a single element at the
12833   // end, make sure that the ElementsKind is HOLEY.
12834   ElementsKind elements_kind = object->GetElementsKind();
12835   if (introduces_holes &&
12836       IsFastElementsKind(elements_kind) &&
12837       !IsFastHoleyElementsKind(elements_kind)) {
12838     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12839     TransitionElementsKind(object, transitioned_kind);
12840   }
12841
12842   // Check if the capacity of the backing store needs to be increased, or if
12843   // a transition to slow elements is necessary.
12844   if (index >= capacity) {
12845     bool convert_to_slow = true;
12846     if ((index - capacity) < kMaxGap) {
12847       new_capacity = NewElementsCapacity(index + 1);
12848       DCHECK(new_capacity > index);
12849       if (!object->ShouldConvertToSlowElements(new_capacity)) {
12850         convert_to_slow = false;
12851       }
12852     }
12853     if (convert_to_slow) {
12854       NormalizeElements(object);
12855       return SetDictionaryElement(object, index, value, NONE, language_mode,
12856                                   check_prototype);
12857     }
12858   }
12859   // Convert to fast double elements if appropriate.
12860   if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12861     // Consider fixing the boilerplate as well if we have one.
12862     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12863         ? FAST_HOLEY_DOUBLE_ELEMENTS
12864         : FAST_DOUBLE_ELEMENTS;
12865
12866     UpdateAllocationSite(object, to_kind);
12867
12868     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12869     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12870     JSObject::ValidateElements(object);
12871     return value;
12872   }
12873   // Change elements kind from Smi-only to generic FAST if necessary.
12874   if (object->HasFastSmiElements() && !value->IsSmi()) {
12875     ElementsKind kind = object->HasFastHoleyElements()
12876         ? FAST_HOLEY_ELEMENTS
12877         : FAST_ELEMENTS;
12878
12879     UpdateAllocationSite(object, kind);
12880     Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12881     JSObject::MigrateToMap(object, new_map);
12882     DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12883   }
12884   // Increase backing store capacity if that's been decided previously.
12885   if (new_capacity != capacity) {
12886     SetFastElementsCapacitySmiMode smi_mode =
12887         value->IsSmi() && object->HasFastSmiElements()
12888             ? kAllowSmiElements
12889             : kDontAllowSmiElements;
12890     Handle<FixedArray> new_elements =
12891         SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12892                                          smi_mode);
12893     new_elements->set(index, *value);
12894     JSObject::ValidateElements(object);
12895     return value;
12896   }
12897
12898   // Finally, set the new element and length.
12899   DCHECK(object->elements()->IsFixedArray());
12900   backing_store->set(index, *value);
12901   if (must_update_array_length) {
12902     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12903   }
12904   return value;
12905 }
12906
12907
12908 MaybeHandle<Object> JSObject::SetDictionaryElement(
12909     Handle<JSObject> object, uint32_t index, Handle<Object> value,
12910     PropertyAttributes attributes, LanguageMode language_mode,
12911     bool check_prototype, SetPropertyMode set_mode) {
12912   DCHECK(object->HasDictionaryElements() ||
12913          object->HasDictionaryArgumentsElements());
12914   Isolate* isolate = object->GetIsolate();
12915
12916   // Insert element in the dictionary.
12917   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12918   bool is_arguments =
12919       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12920   Handle<SeededNumberDictionary> dictionary(is_arguments
12921     ? SeededNumberDictionary::cast(elements->get(1))
12922     : SeededNumberDictionary::cast(*elements));
12923
12924   int entry = dictionary->FindEntry(index);
12925   if (entry != SeededNumberDictionary::kNotFound) {
12926     Handle<Object> element(dictionary->ValueAt(entry), isolate);
12927     PropertyDetails details = dictionary->DetailsAt(entry);
12928     if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) {
12929       return SetElementWithCallback(object, element, index, value, object,
12930                                     language_mode);
12931     } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12932                details.kind() == kAccessor) {
12933       return RedefineNonconfigurableProperty(
12934           isolate, isolate->factory()->NewNumberFromUint(index),
12935           isolate->factory()->undefined_value(), language_mode);
12936
12937     } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12938                 details.IsReadOnly()) ||
12939                (set_mode == SET_PROPERTY && details.IsReadOnly() &&
12940                 !element->IsTheHole())) {
12941       // If a value has not been initialized we allow writing to it even if it
12942       // is read-only (a declared const that has not been initialized).
12943       return WriteToReadOnlyProperty(
12944           isolate, object, isolate->factory()->NewNumberFromUint(index),
12945           isolate->factory()->undefined_value(), language_mode);
12946     } else {
12947       DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12948              element->IsTheHole());
12949       dictionary->UpdateMaxNumberKey(index);
12950       if (set_mode == DEFINE_PROPERTY) {
12951         details = PropertyDetails(attributes, DATA, details.dictionary_index());
12952         dictionary->DetailsAtPut(entry, details);
12953       }
12954
12955       // Elements of the arguments object in slow mode might be slow aliases.
12956       if (is_arguments && element->IsAliasedArgumentsEntry()) {
12957         Handle<AliasedArgumentsEntry> entry =
12958             Handle<AliasedArgumentsEntry>::cast(element);
12959         Handle<Context> context(Context::cast(elements->get(0)));
12960         int context_index = entry->aliased_context_slot();
12961         DCHECK(!context->get(context_index)->IsTheHole());
12962         context->set(context_index, *value);
12963         // For elements that are still writable we keep slow aliasing.
12964         if (!details.IsReadOnly()) value = element;
12965       }
12966       dictionary->ValueAtPut(entry, *value);
12967     }
12968   } else {
12969     // Index not already used. Look for an accessor in the prototype chain.
12970     // Can cause GC!
12971     if (check_prototype) {
12972       bool found;
12973       MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12974           object, index, value, &found, language_mode);
12975       if (found) return result;
12976     }
12977
12978     // When we set the is_extensible flag to false we always force the
12979     // element into dictionary mode (and force them to stay there).
12980     if (!object->map()->is_extensible()) {
12981       if (is_sloppy(language_mode)) {
12982         return isolate->factory()->undefined_value();
12983       } else {
12984         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12985         Handle<String> name = isolate->factory()->NumberToString(number);
12986         Handle<Object> args[] = {name};
12987         THROW_NEW_ERROR(isolate,
12988                         NewTypeError("object_not_extensible",
12989                                      HandleVector(args, arraysize(args))),
12990                         Object);
12991       }
12992     }
12993
12994     PropertyDetails details(attributes, DATA, 0);
12995     Handle<SeededNumberDictionary> new_dictionary =
12996         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12997                                                details);
12998     if (*dictionary != *new_dictionary) {
12999       if (is_arguments) {
13000         elements->set(1, *new_dictionary);
13001       } else {
13002         object->set_elements(*new_dictionary);
13003       }
13004       dictionary = new_dictionary;
13005     }
13006   }
13007
13008   // Update the array length if this JSObject is an array.
13009   if (object->IsJSArray()) {
13010     JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
13011                                           value);
13012   }
13013
13014   // Attempt to put this object back in fast case.
13015   if (object->ShouldConvertToFastElements()) {
13016     uint32_t new_length = 0;
13017     if (object->IsJSArray()) {
13018       CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
13019     } else {
13020       new_length = dictionary->max_number_key() + 1;
13021     }
13022     bool has_smi_only_elements = false;
13023     bool should_convert_to_fast_double_elements =
13024         object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
13025     SetFastElementsCapacitySmiMode smi_mode =
13026         has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
13027
13028     if (should_convert_to_fast_double_elements) {
13029       SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
13030     } else {
13031       SetFastElementsCapacityAndLength(object, new_length, new_length,
13032                                        smi_mode);
13033     }
13034     JSObject::ValidateElements(object);
13035 #ifdef DEBUG
13036     if (FLAG_trace_normalization) {
13037       OFStream os(stdout);
13038       os << "Object elements are fast case again:\n";
13039       object->Print(os);
13040     }
13041 #endif
13042   }
13043   return value;
13044 }
13045
13046 MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
13047                                                    uint32_t index,
13048                                                    Handle<Object> value,
13049                                                    LanguageMode language_mode,
13050                                                    bool check_prototype) {
13051   DCHECK(object->HasFastDoubleElements());
13052
13053   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
13054   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
13055
13056   // If storing to an element that isn't in the array, pass the store request
13057   // up the prototype chain before storing in the receiver's elements.
13058   if (check_prototype &&
13059       (index >= elms_length ||
13060        Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
13061     bool found;
13062     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
13063         object, index, value, &found, language_mode);
13064     if (found) return result;
13065   }
13066
13067   // If the value object is not a heap number, switch to fast elements and try
13068   // again.
13069   bool value_is_smi = value->IsSmi();
13070   bool introduces_holes = true;
13071   uint32_t length = elms_length;
13072   if (object->IsJSArray()) {
13073     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
13074     introduces_holes = index > length;
13075   } else {
13076     introduces_holes = index >= elms_length;
13077   }
13078
13079   if (!value->IsNumber()) {
13080     SetFastElementsCapacityAndLength(object, elms_length, length,
13081                                      kDontAllowSmiElements);
13082     Handle<Object> result;
13083     ASSIGN_RETURN_ON_EXCEPTION(
13084         object->GetIsolate(), result,
13085         SetFastElement(object, index, value, language_mode, check_prototype),
13086         Object);
13087     JSObject::ValidateElements(object);
13088     return result;
13089   }
13090
13091   double double_value = value_is_smi
13092       ? static_cast<double>(Handle<Smi>::cast(value)->value())
13093       : Handle<HeapNumber>::cast(value)->value();
13094
13095   // If the array is growing, and it's not growth by a single element at the
13096   // end, make sure that the ElementsKind is HOLEY.
13097   ElementsKind elements_kind = object->GetElementsKind();
13098   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
13099     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
13100     TransitionElementsKind(object, transitioned_kind);
13101   }
13102
13103   // Check whether there is extra space in the fixed array.
13104   if (index < elms_length) {
13105     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
13106     elms->set(index, double_value);
13107     if (object->IsJSArray()) {
13108       // Update the length of the array if needed.
13109       uint32_t array_length = 0;
13110       CHECK(
13111           Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
13112       if (index >= array_length) {
13113         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
13114       }
13115     }
13116     return value;
13117   }
13118
13119   // Allow gap in fast case.
13120   if ((index - elms_length) < kMaxGap) {
13121     // Try allocating extra space.
13122     int new_capacity = NewElementsCapacity(index+1);
13123     if (!object->ShouldConvertToSlowElements(new_capacity)) {
13124       DCHECK(static_cast<uint32_t>(new_capacity) > index);
13125       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
13126       FixedDoubleArray::cast(object->elements())->set(index, double_value);
13127       JSObject::ValidateElements(object);
13128       return value;
13129     }
13130   }
13131
13132   // Otherwise default to slow case.
13133   DCHECK(object->HasFastDoubleElements());
13134   DCHECK(object->map()->has_fast_double_elements());
13135   DCHECK(object->elements()->IsFixedDoubleArray() ||
13136          object->elements()->length() == 0);
13137
13138   NormalizeElements(object);
13139   DCHECK(object->HasDictionaryElements());
13140   return SetElement(object, index, value, NONE, language_mode, check_prototype);
13141 }
13142
13143
13144 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
13145                                            uint32_t index, Handle<Object> value,
13146                                            PropertyAttributes attributes,
13147                                            LanguageMode language_mode) {
13148   if (object->IsJSProxy()) {
13149     return JSProxy::SetElementWithHandler(Handle<JSProxy>::cast(object), object,
13150                                           index, value, language_mode);
13151   }
13152   return JSObject::SetElement(Handle<JSObject>::cast(object), index, value,
13153                               attributes, language_mode);
13154 }
13155
13156
13157 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
13158                                             uint32_t index,
13159                                             Handle<Object> value,
13160                                             PropertyAttributes attributes,
13161                                             LanguageMode language_mode) {
13162   DCHECK(!object->HasExternalArrayElements());
13163   return JSObject::SetElement(object, index, value, attributes, language_mode,
13164                               false);
13165 }
13166
13167
13168 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
13169                                          uint32_t index, Handle<Object> value,
13170                                          PropertyAttributes attributes,
13171                                          LanguageMode language_mode,
13172                                          bool check_prototype,
13173                                          SetPropertyMode set_mode) {
13174   Isolate* isolate = object->GetIsolate();
13175
13176   if (object->HasExternalArrayElements() ||
13177       object->HasFixedTypedArrayElements()) {
13178     if (!value->IsNumber() && !value->IsUndefined()) {
13179       ASSIGN_RETURN_ON_EXCEPTION(
13180           isolate, value,
13181           Execution::ToNumber(isolate, value), Object);
13182     }
13183   }
13184
13185   // Check access rights if needed.
13186   if (object->IsAccessCheckNeeded()) {
13187     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) {
13188       isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
13189       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13190       return value;
13191     }
13192   }
13193
13194   if (object->IsJSGlobalProxy()) {
13195     PrototypeIterator iter(isolate, object);
13196     if (iter.IsAtEnd()) return value;
13197     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13198     return SetElement(
13199         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
13200         value, attributes, language_mode, check_prototype, set_mode);
13201   }
13202
13203   // Don't allow element properties to be redefined for external arrays.
13204   if ((object->HasExternalArrayElements() ||
13205           object->HasFixedTypedArrayElements()) &&
13206       set_mode == DEFINE_PROPERTY) {
13207     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
13208     Handle<Object> args[] = { object, number };
13209     THROW_NEW_ERROR(isolate, NewTypeError("redef_external_array_element",
13210                                           HandleVector(args, arraysize(args))),
13211                     Object);
13212   }
13213
13214   // Normalize the elements to enable attributes on the property.
13215   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
13216     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
13217     // Make sure that we never go back to fast case.
13218     dictionary->set_requires_slow_elements();
13219   }
13220
13221   if (!object->map()->is_observed()) {
13222     return object->HasIndexedInterceptor()
13223                ? SetElementWithInterceptor(object, index, value, attributes,
13224                                            language_mode, check_prototype,
13225                                            set_mode)
13226                : SetElementWithoutInterceptor(object, index, value, attributes,
13227                                               language_mode, check_prototype,
13228                                               set_mode);
13229   }
13230
13231   Maybe<PropertyAttributes> maybe =
13232       JSReceiver::GetOwnElementAttribute(object, index);
13233   if (!maybe.has_value) return MaybeHandle<Object>();
13234   PropertyAttributes old_attributes = maybe.value;
13235
13236   Handle<Object> old_value = isolate->factory()->the_hole_value();
13237   Handle<Object> old_length_handle;
13238   Handle<Object> new_length_handle;
13239
13240   if (old_attributes != ABSENT) {
13241     if (GetOwnElementAccessorPair(object, index).is_null()) {
13242       old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
13243     }
13244   } else if (object->IsJSArray()) {
13245     // Store old array length in case adding an element grows the array.
13246     old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13247                                isolate);
13248   }
13249
13250   // Check for lookup interceptor
13251   Handle<Object> result;
13252   ASSIGN_RETURN_ON_EXCEPTION(
13253       isolate, result,
13254       object->HasIndexedInterceptor()
13255           ? SetElementWithInterceptor(object, index, value, attributes,
13256                                       language_mode, check_prototype, set_mode)
13257           : SetElementWithoutInterceptor(object, index, value, attributes,
13258                                          language_mode, check_prototype,
13259                                          set_mode),
13260       Object);
13261
13262   Handle<String> name = isolate->factory()->Uint32ToString(index);
13263   maybe = GetOwnElementAttribute(object, index);
13264   if (!maybe.has_value) return MaybeHandle<Object>();
13265   PropertyAttributes new_attributes = maybe.value;
13266
13267   if (old_attributes == ABSENT) {
13268     if (object->IsJSArray() &&
13269         !old_length_handle->SameValue(
13270             Handle<JSArray>::cast(object)->length())) {
13271       new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13272                                  isolate);
13273       uint32_t old_length = 0;
13274       uint32_t new_length = 0;
13275       CHECK(old_length_handle->ToArrayIndex(&old_length));
13276       CHECK(new_length_handle->ToArrayIndex(&new_length));
13277
13278       RETURN_ON_EXCEPTION(
13279           isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
13280       RETURN_ON_EXCEPTION(
13281           isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13282       RETURN_ON_EXCEPTION(
13283           isolate, EnqueueChangeRecord(object, "update",
13284                                        isolate->factory()->length_string(),
13285                                        old_length_handle),
13286           Object);
13287       RETURN_ON_EXCEPTION(
13288           isolate, EndPerformSplice(Handle<JSArray>::cast(object)), Object);
13289       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13290       RETURN_ON_EXCEPTION(
13291           isolate,
13292           EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length,
13293                               deleted, new_length - old_length),
13294           Object);
13295     } else {
13296       RETURN_ON_EXCEPTION(
13297           isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13298     }
13299   } else if (old_value->IsTheHole()) {
13300     RETURN_ON_EXCEPTION(
13301         isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
13302         Object);
13303   } else {
13304     Handle<Object> new_value =
13305         Object::GetElement(isolate, object, index).ToHandleChecked();
13306     bool value_changed = !old_value->SameValue(*new_value);
13307     if (old_attributes != new_attributes) {
13308       if (!value_changed) old_value = isolate->factory()->the_hole_value();
13309       RETURN_ON_EXCEPTION(
13310           isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
13311           Object);
13312     } else if (value_changed) {
13313       RETURN_ON_EXCEPTION(
13314           isolate, EnqueueChangeRecord(object, "update", name, old_value),
13315           Object);
13316     }
13317   }
13318
13319   return result;
13320 }
13321
13322
13323 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13324     Handle<JSObject> object, uint32_t index, Handle<Object> value,
13325     PropertyAttributes attributes, LanguageMode language_mode,
13326     bool check_prototype, SetPropertyMode set_mode) {
13327   DCHECK(object->HasDictionaryElements() ||
13328          object->HasDictionaryArgumentsElements() ||
13329          (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13330   Isolate* isolate = object->GetIsolate();
13331   if (FLAG_trace_external_array_abuse &&
13332       IsExternalArrayElementsKind(object->GetElementsKind())) {
13333     CheckArrayAbuse(object, "external elements write", index);
13334   }
13335   if (FLAG_trace_js_array_abuse &&
13336       !IsExternalArrayElementsKind(object->GetElementsKind())) {
13337     if (object->IsJSArray()) {
13338       CheckArrayAbuse(object, "elements write", index, true);
13339     }
13340   }
13341   if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13342       Handle<JSArray>::cast(object), index)) {
13343     if (is_sloppy(language_mode)) {
13344       return value;
13345     } else {
13346       return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13347     }
13348   }
13349   switch (object->GetElementsKind()) {
13350     case FAST_SMI_ELEMENTS:
13351     case FAST_ELEMENTS:
13352     case FAST_HOLEY_SMI_ELEMENTS:
13353     case FAST_HOLEY_ELEMENTS:
13354       return SetFastElement(object, index, value, language_mode,
13355                             check_prototype);
13356     case FAST_DOUBLE_ELEMENTS:
13357     case FAST_HOLEY_DOUBLE_ELEMENTS:
13358       return SetFastDoubleElement(object, index, value, language_mode,
13359                                   check_prototype);
13360
13361 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
13362     case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
13363       Handle<External##Type##Array> array(                                    \
13364           External##Type##Array::cast(object->elements()));                   \
13365       return External##Type##Array::SetValue(array, index, value);            \
13366     }                                                                         \
13367     case TYPE##_ELEMENTS: {                                                   \
13368       Handle<Fixed##Type##Array> array(                                       \
13369           Fixed##Type##Array::cast(object->elements()));                      \
13370       return Fixed##Type##Array::SetValue(array, index, value);               \
13371     }
13372
13373     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13374
13375 #undef TYPED_ARRAY_CASE
13376
13377     case DICTIONARY_ELEMENTS:
13378       return SetDictionaryElement(object, index, value, attributes,
13379                                   language_mode, check_prototype, set_mode);
13380     case SLOPPY_ARGUMENTS_ELEMENTS: {
13381       Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13382       uint32_t length = parameter_map->length();
13383       Handle<Object> probe = index < length - 2 ?
13384           Handle<Object>(parameter_map->get(index + 2), isolate) :
13385           Handle<Object>();
13386       if (!probe.is_null() && !probe->IsTheHole()) {
13387         Handle<Context> context(Context::cast(parameter_map->get(0)));
13388         int context_index = Handle<Smi>::cast(probe)->value();
13389         DCHECK(!context->get(context_index)->IsTheHole());
13390         context->set(context_index, *value);
13391         // Redefining attributes of an aliased element destroys fast aliasing.
13392         if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13393         parameter_map->set_the_hole(index + 2);
13394         // For elements that are still writable we re-establish slow aliasing.
13395         if ((attributes & READ_ONLY) == 0) {
13396           value = Handle<Object>::cast(
13397               isolate->factory()->NewAliasedArgumentsEntry(context_index));
13398         }
13399       }
13400       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13401       if (arguments->IsDictionary()) {
13402         return SetDictionaryElement(object, index, value, attributes,
13403                                     language_mode, check_prototype, set_mode);
13404       } else {
13405         return SetFastElement(object, index, value, language_mode,
13406                               check_prototype);
13407       }
13408     }
13409   }
13410   // All possible cases have been handled above. Add a return to avoid the
13411   // complaints from the compiler.
13412   UNREACHABLE();
13413   return isolate->factory()->null_value();
13414 }
13415
13416
13417 const double AllocationSite::kPretenureRatio = 0.85;
13418
13419
13420 void AllocationSite::ResetPretenureDecision() {
13421   set_pretenure_decision(kUndecided);
13422   set_memento_found_count(0);
13423   set_memento_create_count(0);
13424 }
13425
13426
13427 PretenureFlag AllocationSite::GetPretenureMode() {
13428   PretenureDecision mode = pretenure_decision();
13429   // Zombie objects "decide" to be untenured.
13430   return mode == kTenure ? TENURED : NOT_TENURED;
13431 }
13432
13433
13434 bool AllocationSite::IsNestedSite() {
13435   DCHECK(FLAG_trace_track_allocation_sites);
13436   Object* current = GetHeap()->allocation_sites_list();
13437   while (current->IsAllocationSite()) {
13438     AllocationSite* current_site = AllocationSite::cast(current);
13439     if (current_site->nested_site() == this) {
13440       return true;
13441     }
13442     current = current_site->weak_next();
13443   }
13444   return false;
13445 }
13446
13447
13448 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
13449                                               ElementsKind to_kind) {
13450   Isolate* isolate = site->GetIsolate();
13451
13452   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
13453     Handle<JSArray> transition_info =
13454         handle(JSArray::cast(site->transition_info()));
13455     ElementsKind kind = transition_info->GetElementsKind();
13456     // if kind is holey ensure that to_kind is as well.
13457     if (IsHoleyElementsKind(kind)) {
13458       to_kind = GetHoleyElementsKind(to_kind);
13459     }
13460     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13461       // If the array is huge, it's not likely to be defined in a local
13462       // function, so we shouldn't make new instances of it very often.
13463       uint32_t length = 0;
13464       CHECK(transition_info->length()->ToArrayIndex(&length));
13465       if (length <= kMaximumArrayBytesToPretransition) {
13466         if (FLAG_trace_track_allocation_sites) {
13467           bool is_nested = site->IsNestedSite();
13468           PrintF(
13469               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
13470               reinterpret_cast<void*>(*site),
13471               is_nested ? "(nested)" : "",
13472               ElementsKindToString(kind),
13473               ElementsKindToString(to_kind));
13474         }
13475         JSObject::TransitionElementsKind(transition_info, to_kind);
13476         site->dependent_code()->DeoptimizeDependentCodeGroup(
13477             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13478       }
13479     }
13480   } else {
13481     ElementsKind kind = site->GetElementsKind();
13482     // if kind is holey ensure that to_kind is as well.
13483     if (IsHoleyElementsKind(kind)) {
13484       to_kind = GetHoleyElementsKind(to_kind);
13485     }
13486     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13487       if (FLAG_trace_track_allocation_sites) {
13488         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
13489                reinterpret_cast<void*>(*site),
13490                ElementsKindToString(kind),
13491                ElementsKindToString(to_kind));
13492       }
13493       site->SetElementsKind(to_kind);
13494       site->dependent_code()->DeoptimizeDependentCodeGroup(
13495           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13496     }
13497   }
13498 }
13499
13500
13501 // static
13502 void AllocationSite::RegisterForDeoptOnTenureChange(Handle<AllocationSite> site,
13503                                                     CompilationInfo* info) {
13504   AddDependentCompilationInfo(
13505       site, DependentCode::kAllocationSiteTenuringChangedGroup, info);
13506 }
13507
13508
13509 // static
13510 void AllocationSite::RegisterForDeoptOnTransitionChange(
13511     Handle<AllocationSite> site, CompilationInfo* info) {
13512   // Do nothing if the object doesn't have any useful element transitions left.
13513   ElementsKind kind =
13514       site->SitePointsToLiteral()
13515           ? JSObject::cast(site->transition_info())->GetElementsKind()
13516           : site->GetElementsKind();
13517   if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
13518     AddDependentCompilationInfo(
13519         site, DependentCode::kAllocationSiteTransitionChangedGroup, info);
13520   }
13521 }
13522
13523
13524 // static
13525 void AllocationSite::AddDependentCompilationInfo(
13526     Handle<AllocationSite> site, DependentCode::DependencyGroup group,
13527     CompilationInfo* info) {
13528   Handle<DependentCode> dep(site->dependent_code());
13529   Handle<DependentCode> codes =
13530       DependentCode::InsertCompilationInfo(dep, group, info->object_wrapper());
13531   if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
13532   info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
13533 }
13534
13535
13536 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
13537   switch (decision) {
13538     case kUndecided: return "undecided";
13539     case kDontTenure: return "don't tenure";
13540     case kMaybeTenure: return "maybe tenure";
13541     case kTenure: return "tenure";
13542     case kZombie: return "zombie";
13543     default: UNREACHABLE();
13544   }
13545   return NULL;
13546 }
13547
13548
13549 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
13550                                     ElementsKind to_kind) {
13551   if (!object->IsJSArray()) return;
13552
13553   Heap* heap = object->GetHeap();
13554   if (!heap->InNewSpace(*object)) return;
13555
13556   Handle<AllocationSite> site;
13557   {
13558     DisallowHeapAllocation no_allocation;
13559
13560     AllocationMemento* memento = heap->FindAllocationMemento(*object);
13561     if (memento == NULL) return;
13562
13563     // Walk through to the Allocation Site
13564     site = handle(memento->GetAllocationSite());
13565   }
13566   AllocationSite::DigestTransitionFeedback(site, to_kind);
13567 }
13568
13569
13570 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13571                                       ElementsKind to_kind) {
13572   ElementsKind from_kind = object->map()->elements_kind();
13573
13574   if (IsFastHoleyElementsKind(from_kind)) {
13575     to_kind = GetHoleyElementsKind(to_kind);
13576   }
13577
13578   if (from_kind == to_kind) return;
13579   // Don't update the site if to_kind isn't fast
13580   if (IsFastElementsKind(to_kind)) {
13581     UpdateAllocationSite(object, to_kind);
13582   }
13583
13584   Isolate* isolate = object->GetIsolate();
13585   if (object->elements() == isolate->heap()->empty_fixed_array() ||
13586       (IsFastSmiOrObjectElementsKind(from_kind) &&
13587        IsFastSmiOrObjectElementsKind(to_kind)) ||
13588       (from_kind == FAST_DOUBLE_ELEMENTS &&
13589        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
13590     DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
13591     // No change is needed to the elements() buffer, the transition
13592     // only requires a map change.
13593     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13594     MigrateToMap(object, new_map);
13595     if (FLAG_trace_elements_transitions) {
13596       Handle<FixedArrayBase> elms(object->elements());
13597       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13598     }
13599     return;
13600   }
13601
13602   Handle<FixedArrayBase> elms(object->elements());
13603   uint32_t capacity = static_cast<uint32_t>(elms->length());
13604   uint32_t length = capacity;
13605
13606   if (object->IsJSArray()) {
13607     Object* raw_length = Handle<JSArray>::cast(object)->length();
13608     if (raw_length->IsUndefined()) {
13609       // If length is undefined, then JSArray is being initialized and has no
13610       // elements, assume a length of zero.
13611       length = 0;
13612     } else {
13613       CHECK(raw_length->ToArrayIndex(&length));
13614     }
13615   }
13616
13617   if (IsFastSmiElementsKind(from_kind) &&
13618       IsFastDoubleElementsKind(to_kind)) {
13619     SetFastDoubleElementsCapacityAndLength(object, capacity, length);
13620     JSObject::ValidateElements(object);
13621     return;
13622   }
13623
13624   if (IsFastDoubleElementsKind(from_kind) &&
13625       IsFastObjectElementsKind(to_kind)) {
13626     SetFastElementsCapacityAndLength(object, capacity, length,
13627                                      kDontAllowSmiElements);
13628     JSObject::ValidateElements(object);
13629     return;
13630   }
13631
13632   // This method should never be called for any other case than the ones
13633   // handled above.
13634   UNREACHABLE();
13635 }
13636
13637
13638 // static
13639 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13640                                     ElementsKind to_kind) {
13641   // Transitions can't go backwards.
13642   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13643     return false;
13644   }
13645
13646   // Transitions from HOLEY -> PACKED are not allowed.
13647   return !IsFastHoleyElementsKind(from_kind) ||
13648       IsFastHoleyElementsKind(to_kind);
13649 }
13650
13651
13652 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
13653                                            uint32_t index,
13654                                            Handle<Object> value) {
13655   uint32_t old_len = 0;
13656   CHECK(array->length()->ToArrayIndex(&old_len));
13657   // Check to see if we need to update the length. For now, we make
13658   // sure that the length stays within 32-bits (unsigned).
13659   if (index >= old_len && index != 0xffffffff) {
13660     Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
13661         static_cast<double>(index) + 1);
13662     array->set_length(*len);
13663   }
13664 }
13665
13666
13667 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
13668   LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
13669                     LookupIterator::OWN_SKIP_INTERCEPTOR);
13670   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
13671   CHECK(it.IsFound());
13672   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
13673   return it.IsReadOnly();
13674 }
13675
13676
13677 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
13678                                         uint32_t index) {
13679   uint32_t length = 0;
13680   CHECK(array->length()->ToArrayIndex(&length));
13681   if (length <= index) return HasReadOnlyLength(array);
13682   return false;
13683 }
13684
13685
13686 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
13687   Isolate* isolate = array->GetIsolate();
13688   Handle<Name> length = isolate->factory()->length_string();
13689   Handle<Object> args[] = {length, array};
13690   THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
13691                                         HandleVector(args, arraysize(args))),
13692                   Object);
13693 }
13694
13695
13696 MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
13697                                                         Handle<Object> receiver,
13698                                                         uint32_t index,
13699                                                         bool check_prototype) {
13700   Isolate* isolate = object->GetIsolate();
13701
13702   // Make sure that the top context does not change when doing
13703   // callbacks or interceptor calls.
13704   AssertNoContextChange ncc(isolate);
13705
13706   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13707   if (!interceptor->getter()->IsUndefined()) {
13708     v8::IndexedPropertyGetterCallback getter =
13709         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13710     LOG(isolate,
13711         ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13712     PropertyCallbackArguments
13713         args(isolate, interceptor->data(), *receiver, *object);
13714     v8::Handle<v8::Value> result = args.Call(getter, index);
13715     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13716     if (!result.IsEmpty()) {
13717       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13718       result_internal->VerifyApiCallResultType();
13719       // Rebox handle before return.
13720       return handle(*result_internal, isolate);
13721     }
13722   }
13723
13724   if (!check_prototype) return MaybeHandle<Object>();
13725
13726   ElementsAccessor* handler = object->GetElementsAccessor();
13727   Handle<Object> result;
13728   ASSIGN_RETURN_ON_EXCEPTION(
13729       isolate, result, handler->Get(receiver,  object, index),
13730       Object);
13731   if (!result->IsTheHole()) return result;
13732
13733   PrototypeIterator iter(isolate, object);
13734   if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
13735   return Object::GetElementWithReceiver(
13736       isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
13737 }
13738
13739
13740 bool JSObject::HasDenseElements() {
13741   int capacity = 0;
13742   int used = 0;
13743   GetElementsCapacityAndUsage(&capacity, &used);
13744   return (capacity == 0) || (used > (capacity / 2));
13745 }
13746
13747
13748 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
13749   *capacity = 0;
13750   *used = 0;
13751
13752   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
13753   FixedArray* backing_store = NULL;
13754   switch (GetElementsKind()) {
13755     case SLOPPY_ARGUMENTS_ELEMENTS:
13756       backing_store_base =
13757           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
13758       backing_store = FixedArray::cast(backing_store_base);
13759       if (backing_store->IsDictionary()) {
13760         SeededNumberDictionary* dictionary =
13761             SeededNumberDictionary::cast(backing_store);
13762         *capacity = dictionary->Capacity();
13763         *used = dictionary->NumberOfElements();
13764         break;
13765       }
13766       // Fall through.
13767     case FAST_SMI_ELEMENTS:
13768     case FAST_ELEMENTS:
13769       if (IsJSArray()) {
13770         *capacity = backing_store_base->length();
13771         *used = Smi::cast(JSArray::cast(this)->length())->value();
13772         break;
13773       }
13774       // Fall through if packing is not guaranteed.
13775     case FAST_HOLEY_SMI_ELEMENTS:
13776     case FAST_HOLEY_ELEMENTS:
13777       backing_store = FixedArray::cast(backing_store_base);
13778       *capacity = backing_store->length();
13779       for (int i = 0; i < *capacity; ++i) {
13780         if (!backing_store->get(i)->IsTheHole()) ++(*used);
13781       }
13782       break;
13783     case DICTIONARY_ELEMENTS: {
13784       SeededNumberDictionary* dictionary = element_dictionary();
13785       *capacity = dictionary->Capacity();
13786       *used = dictionary->NumberOfElements();
13787       break;
13788     }
13789     case FAST_DOUBLE_ELEMENTS:
13790       if (IsJSArray()) {
13791         *capacity = backing_store_base->length();
13792         *used = Smi::cast(JSArray::cast(this)->length())->value();
13793         break;
13794       }
13795       // Fall through if packing is not guaranteed.
13796     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13797       *capacity = elements()->length();
13798       if (*capacity == 0) break;
13799       FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
13800       for (int i = 0; i < *capacity; i++) {
13801         if (!elms->is_the_hole(i)) ++(*used);
13802       }
13803       break;
13804     }
13805
13806 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13807     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13808     case TYPE##_ELEMENTS:                                                    \
13809
13810     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13811 #undef TYPED_ARRAY_CASE
13812     {
13813       // External arrays are considered 100% used.
13814       FixedArrayBase* external_array = FixedArrayBase::cast(elements());
13815       *capacity = external_array->length();
13816       *used = external_array->length();
13817       break;
13818     }
13819   }
13820 }
13821
13822
13823 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
13824   uint32_t index;
13825   if (HasFastElements() && key->ToArrayIndex(&index)) {
13826     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
13827     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
13828     if (index >= capacity) {
13829       if ((index - capacity) >= kMaxGap) return true;
13830       uint32_t new_capacity = NewElementsCapacity(index + 1);
13831       return ShouldConvertToSlowElements(new_capacity);
13832     }
13833   }
13834   return false;
13835 }
13836
13837
13838 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
13839   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
13840                 kMaxUncheckedFastElementsLength);
13841   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
13842       (new_capacity <= kMaxUncheckedFastElementsLength &&
13843        GetHeap()->InNewSpace(this))) {
13844     return false;
13845   }
13846   // If the fast-case backing storage takes up roughly three times as
13847   // much space (in machine words) as a dictionary backing storage
13848   // would, the object should have slow elements.
13849   int old_capacity = 0;
13850   int used_elements = 0;
13851   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
13852   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
13853       SeededNumberDictionary::kEntrySize;
13854   return 3 * dictionary_size <= new_capacity;
13855 }
13856
13857
13858 bool JSObject::ShouldConvertToFastElements() {
13859   DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements());
13860   // If the elements are sparse, we should not go back to fast case.
13861   if (!HasDenseElements()) return false;
13862   // An object requiring access checks is never allowed to have fast
13863   // elements.  If it had fast elements we would skip security checks.
13864   if (IsAccessCheckNeeded()) return false;
13865   // Observed objects may not go to fast mode because they rely on map checks,
13866   // and for fast element accesses we sometimes check element kinds only.
13867   if (map()->is_observed()) return false;
13868
13869   FixedArray* elements = FixedArray::cast(this->elements());
13870   SeededNumberDictionary* dictionary = NULL;
13871   if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13872     dictionary = SeededNumberDictionary::cast(elements->get(1));
13873   } else {
13874     dictionary = SeededNumberDictionary::cast(elements);
13875   }
13876   // If an element has been added at a very high index in the elements
13877   // dictionary, we cannot go back to fast case.
13878   if (dictionary->requires_slow_elements()) return false;
13879   // If the dictionary backing storage takes up roughly half as much
13880   // space (in machine words) as a fast-case backing storage would,
13881   // the object should have fast elements.
13882   uint32_t array_size = 0;
13883   if (IsJSArray()) {
13884     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13885   } else {
13886     array_size = dictionary->max_number_key();
13887   }
13888   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13889       SeededNumberDictionary::kEntrySize;
13890   return 2 * dictionary_size >= array_size;
13891 }
13892
13893
13894 bool JSObject::ShouldConvertToFastDoubleElements(
13895     bool* has_smi_only_elements) {
13896   *has_smi_only_elements = false;
13897   if (HasSloppyArgumentsElements()) return false;
13898   if (FLAG_unbox_double_arrays) {
13899     DCHECK(HasDictionaryElements());
13900     SeededNumberDictionary* dictionary = element_dictionary();
13901     bool found_double = false;
13902     for (int i = 0; i < dictionary->Capacity(); i++) {
13903       Object* key = dictionary->KeyAt(i);
13904       if (key->IsNumber()) {
13905         Object* value = dictionary->ValueAt(i);
13906         if (!value->IsNumber()) return false;
13907         if (!value->IsSmi()) {
13908           found_double = true;
13909         }
13910       }
13911     }
13912     *has_smi_only_elements = !found_double;
13913     return found_double;
13914   } else {
13915     return false;
13916   }
13917 }
13918
13919
13920 // Certain compilers request function template instantiation when they
13921 // see the definition of the other template functions in the
13922 // class. This requires us to have the template functions put
13923 // together, so even though this function belongs in objects-debug.cc,
13924 // we keep it here instead to satisfy certain compilers.
13925 #ifdef OBJECT_PRINT
13926 template <typename Derived, typename Shape, typename Key>
13927 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
13928   int capacity = DerivedHashTable::Capacity();
13929   for (int i = 0; i < capacity; i++) {
13930     Object* k = DerivedHashTable::KeyAt(i);
13931     if (DerivedHashTable::IsKey(k)) {
13932       os << " ";
13933       if (k->IsString()) {
13934         String::cast(k)->StringPrint(os);
13935       } else {
13936         os << Brief(k);
13937       }
13938       os << ": " << Brief(ValueAt(i)) << " " << DetailsAt(i) << "\n";
13939     }
13940   }
13941 }
13942 #endif
13943
13944
13945 template<typename Derived, typename Shape, typename Key>
13946 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
13947   int pos = 0;
13948   int capacity = DerivedHashTable::Capacity();
13949   DisallowHeapAllocation no_gc;
13950   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13951   for (int i = 0; i < capacity; i++) {
13952     Object* k =  Dictionary::KeyAt(i);
13953     if (Dictionary::IsKey(k)) {
13954       elements->set(pos++, ValueAt(i), mode);
13955     }
13956   }
13957   DCHECK(pos == elements->length());
13958 }
13959
13960
13961 InterceptorInfo* JSObject::GetNamedInterceptor() {
13962   DCHECK(map()->has_named_interceptor());
13963   JSFunction* constructor = JSFunction::cast(map()->constructor());
13964   DCHECK(constructor->shared()->IsApiFunction());
13965   Object* result =
13966       constructor->shared()->get_api_func_data()->named_property_handler();
13967   return InterceptorInfo::cast(result);
13968 }
13969
13970
13971 InterceptorInfo* JSObject::GetIndexedInterceptor() {
13972   DCHECK(map()->has_indexed_interceptor());
13973   JSFunction* constructor = JSFunction::cast(map()->constructor());
13974   DCHECK(constructor->shared()->IsApiFunction());
13975   Object* result =
13976       constructor->shared()->get_api_func_data()->indexed_property_handler();
13977   return InterceptorInfo::cast(result);
13978 }
13979
13980
13981 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(
13982     Handle<JSObject> holder,
13983     Handle<Object> receiver,
13984     Handle<Name> name) {
13985   Isolate* isolate = holder->GetIsolate();
13986
13987   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13988   if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13989
13990   if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
13991     return MaybeHandle<Object>();
13992   }
13993
13994   v8::GenericNamedPropertyGetterCallback getter =
13995       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
13996           interceptor->getter());
13997   LOG(isolate,
13998       ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13999   PropertyCallbackArguments
14000       args(isolate, interceptor->data(), *receiver, *holder);
14001   v8::Handle<v8::Value> result = args.Call(getter, v8::Utils::ToLocal(name));
14002   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
14003   if (result.IsEmpty()) return MaybeHandle<Object>();
14004
14005   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
14006   result_internal->VerifyApiCallResultType();
14007   // Rebox handle before return
14008   return handle(*result_internal, isolate);
14009 }
14010
14011
14012 // Compute the property keys from the interceptor.
14013 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
14014     Handle<JSObject> object, Handle<JSReceiver> receiver) {
14015   Isolate* isolate = receiver->GetIsolate();
14016   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
14017   PropertyCallbackArguments
14018       args(isolate, interceptor->data(), *receiver, *object);
14019   v8::Handle<v8::Object> result;
14020   if (!interceptor->enumerator()->IsUndefined()) {
14021     v8::GenericNamedPropertyEnumeratorCallback enum_fun =
14022         v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>(
14023             interceptor->enumerator());
14024     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
14025     result = args.Call(enum_fun);
14026   }
14027   if (result.IsEmpty()) return MaybeHandle<JSObject>();
14028   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
14029          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
14030   // Rebox before returning.
14031   return handle(*v8::Utils::OpenHandle(*result), isolate);
14032 }
14033
14034
14035 // Compute the element keys from the interceptor.
14036 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
14037     Handle<JSObject> object, Handle<JSReceiver> receiver) {
14038   Isolate* isolate = receiver->GetIsolate();
14039   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
14040   PropertyCallbackArguments
14041       args(isolate, interceptor->data(), *receiver, *object);
14042   v8::Handle<v8::Object> result;
14043   if (!interceptor->enumerator()->IsUndefined()) {
14044     v8::IndexedPropertyEnumeratorCallback enum_fun =
14045         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
14046             interceptor->enumerator());
14047     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
14048     result = args.Call(enum_fun);
14049   }
14050   if (result.IsEmpty()) return MaybeHandle<JSObject>();
14051   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
14052          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
14053   // Rebox before returning.
14054   return handle(*v8::Utils::OpenHandle(*result), isolate);
14055 }
14056
14057
14058 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
14059                                            Handle<Name> key) {
14060   LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
14061   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
14062   if (!maybe_result.has_value) return Maybe<bool>();
14063   return maybe(it.IsFound());
14064 }
14065
14066
14067 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
14068                                              uint32_t index) {
14069   Isolate* isolate = object->GetIsolate();
14070   HandleScope scope(isolate);
14071   // Check access rights if needed.
14072   if (object->IsAccessCheckNeeded()) {
14073     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
14074       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
14075       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
14076       return maybe(false);
14077     }
14078   }
14079
14080   if (object->IsJSGlobalProxy()) {
14081     HandleScope scope(isolate);
14082     PrototypeIterator iter(isolate, object);
14083     if (iter.IsAtEnd()) return maybe(false);
14084     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
14085     return HasRealElementProperty(
14086         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
14087   }
14088
14089   Maybe<PropertyAttributes> result =
14090       GetElementAttributeWithoutInterceptor(object, object, index, false);
14091   if (!result.has_value) return Maybe<bool>();
14092   return maybe(result.value != ABSENT);
14093 }
14094
14095
14096 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
14097                                                    Handle<Name> key) {
14098   LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
14099   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
14100   if (!maybe_result.has_value) return Maybe<bool>();
14101   return maybe(it.state() == LookupIterator::ACCESSOR);
14102 }
14103
14104
14105 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
14106   if (HasFastProperties()) {
14107     Map* map = this->map();
14108     if (filter == NONE) return map->NumberOfOwnDescriptors();
14109     if (filter & DONT_ENUM) {
14110       int result = map->EnumLength();
14111       if (result != kInvalidEnumCacheSentinel) return result;
14112     }
14113     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
14114   }
14115   return property_dictionary()->NumberOfElementsFilterAttributes(filter);
14116 }
14117
14118
14119 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
14120   Object* temp = get(i);
14121   set(i, get(j));
14122   set(j, temp);
14123   if (this != numbers) {
14124     temp = numbers->get(i);
14125     numbers->set(i, Smi::cast(numbers->get(j)));
14126     numbers->set(j, Smi::cast(temp));
14127   }
14128 }
14129
14130
14131 static void InsertionSortPairs(FixedArray* content,
14132                                FixedArray* numbers,
14133                                int len) {
14134   for (int i = 1; i < len; i++) {
14135     int j = i;
14136     while (j > 0 &&
14137            (NumberToUint32(numbers->get(j - 1)) >
14138             NumberToUint32(numbers->get(j)))) {
14139       content->SwapPairs(numbers, j - 1, j);
14140       j--;
14141     }
14142   }
14143 }
14144
14145
14146 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
14147   // In-place heap sort.
14148   DCHECK(content->length() == numbers->length());
14149
14150   // Bottom-up max-heap construction.
14151   for (int i = 1; i < len; ++i) {
14152     int child_index = i;
14153     while (child_index > 0) {
14154       int parent_index = ((child_index + 1) >> 1) - 1;
14155       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
14156       uint32_t child_value = NumberToUint32(numbers->get(child_index));
14157       if (parent_value < child_value) {
14158         content->SwapPairs(numbers, parent_index, child_index);
14159       } else {
14160         break;
14161       }
14162       child_index = parent_index;
14163     }
14164   }
14165
14166   // Extract elements and create sorted array.
14167   for (int i = len - 1; i > 0; --i) {
14168     // Put max element at the back of the array.
14169     content->SwapPairs(numbers, 0, i);
14170     // Sift down the new top element.
14171     int parent_index = 0;
14172     while (true) {
14173       int child_index = ((parent_index + 1) << 1) - 1;
14174       if (child_index >= i) break;
14175       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
14176       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
14177       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
14178       if (child_index + 1 >= i || child1_value > child2_value) {
14179         if (parent_value > child1_value) break;
14180         content->SwapPairs(numbers, parent_index, child_index);
14181         parent_index = child_index;
14182       } else {
14183         if (parent_value > child2_value) break;
14184         content->SwapPairs(numbers, parent_index, child_index + 1);
14185         parent_index = child_index + 1;
14186       }
14187     }
14188   }
14189 }
14190
14191
14192 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
14193 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
14194   DCHECK(this->length() == numbers->length());
14195   // For small arrays, simply use insertion sort.
14196   if (len <= 10) {
14197     InsertionSortPairs(this, numbers, len);
14198     return;
14199   }
14200   // Check the range of indices.
14201   uint32_t min_index = NumberToUint32(numbers->get(0));
14202   uint32_t max_index = min_index;
14203   uint32_t i;
14204   for (i = 1; i < len; i++) {
14205     if (NumberToUint32(numbers->get(i)) < min_index) {
14206       min_index = NumberToUint32(numbers->get(i));
14207     } else if (NumberToUint32(numbers->get(i)) > max_index) {
14208       max_index = NumberToUint32(numbers->get(i));
14209     }
14210   }
14211   if (max_index - min_index + 1 == len) {
14212     // Indices form a contiguous range, unless there are duplicates.
14213     // Do an in-place linear time sort assuming distinct numbers, but
14214     // avoid hanging in case they are not.
14215     for (i = 0; i < len; i++) {
14216       uint32_t p;
14217       uint32_t j = 0;
14218       // While the current element at i is not at its correct position p,
14219       // swap the elements at these two positions.
14220       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
14221              j++ < len) {
14222         SwapPairs(numbers, i, p);
14223       }
14224     }
14225   } else {
14226     HeapSortPairs(this, numbers, len);
14227     return;
14228   }
14229 }
14230
14231
14232 // Fill in the names of own properties into the supplied storage. The main
14233 // purpose of this function is to provide reflection information for the object
14234 // mirrors.
14235 void JSObject::GetOwnPropertyNames(
14236     FixedArray* storage, int index, PropertyAttributes filter) {
14237   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
14238   if (HasFastProperties()) {
14239     int real_size = map()->NumberOfOwnDescriptors();
14240     DescriptorArray* descs = map()->instance_descriptors();
14241     for (int i = 0; i < real_size; i++) {
14242       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
14243           !FilterKey(descs->GetKey(i), filter)) {
14244         storage->set(index++, descs->GetKey(i));
14245       }
14246     }
14247   } else {
14248     property_dictionary()->CopyKeysTo(storage,
14249                                       index,
14250                                       filter,
14251                                       NameDictionary::UNSORTED);
14252   }
14253 }
14254
14255
14256 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
14257   return GetOwnElementKeys(NULL, filter);
14258 }
14259
14260
14261 int JSObject::NumberOfEnumElements() {
14262   // Fast case for objects with no elements.
14263   if (!IsJSValue() && HasFastObjectElements()) {
14264     uint32_t length = IsJSArray() ?
14265         static_cast<uint32_t>(
14266             Smi::cast(JSArray::cast(this)->length())->value()) :
14267         static_cast<uint32_t>(FixedArray::cast(elements())->length());
14268     if (length == 0) return 0;
14269   }
14270   // Compute the number of enumerable elements.
14271   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
14272 }
14273
14274
14275 int JSObject::GetOwnElementKeys(FixedArray* storage,
14276                                 PropertyAttributes filter) {
14277   int counter = 0;
14278   switch (GetElementsKind()) {
14279     case FAST_SMI_ELEMENTS:
14280     case FAST_ELEMENTS:
14281     case FAST_HOLEY_SMI_ELEMENTS:
14282     case FAST_HOLEY_ELEMENTS: {
14283       int length = IsJSArray() ?
14284           Smi::cast(JSArray::cast(this)->length())->value() :
14285           FixedArray::cast(elements())->length();
14286       for (int i = 0; i < length; i++) {
14287         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
14288           if (storage != NULL) {
14289             storage->set(counter, Smi::FromInt(i));
14290           }
14291           counter++;
14292         }
14293       }
14294       DCHECK(!storage || storage->length() >= counter);
14295       break;
14296     }
14297     case FAST_DOUBLE_ELEMENTS:
14298     case FAST_HOLEY_DOUBLE_ELEMENTS: {
14299       int length = IsJSArray() ?
14300           Smi::cast(JSArray::cast(this)->length())->value() :
14301           FixedArrayBase::cast(elements())->length();
14302       for (int i = 0; i < length; i++) {
14303         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
14304           if (storage != NULL) {
14305             storage->set(counter, Smi::FromInt(i));
14306           }
14307           counter++;
14308         }
14309       }
14310       DCHECK(!storage || storage->length() >= counter);
14311       break;
14312     }
14313
14314 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
14315     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
14316     case TYPE##_ELEMENTS:                                                    \
14317
14318     TYPED_ARRAYS(TYPED_ARRAY_CASE)
14319 #undef TYPED_ARRAY_CASE
14320     {
14321       int length = FixedArrayBase::cast(elements())->length();
14322       while (counter < length) {
14323         if (storage != NULL) {
14324           storage->set(counter, Smi::FromInt(counter));
14325         }
14326         counter++;
14327       }
14328       DCHECK(!storage || storage->length() >= counter);
14329       break;
14330     }
14331
14332     case DICTIONARY_ELEMENTS: {
14333       if (storage != NULL) {
14334         element_dictionary()->CopyKeysTo(storage,
14335                                          filter,
14336                                          SeededNumberDictionary::SORTED);
14337       }
14338       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
14339       break;
14340     }
14341     case SLOPPY_ARGUMENTS_ELEMENTS: {
14342       FixedArray* parameter_map = FixedArray::cast(elements());
14343       int mapped_length = parameter_map->length() - 2;
14344       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
14345       if (arguments->IsDictionary()) {
14346         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
14347         // will insert in storage starting at index 0.
14348         SeededNumberDictionary* dictionary =
14349             SeededNumberDictionary::cast(arguments);
14350         if (storage != NULL) {
14351           dictionary->CopyKeysTo(
14352               storage, filter, SeededNumberDictionary::UNSORTED);
14353         }
14354         counter += dictionary->NumberOfElementsFilterAttributes(filter);
14355         for (int i = 0; i < mapped_length; ++i) {
14356           if (!parameter_map->get(i + 2)->IsTheHole()) {
14357             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14358             ++counter;
14359           }
14360         }
14361         if (storage != NULL) storage->SortPairs(storage, counter);
14362
14363       } else {
14364         int backing_length = arguments->length();
14365         int i = 0;
14366         for (; i < mapped_length; ++i) {
14367           if (!parameter_map->get(i + 2)->IsTheHole()) {
14368             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14369             ++counter;
14370           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
14371             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14372             ++counter;
14373           }
14374         }
14375         for (; i < backing_length; ++i) {
14376           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14377           ++counter;
14378         }
14379       }
14380       break;
14381     }
14382   }
14383
14384   if (this->IsJSValue()) {
14385     Object* val = JSValue::cast(this)->value();
14386     if (val->IsString()) {
14387       String* str = String::cast(val);
14388       if (storage) {
14389         for (int i = 0; i < str->length(); i++) {
14390           storage->set(counter + i, Smi::FromInt(i));
14391         }
14392       }
14393       counter += str->length();
14394     }
14395   }
14396   DCHECK(!storage || storage->length() == counter);
14397   return counter;
14398 }
14399
14400
14401 int JSObject::GetEnumElementKeys(FixedArray* storage) {
14402   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
14403 }
14404
14405
14406 const char* Symbol::PrivateSymbolToName() const {
14407   Heap* heap = GetIsolate()->heap();
14408 #define SYMBOL_CHECK_AND_PRINT(name) \
14409   if (this == heap->name()) return #name;
14410   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
14411 #undef SYMBOL_CHECK_AND_PRINT
14412   return "UNKNOWN";
14413 }
14414
14415
14416 void Symbol::SymbolShortPrint(std::ostream& os) {
14417   os << "<Symbol: " << Hash();
14418   if (!name()->IsUndefined()) {
14419     os << " ";
14420     HeapStringAllocator allocator;
14421     StringStream accumulator(&allocator);
14422     String::cast(name())->StringShortPrint(&accumulator);
14423     os << accumulator.ToCString().get();
14424   } else {
14425     os << " (" << PrivateSymbolToName() << ")";
14426   }
14427   os << ">";
14428 }
14429
14430
14431 // StringSharedKeys are used as keys in the eval cache.
14432 class StringSharedKey : public HashTableKey {
14433  public:
14434   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
14435                   LanguageMode language_mode, int scope_position)
14436       : source_(source),
14437         shared_(shared),
14438         language_mode_(language_mode),
14439         scope_position_(scope_position) {}
14440
14441   bool IsMatch(Object* other) OVERRIDE {
14442     DisallowHeapAllocation no_allocation;
14443     if (!other->IsFixedArray()) {
14444       if (!other->IsNumber()) return false;
14445       uint32_t other_hash = static_cast<uint32_t>(other->Number());
14446       return Hash() == other_hash;
14447     }
14448     FixedArray* other_array = FixedArray::cast(other);
14449     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14450     if (shared != *shared_) return false;
14451     int language_unchecked = Smi::cast(other_array->get(2))->value();
14452     DCHECK(is_valid_language_mode(language_unchecked));
14453     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
14454     if (language_mode != language_mode_) return false;
14455     int scope_position = Smi::cast(other_array->get(3))->value();
14456     if (scope_position != scope_position_) return false;
14457     String* source = String::cast(other_array->get(1));
14458     return source->Equals(*source_);
14459   }
14460
14461   static uint32_t StringSharedHashHelper(String* source,
14462                                          SharedFunctionInfo* shared,
14463                                          LanguageMode language_mode,
14464                                          int scope_position) {
14465     uint32_t hash = source->Hash();
14466     if (shared->HasSourceCode()) {
14467       // Instead of using the SharedFunctionInfo pointer in the hash
14468       // code computation, we use a combination of the hash of the
14469       // script source code and the start position of the calling scope.
14470       // We do this to ensure that the cache entries can survive garbage
14471       // collection.
14472       Script* script(Script::cast(shared->script()));
14473       hash ^= String::cast(script->source())->Hash();
14474       STATIC_ASSERT(LANGUAGE_END == 3);
14475       if (is_strict(language_mode)) hash ^= 0x8000;
14476       if (is_strong(language_mode)) hash ^= 0x10000;
14477       hash += scope_position;
14478     }
14479     return hash;
14480   }
14481
14482   uint32_t Hash() OVERRIDE {
14483     return StringSharedHashHelper(*source_, *shared_, language_mode_,
14484                                   scope_position_);
14485   }
14486
14487   uint32_t HashForObject(Object* obj) OVERRIDE {
14488     DisallowHeapAllocation no_allocation;
14489     if (obj->IsNumber()) {
14490       return static_cast<uint32_t>(obj->Number());
14491     }
14492     FixedArray* other_array = FixedArray::cast(obj);
14493     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14494     String* source = String::cast(other_array->get(1));
14495     int language_unchecked = Smi::cast(other_array->get(2))->value();
14496     DCHECK(is_valid_language_mode(language_unchecked));
14497     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
14498     int scope_position = Smi::cast(other_array->get(3))->value();
14499     return StringSharedHashHelper(source, shared, language_mode,
14500                                   scope_position);
14501   }
14502
14503
14504   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14505     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
14506     array->set(0, *shared_);
14507     array->set(1, *source_);
14508     array->set(2, Smi::FromInt(language_mode_));
14509     array->set(3, Smi::FromInt(scope_position_));
14510     return array;
14511   }
14512
14513  private:
14514   Handle<String> source_;
14515   Handle<SharedFunctionInfo> shared_;
14516   LanguageMode language_mode_;
14517   int scope_position_;
14518 };
14519
14520
14521 // RegExpKey carries the source and flags of a regular expression as key.
14522 class RegExpKey : public HashTableKey {
14523  public:
14524   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
14525       : string_(string),
14526         flags_(Smi::FromInt(flags.value())) { }
14527
14528   // Rather than storing the key in the hash table, a pointer to the
14529   // stored value is stored where the key should be.  IsMatch then
14530   // compares the search key to the found object, rather than comparing
14531   // a key to a key.
14532   bool IsMatch(Object* obj) OVERRIDE {
14533     FixedArray* val = FixedArray::cast(obj);
14534     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
14535         && (flags_ == val->get(JSRegExp::kFlagsIndex));
14536   }
14537
14538   uint32_t Hash() OVERRIDE { return RegExpHash(*string_, flags_); }
14539
14540   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14541     // Plain hash maps, which is where regexp keys are used, don't
14542     // use this function.
14543     UNREACHABLE();
14544     return MaybeHandle<Object>().ToHandleChecked();
14545   }
14546
14547   uint32_t HashForObject(Object* obj) OVERRIDE {
14548     FixedArray* val = FixedArray::cast(obj);
14549     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
14550                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
14551   }
14552
14553   static uint32_t RegExpHash(String* string, Smi* flags) {
14554     return string->Hash() + flags->value();
14555   }
14556
14557   Handle<String> string_;
14558   Smi* flags_;
14559 };
14560
14561
14562 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
14563   if (hash_field_ == 0) Hash();
14564   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
14565 }
14566
14567
14568 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
14569   if (hash_field_ == 0) Hash();
14570   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
14571 }
14572
14573
14574 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
14575   if (hash_field_ == 0) Hash();
14576   return isolate->factory()->NewOneByteInternalizedSubString(
14577       string_, from_, length_, hash_field_);
14578 }
14579
14580
14581 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
14582   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
14583   return String::cast(string)->IsOneByteEqualTo(chars);
14584 }
14585
14586
14587 // InternalizedStringKey carries a string/internalized-string object as key.
14588 class InternalizedStringKey : public HashTableKey {
14589  public:
14590   explicit InternalizedStringKey(Handle<String> string)
14591       : string_(string) { }
14592
14593   bool IsMatch(Object* string) OVERRIDE {
14594     return String::cast(string)->Equals(*string_);
14595   }
14596
14597   uint32_t Hash() OVERRIDE { return string_->Hash(); }
14598
14599   uint32_t HashForObject(Object* other) OVERRIDE {
14600     return String::cast(other)->Hash();
14601   }
14602
14603   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14604     // Internalize the string if possible.
14605     MaybeHandle<Map> maybe_map =
14606         isolate->factory()->InternalizedStringMapForString(string_);
14607     Handle<Map> map;
14608     if (maybe_map.ToHandle(&map)) {
14609       string_->set_map_no_write_barrier(*map);
14610       DCHECK(string_->IsInternalizedString());
14611       return string_;
14612     }
14613     // Otherwise allocate a new internalized string.
14614     return isolate->factory()->NewInternalizedStringImpl(
14615         string_, string_->length(), string_->hash_field());
14616   }
14617
14618   static uint32_t StringHash(Object* obj) {
14619     return String::cast(obj)->Hash();
14620   }
14621
14622   Handle<String> string_;
14623 };
14624
14625
14626 template<typename Derived, typename Shape, typename Key>
14627 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
14628   IteratePointers(v, 0, kElementsStartOffset);
14629 }
14630
14631
14632 template<typename Derived, typename Shape, typename Key>
14633 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
14634   IteratePointers(v,
14635                   kElementsStartOffset,
14636                   kHeaderSize + length() * kPointerSize);
14637 }
14638
14639
14640 template<typename Derived, typename Shape, typename Key>
14641 Handle<Derived> HashTable<Derived, Shape, Key>::New(
14642     Isolate* isolate,
14643     int at_least_space_for,
14644     MinimumCapacity capacity_option,
14645     PretenureFlag pretenure) {
14646   DCHECK(0 <= at_least_space_for);
14647   DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
14648   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
14649                      ? at_least_space_for
14650                      : ComputeCapacity(at_least_space_for);
14651   if (capacity > HashTable::kMaxCapacity) {
14652     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
14653   }
14654
14655   Factory* factory = isolate->factory();
14656   int length = EntryToIndex(capacity);
14657   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
14658   array->set_map_no_write_barrier(*factory->hash_table_map());
14659   Handle<Derived> table = Handle<Derived>::cast(array);
14660
14661   table->SetNumberOfElements(0);
14662   table->SetNumberOfDeletedElements(0);
14663   table->SetCapacity(capacity);
14664   return table;
14665 }
14666
14667
14668 // Find entry for key otherwise return kNotFound.
14669 int NameDictionary::FindEntry(Handle<Name> key) {
14670   if (!key->IsUniqueName()) {
14671     return DerivedHashTable::FindEntry(key);
14672   }
14673
14674   // Optimized for unique names. Knowledge of the key type allows:
14675   // 1. Move the check if the key is unique out of the loop.
14676   // 2. Avoid comparing hash codes in unique-to-unique comparison.
14677   // 3. Detect a case when a dictionary key is not unique but the key is.
14678   //    In case of positive result the dictionary key may be replaced by the
14679   //    internalized string with minimal performance penalty. It gives a chance
14680   //    to perform further lookups in code stubs (and significant performance
14681   //    boost a certain style of code).
14682
14683   // EnsureCapacity will guarantee the hash table is never full.
14684   uint32_t capacity = Capacity();
14685   uint32_t entry = FirstProbe(key->Hash(), capacity);
14686   uint32_t count = 1;
14687
14688   while (true) {
14689     int index = EntryToIndex(entry);
14690     Object* element = get(index);
14691     if (element->IsUndefined()) break;  // Empty entry.
14692     if (*key == element) return entry;
14693     if (!element->IsUniqueName() &&
14694         !element->IsTheHole() &&
14695         Name::cast(element)->Equals(*key)) {
14696       // Replace a key that is a non-internalized string by the equivalent
14697       // internalized string for faster further lookups.
14698       set(index, *key);
14699       return entry;
14700     }
14701     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
14702     entry = NextProbe(entry, count++, capacity);
14703   }
14704   return kNotFound;
14705 }
14706
14707
14708 template<typename Derived, typename Shape, typename Key>
14709 void HashTable<Derived, Shape, Key>::Rehash(
14710     Handle<Derived> new_table,
14711     Key key) {
14712   DCHECK(NumberOfElements() < new_table->Capacity());
14713
14714   DisallowHeapAllocation no_gc;
14715   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
14716
14717   // Copy prefix to new array.
14718   for (int i = kPrefixStartIndex;
14719        i < kPrefixStartIndex + Shape::kPrefixSize;
14720        i++) {
14721     new_table->set(i, get(i), mode);
14722   }
14723
14724   // Rehash the elements.
14725   int capacity = Capacity();
14726   for (int i = 0; i < capacity; i++) {
14727     uint32_t from_index = EntryToIndex(i);
14728     Object* k = get(from_index);
14729     if (IsKey(k)) {
14730       uint32_t hash = HashTable::HashForObject(key, k);
14731       uint32_t insertion_index =
14732           EntryToIndex(new_table->FindInsertionEntry(hash));
14733       for (int j = 0; j < Shape::kEntrySize; j++) {
14734         new_table->set(insertion_index + j, get(from_index + j), mode);
14735       }
14736     }
14737   }
14738   new_table->SetNumberOfElements(NumberOfElements());
14739   new_table->SetNumberOfDeletedElements(0);
14740 }
14741
14742
14743 template<typename Derived, typename Shape, typename Key>
14744 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
14745     Key key,
14746     Object* k,
14747     int probe,
14748     uint32_t expected) {
14749   uint32_t hash = HashTable::HashForObject(key, k);
14750   uint32_t capacity = Capacity();
14751   uint32_t entry = FirstProbe(hash, capacity);
14752   for (int i = 1; i < probe; i++) {
14753     if (entry == expected) return expected;
14754     entry = NextProbe(entry, i, capacity);
14755   }
14756   return entry;
14757 }
14758
14759
14760 template<typename Derived, typename Shape, typename Key>
14761 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
14762                                           uint32_t entry2,
14763                                           WriteBarrierMode mode) {
14764   int index1 = EntryToIndex(entry1);
14765   int index2 = EntryToIndex(entry2);
14766   Object* temp[Shape::kEntrySize];
14767   for (int j = 0; j < Shape::kEntrySize; j++) {
14768     temp[j] = get(index1 + j);
14769   }
14770   for (int j = 0; j < Shape::kEntrySize; j++) {
14771     set(index1 + j, get(index2 + j), mode);
14772   }
14773   for (int j = 0; j < Shape::kEntrySize; j++) {
14774     set(index2 + j, temp[j], mode);
14775   }
14776 }
14777
14778
14779 template<typename Derived, typename Shape, typename Key>
14780 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
14781   DisallowHeapAllocation no_gc;
14782   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
14783   uint32_t capacity = Capacity();
14784   bool done = false;
14785   for (int probe = 1; !done; probe++) {
14786     // All elements at entries given by one of the first _probe_ probes
14787     // are placed correctly. Other elements might need to be moved.
14788     done = true;
14789     for (uint32_t current = 0; current < capacity; current++) {
14790       Object* current_key = get(EntryToIndex(current));
14791       if (IsKey(current_key)) {
14792         uint32_t target = EntryForProbe(key, current_key, probe, current);
14793         if (current == target) continue;
14794         Object* target_key = get(EntryToIndex(target));
14795         if (!IsKey(target_key) ||
14796             EntryForProbe(key, target_key, probe, target) != target) {
14797           // Put the current element into the correct position.
14798           Swap(current, target, mode);
14799           // The other element will be processed on the next iteration.
14800           current--;
14801         } else {
14802           // The place for the current element is occupied. Leave the element
14803           // for the next probe.
14804           done = false;
14805         }
14806       }
14807     }
14808   }
14809 }
14810
14811
14812 template<typename Derived, typename Shape, typename Key>
14813 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
14814     Handle<Derived> table,
14815     int n,
14816     Key key,
14817     PretenureFlag pretenure) {
14818   Isolate* isolate = table->GetIsolate();
14819   int capacity = table->Capacity();
14820   int nof = table->NumberOfElements() + n;
14821   int nod = table->NumberOfDeletedElements();
14822   // Return if:
14823   //   50% is still free after adding n elements and
14824   //   at most 50% of the free elements are deleted elements.
14825   if (nod <= (capacity - nof) >> 1) {
14826     int needed_free = nof >> 1;
14827     if (nof + needed_free <= capacity) return table;
14828   }
14829
14830   const int kMinCapacityForPretenure = 256;
14831   bool should_pretenure = pretenure == TENURED ||
14832       ((capacity > kMinCapacityForPretenure) &&
14833           !isolate->heap()->InNewSpace(*table));
14834   Handle<Derived> new_table = HashTable::New(
14835       isolate,
14836       nof * 2,
14837       USE_DEFAULT_MINIMUM_CAPACITY,
14838       should_pretenure ? TENURED : NOT_TENURED);
14839
14840   table->Rehash(new_table, key);
14841   return new_table;
14842 }
14843
14844
14845 template<typename Derived, typename Shape, typename Key>
14846 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
14847                                                        Key key) {
14848   int capacity = table->Capacity();
14849   int nof = table->NumberOfElements();
14850
14851   // Shrink to fit the number of elements if only a quarter of the
14852   // capacity is filled with elements.
14853   if (nof > (capacity >> 2)) return table;
14854   // Allocate a new dictionary with room for at least the current
14855   // number of elements. The allocation method will make sure that
14856   // there is extra room in the dictionary for additions. Don't go
14857   // lower than room for 16 elements.
14858   int at_least_room_for = nof;
14859   if (at_least_room_for < 16) return table;
14860
14861   Isolate* isolate = table->GetIsolate();
14862   const int kMinCapacityForPretenure = 256;
14863   bool pretenure =
14864       (at_least_room_for > kMinCapacityForPretenure) &&
14865       !isolate->heap()->InNewSpace(*table);
14866   Handle<Derived> new_table = HashTable::New(
14867       isolate,
14868       at_least_room_for,
14869       USE_DEFAULT_MINIMUM_CAPACITY,
14870       pretenure ? TENURED : NOT_TENURED);
14871
14872   table->Rehash(new_table, key);
14873   return new_table;
14874 }
14875
14876
14877 template<typename Derived, typename Shape, typename Key>
14878 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
14879   uint32_t capacity = Capacity();
14880   uint32_t entry = FirstProbe(hash, capacity);
14881   uint32_t count = 1;
14882   // EnsureCapacity will guarantee the hash table is never full.
14883   while (true) {
14884     Object* element = KeyAt(entry);
14885     if (element->IsUndefined() || element->IsTheHole()) break;
14886     entry = NextProbe(entry, count++, capacity);
14887   }
14888   return entry;
14889 }
14890
14891
14892 // Force instantiation of template instances class.
14893 // Please note this list is compiler dependent.
14894
14895 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
14896
14897 template class HashTable<CompilationCacheTable,
14898                          CompilationCacheShape,
14899                          HashTableKey*>;
14900
14901 template class HashTable<ObjectHashTable,
14902                          ObjectHashTableShape,
14903                          Handle<Object> >;
14904
14905 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
14906
14907 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
14908
14909 template class Dictionary<SeededNumberDictionary,
14910                           SeededNumberDictionaryShape,
14911                           uint32_t>;
14912
14913 template class Dictionary<UnseededNumberDictionary,
14914                           UnseededNumberDictionaryShape,
14915                           uint32_t>;
14916
14917 template Handle<SeededNumberDictionary>
14918 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14919     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14920
14921 template Handle<UnseededNumberDictionary>
14922 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14923     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14924
14925 template Handle<NameDictionary>
14926 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14927     New(Isolate*, int n, PretenureFlag pretenure);
14928
14929 template Handle<SeededNumberDictionary>
14930 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14931     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
14932
14933 template Handle<UnseededNumberDictionary>
14934 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14935     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
14936
14937 template Object*
14938 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14939     SlowReverseLookup(Object* value);
14940
14941 template Object*
14942 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14943     SlowReverseLookup(Object* value);
14944
14945 template void
14946 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14947     CopyKeysTo(
14948         FixedArray*,
14949         PropertyAttributes,
14950         Dictionary<SeededNumberDictionary,
14951                    SeededNumberDictionaryShape,
14952                    uint32_t>::SortMode);
14953
14954 template Handle<Object>
14955 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
14956     Handle<NameDictionary>, int);
14957
14958 template Handle<Object>
14959 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
14960            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
14961
14962 template Handle<NameDictionary>
14963 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14964     New(Isolate*, int, MinimumCapacity, PretenureFlag);
14965
14966 template Handle<NameDictionary>
14967 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14968     Shrink(Handle<NameDictionary>, Handle<Name>);
14969
14970 template Handle<SeededNumberDictionary>
14971 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14972     Shrink(Handle<SeededNumberDictionary>, uint32_t);
14973
14974 template void Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14975     CopyKeysTo(
14976         FixedArray*,
14977         int,
14978         PropertyAttributes,
14979         Dictionary<
14980             NameDictionary, NameDictionaryShape, Handle<Name> >::SortMode);
14981
14982 template int
14983 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14984     NumberOfElementsFilterAttributes(PropertyAttributes);
14985
14986 template Handle<NameDictionary>
14987 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
14988     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
14989
14990 template Handle<FixedArray> Dictionary<
14991     NameDictionary, NameDictionaryShape,
14992     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
14993
14994 template Handle<FixedArray> Dictionary<
14995     NameDictionary, NameDictionaryShape,
14996     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
14997
14998 template int
14999 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
15000     NumberOfElementsFilterAttributes(PropertyAttributes);
15001
15002 template Handle<SeededNumberDictionary>
15003 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
15004     Add(Handle<SeededNumberDictionary>,
15005         uint32_t,
15006         Handle<Object>,
15007         PropertyDetails);
15008
15009 template Handle<UnseededNumberDictionary>
15010 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
15011     Add(Handle<UnseededNumberDictionary>,
15012         uint32_t,
15013         Handle<Object>,
15014         PropertyDetails);
15015
15016 template Handle<SeededNumberDictionary>
15017 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
15018     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
15019
15020 template Handle<UnseededNumberDictionary>
15021 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
15022     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
15023
15024 template Handle<NameDictionary>
15025 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
15026     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
15027
15028 template
15029 int Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
15030     NumberOfEnumElements();
15031
15032 template
15033 int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
15034     NumberOfEnumElements();
15035
15036 template bool Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
15037                          uint32_t>::HasComplexElements();
15038
15039 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
15040                        uint32_t>::FindEntry(uint32_t);
15041
15042
15043 Handle<Object> JSObject::PrepareSlowElementsForSort(
15044     Handle<JSObject> object, uint32_t limit) {
15045   DCHECK(object->HasDictionaryElements());
15046   Isolate* isolate = object->GetIsolate();
15047   // Must stay in dictionary mode, either because of requires_slow_elements,
15048   // or because we are not going to sort (and therefore compact) all of the
15049   // elements.
15050   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
15051   Handle<SeededNumberDictionary> new_dict =
15052       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
15053
15054   uint32_t pos = 0;
15055   uint32_t undefs = 0;
15056   int capacity = dict->Capacity();
15057   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
15058   // Entry to the new dictionary does not cause it to grow, as we have
15059   // allocated one that is large enough for all entries.
15060   DisallowHeapAllocation no_gc;
15061   for (int i = 0; i < capacity; i++) {
15062     Object* k = dict->KeyAt(i);
15063     if (!dict->IsKey(k)) continue;
15064
15065     DCHECK(k->IsNumber());
15066     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
15067     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
15068     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
15069
15070     HandleScope scope(isolate);
15071     Handle<Object> value(dict->ValueAt(i), isolate);
15072     PropertyDetails details = dict->DetailsAt(i);
15073     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
15074       // Bail out and do the sorting of undefineds and array holes in JS.
15075       // Also bail out if the element is not supposed to be moved.
15076       return bailout;
15077     }
15078
15079     uint32_t key = NumberToUint32(k);
15080     if (key < limit) {
15081       if (value->IsUndefined()) {
15082         undefs++;
15083       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
15084         // Adding an entry with the key beyond smi-range requires
15085         // allocation. Bailout.
15086         return bailout;
15087       } else {
15088         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
15089             new_dict, pos, value, details);
15090         DCHECK(result.is_identical_to(new_dict));
15091         USE(result);
15092         pos++;
15093       }
15094     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
15095       // Adding an entry with the key beyond smi-range requires
15096       // allocation. Bailout.
15097       return bailout;
15098     } else {
15099       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
15100           new_dict, key, value, details);
15101       DCHECK(result.is_identical_to(new_dict));
15102       USE(result);
15103     }
15104   }
15105
15106   uint32_t result = pos;
15107   PropertyDetails no_details(NONE, DATA, 0);
15108   while (undefs > 0) {
15109     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
15110       // Adding an entry with the key beyond smi-range requires
15111       // allocation. Bailout.
15112       return bailout;
15113     }
15114     HandleScope scope(isolate);
15115     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
15116         new_dict, pos, isolate->factory()->undefined_value(), no_details);
15117     DCHECK(result.is_identical_to(new_dict));
15118     USE(result);
15119     pos++;
15120     undefs--;
15121   }
15122
15123   object->set_elements(*new_dict);
15124
15125   AllowHeapAllocation allocate_return_value;
15126   return isolate->factory()->NewNumberFromUint(result);
15127 }
15128
15129
15130 // Collects all defined (non-hole) and non-undefined (array) elements at
15131 // the start of the elements array.
15132 // If the object is in dictionary mode, it is converted to fast elements
15133 // mode.
15134 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
15135                                                 uint32_t limit) {
15136   Isolate* isolate = object->GetIsolate();
15137   if (object->HasSloppyArgumentsElements() ||
15138       object->map()->is_observed()) {
15139     return handle(Smi::FromInt(-1), isolate);
15140   }
15141
15142   if (object->HasDictionaryElements()) {
15143     // Convert to fast elements containing only the existing properties.
15144     // Ordering is irrelevant, since we are going to sort anyway.
15145     Handle<SeededNumberDictionary> dict(object->element_dictionary());
15146     if (object->IsJSArray() || dict->requires_slow_elements() ||
15147         dict->max_number_key() >= limit) {
15148       return JSObject::PrepareSlowElementsForSort(object, limit);
15149     }
15150     // Convert to fast elements.
15151
15152     Handle<Map> new_map =
15153         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
15154
15155     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
15156         NOT_TENURED: TENURED;
15157     Handle<FixedArray> fast_elements =
15158         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
15159     dict->CopyValuesTo(*fast_elements);
15160     JSObject::ValidateElements(object);
15161
15162     JSObject::SetMapAndElements(object, new_map, fast_elements);
15163   } else if (object->HasExternalArrayElements() ||
15164              object->HasFixedTypedArrayElements()) {
15165     // Typed arrays cannot have holes or undefined elements.
15166     return handle(Smi::FromInt(
15167         FixedArrayBase::cast(object->elements())->length()), isolate);
15168   } else if (!object->HasFastDoubleElements()) {
15169     EnsureWritableFastElements(object);
15170   }
15171   DCHECK(object->HasFastSmiOrObjectElements() ||
15172          object->HasFastDoubleElements());
15173
15174   // Collect holes at the end, undefined before that and the rest at the
15175   // start, and return the number of non-hole, non-undefined values.
15176
15177   Handle<FixedArrayBase> elements_base(object->elements());
15178   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
15179   if (limit > elements_length) {
15180     limit = elements_length ;
15181   }
15182   if (limit == 0) {
15183     return handle(Smi::FromInt(0), isolate);
15184   }
15185
15186   uint32_t result = 0;
15187   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
15188     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
15189     // Split elements into defined and the_hole, in that order.
15190     unsigned int holes = limit;
15191     // Assume most arrays contain no holes and undefined values, so minimize the
15192     // number of stores of non-undefined, non-the-hole values.
15193     for (unsigned int i = 0; i < holes; i++) {
15194       if (elements->is_the_hole(i)) {
15195         holes--;
15196       } else {
15197         continue;
15198       }
15199       // Position i needs to be filled.
15200       while (holes > i) {
15201         if (elements->is_the_hole(holes)) {
15202           holes--;
15203         } else {
15204           elements->set(i, elements->get_scalar(holes));
15205           break;
15206         }
15207       }
15208     }
15209     result = holes;
15210     while (holes < limit) {
15211       elements->set_the_hole(holes);
15212       holes++;
15213     }
15214   } else {
15215     FixedArray* elements = FixedArray::cast(*elements_base);
15216     DisallowHeapAllocation no_gc;
15217
15218     // Split elements into defined, undefined and the_hole, in that order.  Only
15219     // count locations for undefined and the hole, and fill them afterwards.
15220     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
15221     unsigned int undefs = limit;
15222     unsigned int holes = limit;
15223     // Assume most arrays contain no holes and undefined values, so minimize the
15224     // number of stores of non-undefined, non-the-hole values.
15225     for (unsigned int i = 0; i < undefs; i++) {
15226       Object* current = elements->get(i);
15227       if (current->IsTheHole()) {
15228         holes--;
15229         undefs--;
15230       } else if (current->IsUndefined()) {
15231         undefs--;
15232       } else {
15233         continue;
15234       }
15235       // Position i needs to be filled.
15236       while (undefs > i) {
15237         current = elements->get(undefs);
15238         if (current->IsTheHole()) {
15239           holes--;
15240           undefs--;
15241         } else if (current->IsUndefined()) {
15242           undefs--;
15243         } else {
15244           elements->set(i, current, write_barrier);
15245           break;
15246         }
15247       }
15248     }
15249     result = undefs;
15250     while (undefs < holes) {
15251       elements->set_undefined(undefs);
15252       undefs++;
15253     }
15254     while (holes < limit) {
15255       elements->set_the_hole(holes);
15256       holes++;
15257     }
15258   }
15259
15260   return isolate->factory()->NewNumberFromUint(result);
15261 }
15262
15263
15264 ExternalArrayType JSTypedArray::type() {
15265   switch (elements()->map()->instance_type()) {
15266 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
15267     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15268     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
15269       return kExternal##Type##Array;
15270
15271     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
15272 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
15273
15274     default:
15275       UNREACHABLE();
15276       return static_cast<ExternalArrayType>(-1);
15277   }
15278 }
15279
15280
15281 size_t JSTypedArray::element_size() {
15282   switch (elements()->map()->instance_type()) {
15283 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
15284     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15285       return size;
15286
15287     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
15288 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
15289
15290     default:
15291       UNREACHABLE();
15292       return 0;
15293   }
15294 }
15295
15296
15297 Handle<Object> ExternalUint8ClampedArray::SetValue(
15298     Handle<ExternalUint8ClampedArray> array,
15299     uint32_t index,
15300     Handle<Object> value) {
15301   uint8_t clamped_value = 0;
15302   if (index < static_cast<uint32_t>(array->length())) {
15303     if (value->IsSmi()) {
15304       int int_value = Handle<Smi>::cast(value)->value();
15305       if (int_value < 0) {
15306         clamped_value = 0;
15307       } else if (int_value > 255) {
15308         clamped_value = 255;
15309       } else {
15310         clamped_value = static_cast<uint8_t>(int_value);
15311       }
15312     } else if (value->IsHeapNumber()) {
15313       double double_value = Handle<HeapNumber>::cast(value)->value();
15314       if (!(double_value > 0)) {
15315         // NaN and less than zero clamp to zero.
15316         clamped_value = 0;
15317       } else if (double_value > 255) {
15318         // Greater than 255 clamp to 255.
15319         clamped_value = 255;
15320       } else {
15321         // Other doubles are rounded to the nearest integer.
15322         clamped_value = static_cast<uint8_t>(lrint(double_value));
15323       }
15324     } else {
15325       // Clamp undefined to zero (default). All other types have been
15326       // converted to a number type further up in the call chain.
15327       DCHECK(value->IsUndefined());
15328     }
15329     array->set(index, clamped_value);
15330   }
15331   return handle(Smi::FromInt(clamped_value), array->GetIsolate());
15332 }
15333
15334
15335 template<typename ExternalArrayClass, typename ValueType>
15336 static Handle<Object> ExternalArrayIntSetter(
15337     Isolate* isolate,
15338     Handle<ExternalArrayClass> receiver,
15339     uint32_t index,
15340     Handle<Object> value) {
15341   ValueType cast_value = 0;
15342   if (index < static_cast<uint32_t>(receiver->length())) {
15343     if (value->IsSmi()) {
15344       int int_value = Handle<Smi>::cast(value)->value();
15345       cast_value = static_cast<ValueType>(int_value);
15346     } else if (value->IsHeapNumber()) {
15347       double double_value = Handle<HeapNumber>::cast(value)->value();
15348       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
15349     } else {
15350       // Clamp undefined to zero (default). All other types have been
15351       // converted to a number type further up in the call chain.
15352       DCHECK(value->IsUndefined());
15353     }
15354     receiver->set(index, cast_value);
15355   }
15356   return isolate->factory()->NewNumberFromInt(cast_value);
15357 }
15358
15359
15360 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
15361                                            uint32_t index,
15362                                            Handle<Object> value) {
15363   return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
15364       array->GetIsolate(), array, index, value);
15365 }
15366
15367
15368 Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
15369                                             uint32_t index,
15370                                             Handle<Object> value) {
15371   return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
15372       array->GetIsolate(), array, index, value);
15373 }
15374
15375
15376 Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
15377                                             uint32_t index,
15378                                             Handle<Object> value) {
15379   return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
15380       array->GetIsolate(), array, index, value);
15381 }
15382
15383
15384 Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
15385                                              uint32_t index,
15386                                              Handle<Object> value) {
15387   return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
15388       array->GetIsolate(), array, index, value);
15389 }
15390
15391
15392 Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
15393                                             uint32_t index,
15394                                             Handle<Object> value) {
15395   return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
15396       array->GetIsolate(), array, index, value);
15397 }
15398
15399
15400 Handle<Object> ExternalUint32Array::SetValue(
15401     Handle<ExternalUint32Array> array,
15402     uint32_t index,
15403     Handle<Object> value) {
15404   uint32_t cast_value = 0;
15405   if (index < static_cast<uint32_t>(array->length())) {
15406     if (value->IsSmi()) {
15407       int int_value = Handle<Smi>::cast(value)->value();
15408       cast_value = static_cast<uint32_t>(int_value);
15409     } else if (value->IsHeapNumber()) {
15410       double double_value = Handle<HeapNumber>::cast(value)->value();
15411       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
15412     } else {
15413       // Clamp undefined to zero (default). All other types have been
15414       // converted to a number type further up in the call chain.
15415       DCHECK(value->IsUndefined());
15416     }
15417     array->set(index, cast_value);
15418   }
15419   return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
15420 }
15421
15422
15423 Handle<Object> ExternalFloat32Array::SetValue(
15424     Handle<ExternalFloat32Array> array,
15425     uint32_t index,
15426     Handle<Object> value) {
15427   float cast_value = std::numeric_limits<float>::quiet_NaN();
15428   if (index < static_cast<uint32_t>(array->length())) {
15429     if (value->IsSmi()) {
15430       int int_value = Handle<Smi>::cast(value)->value();
15431       cast_value = static_cast<float>(int_value);
15432     } else if (value->IsHeapNumber()) {
15433       double double_value = Handle<HeapNumber>::cast(value)->value();
15434       cast_value = static_cast<float>(double_value);
15435     } else {
15436       // Clamp undefined to NaN (default). All other types have been
15437       // converted to a number type further up in the call chain.
15438       DCHECK(value->IsUndefined());
15439     }
15440     array->set(index, cast_value);
15441   }
15442   return array->GetIsolate()->factory()->NewNumber(cast_value);
15443 }
15444
15445
15446 Handle<Object> ExternalFloat64Array::SetValue(
15447     Handle<ExternalFloat64Array> array,
15448     uint32_t index,
15449     Handle<Object> value) {
15450   double double_value = std::numeric_limits<double>::quiet_NaN();
15451   if (index < static_cast<uint32_t>(array->length())) {
15452     if (value->IsNumber()) {
15453       double_value = value->Number();
15454     } else {
15455       // Clamp undefined to NaN (default). All other types have been
15456       // converted to a number type further up in the call chain.
15457       DCHECK(value->IsUndefined());
15458     }
15459     array->set(index, double_value);
15460   }
15461   return array->GetIsolate()->factory()->NewNumber(double_value);
15462 }
15463
15464
15465 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
15466                                           Handle<Name> name) {
15467   DCHECK(!global->HasFastProperties());
15468   Isolate* isolate = global->GetIsolate();
15469   int entry = global->property_dictionary()->FindEntry(name);
15470   if (entry != NameDictionary::kNotFound) {
15471     Handle<PropertyCell> cell(
15472         PropertyCell::cast(global->property_dictionary()->ValueAt(entry)));
15473
15474     Handle<Object> value(cell->value(), isolate);
15475     Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(value);
15476     global->property_dictionary()->ValueAtPut(entry, *new_cell);
15477
15478     Handle<Object> hole = global->GetIsolate()->factory()->the_hole_value();
15479     PropertyCell::SetValueInferType(cell, hole);
15480   }
15481 }
15482
15483
15484 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
15485     Handle<GlobalObject> global, Handle<Name> name) {
15486   DCHECK(!global->HasFastProperties());
15487   int entry = global->property_dictionary()->FindEntry(name);
15488   if (entry == NameDictionary::kNotFound) {
15489     Isolate* isolate = global->GetIsolate();
15490     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCellWithHole();
15491     PropertyDetails details(NONE, DATA, 0);
15492     details = details.AsDeleted();
15493     Handle<NameDictionary> dictionary = NameDictionary::Add(
15494         handle(global->property_dictionary()), name, cell, details);
15495     global->set_properties(*dictionary);
15496     return cell;
15497   } else {
15498     Object* value = global->property_dictionary()->ValueAt(entry);
15499     DCHECK(value->IsPropertyCell());
15500     return handle(PropertyCell::cast(value));
15501   }
15502 }
15503
15504
15505 // This class is used for looking up two character strings in the string table.
15506 // If we don't have a hit we don't want to waste much time so we unroll the
15507 // string hash calculation loop here for speed.  Doesn't work if the two
15508 // characters form a decimal integer, since such strings have a different hash
15509 // algorithm.
15510 class TwoCharHashTableKey : public HashTableKey {
15511  public:
15512   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
15513     : c1_(c1), c2_(c2) {
15514     // Char 1.
15515     uint32_t hash = seed;
15516     hash += c1;
15517     hash += hash << 10;
15518     hash ^= hash >> 6;
15519     // Char 2.
15520     hash += c2;
15521     hash += hash << 10;
15522     hash ^= hash >> 6;
15523     // GetHash.
15524     hash += hash << 3;
15525     hash ^= hash >> 11;
15526     hash += hash << 15;
15527     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
15528     hash_ = hash;
15529 #ifdef DEBUG
15530     // If this assert fails then we failed to reproduce the two-character
15531     // version of the string hashing algorithm above.  One reason could be
15532     // that we were passed two digits as characters, since the hash
15533     // algorithm is different in that case.
15534     uint16_t chars[2] = {c1, c2};
15535     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
15536     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
15537     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
15538 #endif
15539   }
15540
15541   bool IsMatch(Object* o) OVERRIDE {
15542     if (!o->IsString()) return false;
15543     String* other = String::cast(o);
15544     if (other->length() != 2) return false;
15545     if (other->Get(0) != c1_) return false;
15546     return other->Get(1) == c2_;
15547   }
15548
15549   uint32_t Hash() OVERRIDE { return hash_; }
15550   uint32_t HashForObject(Object* key) OVERRIDE {
15551     if (!key->IsString()) return 0;
15552     return String::cast(key)->Hash();
15553   }
15554
15555   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
15556     // The TwoCharHashTableKey is only used for looking in the string
15557     // table, not for adding to it.
15558     UNREACHABLE();
15559     return MaybeHandle<Object>().ToHandleChecked();
15560   }
15561
15562  private:
15563   uint16_t c1_;
15564   uint16_t c2_;
15565   uint32_t hash_;
15566 };
15567
15568
15569 MaybeHandle<String> StringTable::InternalizeStringIfExists(
15570     Isolate* isolate,
15571     Handle<String> string) {
15572   if (string->IsInternalizedString()) {
15573     return string;
15574   }
15575   return LookupStringIfExists(isolate, string);
15576 }
15577
15578
15579 MaybeHandle<String> StringTable::LookupStringIfExists(
15580     Isolate* isolate,
15581     Handle<String> string) {
15582   Handle<StringTable> string_table = isolate->factory()->string_table();
15583   InternalizedStringKey key(string);
15584   int entry = string_table->FindEntry(&key);
15585   if (entry == kNotFound) {
15586     return MaybeHandle<String>();
15587   } else {
15588     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15589     DCHECK(StringShape(*result).IsInternalized());
15590     return result;
15591   }
15592 }
15593
15594
15595 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
15596     Isolate* isolate,
15597     uint16_t c1,
15598     uint16_t c2) {
15599   Handle<StringTable> string_table = isolate->factory()->string_table();
15600   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
15601   int entry = string_table->FindEntry(&key);
15602   if (entry == kNotFound) {
15603     return MaybeHandle<String>();
15604   } else {
15605     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15606     DCHECK(StringShape(*result).IsInternalized());
15607     return result;
15608   }
15609 }
15610
15611
15612 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
15613                                                    int expected) {
15614   Handle<StringTable> table = isolate->factory()->string_table();
15615   // We need a key instance for the virtual hash function.
15616   InternalizedStringKey dummy_key(Handle<String>::null());
15617   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
15618   isolate->factory()->set_string_table(table);
15619 }
15620
15621
15622 Handle<String> StringTable::LookupString(Isolate* isolate,
15623                                          Handle<String> string) {
15624   InternalizedStringKey key(string);
15625   return LookupKey(isolate, &key);
15626 }
15627
15628
15629 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
15630   Handle<StringTable> table = isolate->factory()->string_table();
15631   int entry = table->FindEntry(key);
15632
15633   // String already in table.
15634   if (entry != kNotFound) {
15635     return handle(String::cast(table->KeyAt(entry)), isolate);
15636   }
15637
15638   // Adding new string. Grow table if needed.
15639   table = StringTable::EnsureCapacity(table, 1, key);
15640
15641   // Create string object.
15642   Handle<Object> string = key->AsHandle(isolate);
15643   // There must be no attempts to internalize strings that could throw
15644   // InvalidStringLength error.
15645   CHECK(!string.is_null());
15646
15647   // Add the new string and return it along with the string table.
15648   entry = table->FindInsertionEntry(key->Hash());
15649   table->set(EntryToIndex(entry), *string);
15650   table->ElementAdded();
15651
15652   isolate->factory()->set_string_table(table);
15653   return Handle<String>::cast(string);
15654 }
15655
15656
15657 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
15658                                              Handle<Context> context,
15659                                              LanguageMode language_mode) {
15660   Isolate* isolate = GetIsolate();
15661   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15662   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
15663   int entry = FindEntry(&key);
15664   if (entry == kNotFound) return isolate->factory()->undefined_value();
15665   int index = EntryToIndex(entry);
15666   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
15667   return Handle<Object>(get(index + 1), isolate);
15668 }
15669
15670
15671 Handle<Object> CompilationCacheTable::LookupEval(
15672     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
15673     LanguageMode language_mode, int scope_position) {
15674   Isolate* isolate = GetIsolate();
15675   // Cache key is the tuple (source, outer shared function info, scope position)
15676   // to unambiguously identify the context chain the cached eval code assumes.
15677   StringSharedKey key(src, outer_info, language_mode, scope_position);
15678   int entry = FindEntry(&key);
15679   if (entry == kNotFound) return isolate->factory()->undefined_value();
15680   int index = EntryToIndex(entry);
15681   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
15682   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15683 }
15684
15685
15686 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
15687                                                    JSRegExp::Flags flags) {
15688   Isolate* isolate = GetIsolate();
15689   DisallowHeapAllocation no_allocation;
15690   RegExpKey key(src, flags);
15691   int entry = FindEntry(&key);
15692   if (entry == kNotFound) return isolate->factory()->undefined_value();
15693   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15694 }
15695
15696
15697 Handle<CompilationCacheTable> CompilationCacheTable::Put(
15698     Handle<CompilationCacheTable> cache, Handle<String> src,
15699     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
15700   Isolate* isolate = cache->GetIsolate();
15701   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15702   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
15703   {
15704     Handle<Object> k = key.AsHandle(isolate);
15705     DisallowHeapAllocation no_allocation_scope;
15706     int entry = cache->FindEntry(&key);
15707     if (entry != kNotFound) {
15708       cache->set(EntryToIndex(entry), *k);
15709       cache->set(EntryToIndex(entry) + 1, *value);
15710       return cache;
15711     }
15712   }
15713
15714   cache = EnsureCapacity(cache, 1, &key);
15715   int entry = cache->FindInsertionEntry(key.Hash());
15716   Handle<Object> k =
15717       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
15718   cache->set(EntryToIndex(entry), *k);
15719   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
15720   cache->ElementAdded();
15721   return cache;
15722 }
15723
15724
15725 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
15726     Handle<CompilationCacheTable> cache, Handle<String> src,
15727     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
15728     int scope_position) {
15729   Isolate* isolate = cache->GetIsolate();
15730   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
15731   {
15732     Handle<Object> k = key.AsHandle(isolate);
15733     DisallowHeapAllocation no_allocation_scope;
15734     int entry = cache->FindEntry(&key);
15735     if (entry != kNotFound) {
15736       cache->set(EntryToIndex(entry), *k);
15737       cache->set(EntryToIndex(entry) + 1, *value);
15738       return cache;
15739     }
15740   }
15741
15742   cache = EnsureCapacity(cache, 1, &key);
15743   int entry = cache->FindInsertionEntry(key.Hash());
15744   Handle<Object> k =
15745       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
15746   cache->set(EntryToIndex(entry), *k);
15747   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
15748   cache->ElementAdded();
15749   return cache;
15750 }
15751
15752
15753 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
15754       Handle<CompilationCacheTable> cache, Handle<String> src,
15755       JSRegExp::Flags flags, Handle<FixedArray> value) {
15756   RegExpKey key(src, flags);
15757   cache = EnsureCapacity(cache, 1, &key);
15758   int entry = cache->FindInsertionEntry(key.Hash());
15759   // We store the value in the key slot, and compare the search key
15760   // to the stored value with a custon IsMatch function during lookups.
15761   cache->set(EntryToIndex(entry), *value);
15762   cache->set(EntryToIndex(entry) + 1, *value);
15763   cache->ElementAdded();
15764   return cache;
15765 }
15766
15767
15768 void CompilationCacheTable::Age() {
15769   DisallowHeapAllocation no_allocation;
15770   Object* the_hole_value = GetHeap()->the_hole_value();
15771   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15772     int entry_index = EntryToIndex(entry);
15773     int value_index = entry_index + 1;
15774
15775     if (get(entry_index)->IsNumber()) {
15776       Smi* count = Smi::cast(get(value_index));
15777       count = Smi::FromInt(count->value() - 1);
15778       if (count->value() == 0) {
15779         NoWriteBarrierSet(this, entry_index, the_hole_value);
15780         NoWriteBarrierSet(this, value_index, the_hole_value);
15781         ElementRemoved();
15782       } else {
15783         NoWriteBarrierSet(this, value_index, count);
15784       }
15785     } else if (get(entry_index)->IsFixedArray()) {
15786       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
15787       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
15788         NoWriteBarrierSet(this, entry_index, the_hole_value);
15789         NoWriteBarrierSet(this, value_index, the_hole_value);
15790         ElementRemoved();
15791       }
15792     }
15793   }
15794 }
15795
15796
15797 void CompilationCacheTable::Remove(Object* value) {
15798   DisallowHeapAllocation no_allocation;
15799   Object* the_hole_value = GetHeap()->the_hole_value();
15800   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15801     int entry_index = EntryToIndex(entry);
15802     int value_index = entry_index + 1;
15803     if (get(value_index) == value) {
15804       NoWriteBarrierSet(this, entry_index, the_hole_value);
15805       NoWriteBarrierSet(this, value_index, the_hole_value);
15806       ElementRemoved();
15807     }
15808   }
15809   return;
15810 }
15811
15812
15813 // StringsKey used for HashTable where key is array of internalized strings.
15814 class StringsKey : public HashTableKey {
15815  public:
15816   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
15817
15818   bool IsMatch(Object* strings) OVERRIDE {
15819     FixedArray* o = FixedArray::cast(strings);
15820     int len = strings_->length();
15821     if (o->length() != len) return false;
15822     for (int i = 0; i < len; i++) {
15823       if (o->get(i) != strings_->get(i)) return false;
15824     }
15825     return true;
15826   }
15827
15828   uint32_t Hash() OVERRIDE { return HashForObject(*strings_); }
15829
15830   uint32_t HashForObject(Object* obj) OVERRIDE {
15831     FixedArray* strings = FixedArray::cast(obj);
15832     int len = strings->length();
15833     uint32_t hash = 0;
15834     for (int i = 0; i < len; i++) {
15835       hash ^= String::cast(strings->get(i))->Hash();
15836     }
15837     return hash;
15838   }
15839
15840   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE { return strings_; }
15841
15842  private:
15843   Handle<FixedArray> strings_;
15844 };
15845
15846
15847 template<typename Derived, typename Shape, typename Key>
15848 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
15849     Isolate* isolate,
15850     int at_least_space_for,
15851     PretenureFlag pretenure) {
15852   DCHECK(0 <= at_least_space_for);
15853   Handle<Derived> dict = DerivedHashTable::New(isolate,
15854                                                at_least_space_for,
15855                                                USE_DEFAULT_MINIMUM_CAPACITY,
15856                                                pretenure);
15857
15858   // Initialize the next enumeration index.
15859   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15860   return dict;
15861 }
15862
15863
15864 template <typename Derived, typename Shape, typename Key>
15865 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
15866     Handle<Derived> dictionary) {
15867   Factory* factory = dictionary->GetIsolate()->factory();
15868   int length = dictionary->NumberOfElements();
15869
15870   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
15871   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
15872
15873   // Fill both the iteration order array and the enumeration order array
15874   // with property details.
15875   int capacity = dictionary->Capacity();
15876   int pos = 0;
15877   for (int i = 0; i < capacity; i++) {
15878     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15879       int index = dictionary->DetailsAt(i).dictionary_index();
15880       iteration_order->set(pos, Smi::FromInt(i));
15881       enumeration_order->set(pos, Smi::FromInt(index));
15882       pos++;
15883     }
15884   }
15885   DCHECK(pos == length);
15886
15887   // Sort the arrays wrt. enumeration order.
15888   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
15889   return iteration_order;
15890 }
15891
15892
15893 template <typename Derived, typename Shape, typename Key>
15894 Handle<FixedArray>
15895 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
15896     Handle<Derived> dictionary) {
15897   int length = dictionary->NumberOfElements();
15898
15899   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
15900   DCHECK(iteration_order->length() == length);
15901
15902   // Iterate over the dictionary using the enumeration order and update
15903   // the dictionary with new enumeration indices.
15904   for (int i = 0; i < length; i++) {
15905     int index = Smi::cast(iteration_order->get(i))->value();
15906     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
15907
15908     int enum_index = PropertyDetails::kInitialIndex + i;
15909
15910     PropertyDetails details = dictionary->DetailsAt(index);
15911     PropertyDetails new_details =
15912         PropertyDetails(details.attributes(), details.type(), enum_index);
15913     dictionary->DetailsAtPut(index, new_details);
15914   }
15915
15916   // Set the next enumeration index.
15917   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
15918   return iteration_order;
15919 }
15920
15921
15922 template<typename Derived, typename Shape, typename Key>
15923 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
15924     Handle<Derived> dictionary, int n, Key key) {
15925   // Check whether there are enough enumeration indices to add n elements.
15926   if (Shape::kIsEnumerable &&
15927       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
15928     // If not, we generate new indices for the properties.
15929     GenerateNewEnumerationIndices(dictionary);
15930   }
15931   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
15932 }
15933
15934
15935 template <typename Derived, typename Shape, typename Key>
15936 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
15937     Handle<Derived> dictionary, int entry) {
15938   Factory* factory = dictionary->GetIsolate()->factory();
15939   PropertyDetails details = dictionary->DetailsAt(entry);
15940   if (!details.IsConfigurable()) return factory->false_value();
15941
15942   dictionary->SetEntry(
15943       entry, factory->the_hole_value(), factory->the_hole_value());
15944   dictionary->ElementRemoved();
15945   return factory->true_value();
15946 }
15947
15948
15949 template<typename Derived, typename Shape, typename Key>
15950 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
15951     Handle<Derived> dictionary, Key key, Handle<Object> value) {
15952   int entry = dictionary->FindEntry(key);
15953
15954   // If the entry is present set the value;
15955   if (entry != Dictionary::kNotFound) {
15956     dictionary->ValueAtPut(entry, *value);
15957     return dictionary;
15958   }
15959
15960   // Check whether the dictionary should be extended.
15961   dictionary = EnsureCapacity(dictionary, 1, key);
15962 #ifdef DEBUG
15963   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
15964 #endif
15965   PropertyDetails details(NONE, DATA, 0);
15966
15967   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15968   return dictionary;
15969 }
15970
15971
15972 template<typename Derived, typename Shape, typename Key>
15973 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
15974     Handle<Derived> dictionary,
15975     Key key,
15976     Handle<Object> value,
15977     PropertyDetails details) {
15978   // Valdate key is absent.
15979   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
15980   // Check whether the dictionary should be extended.
15981   dictionary = EnsureCapacity(dictionary, 1, key);
15982
15983   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15984   return dictionary;
15985 }
15986
15987
15988 // Add a key, value pair to the dictionary.
15989 template<typename Derived, typename Shape, typename Key>
15990 void Dictionary<Derived, Shape, Key>::AddEntry(
15991     Handle<Derived> dictionary,
15992     Key key,
15993     Handle<Object> value,
15994     PropertyDetails details,
15995     uint32_t hash) {
15996   // Compute the key object.
15997   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15998
15999   uint32_t entry = dictionary->FindInsertionEntry(hash);
16000   // Insert element at empty or deleted entry
16001   if (!details.IsDeleted() &&
16002       details.dictionary_index() == 0 &&
16003       Shape::kIsEnumerable) {
16004     // Assign an enumeration index to the property and update
16005     // SetNextEnumerationIndex.
16006     int index = dictionary->NextEnumerationIndex();
16007     details = PropertyDetails(details.attributes(), details.type(), index);
16008     dictionary->SetNextEnumerationIndex(index + 1);
16009   }
16010   dictionary->SetEntry(entry, k, value, details);
16011   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
16012           dictionary->KeyAt(entry)->IsName()));
16013   dictionary->ElementAdded();
16014 }
16015
16016
16017 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
16018   DisallowHeapAllocation no_allocation;
16019   // If the dictionary requires slow elements an element has already
16020   // been added at a high index.
16021   if (requires_slow_elements()) return;
16022   // Check if this index is high enough that we should require slow
16023   // elements.
16024   if (key > kRequiresSlowElementsLimit) {
16025     set_requires_slow_elements();
16026     return;
16027   }
16028   // Update max key value.
16029   Object* max_index_object = get(kMaxNumberKeyIndex);
16030   if (!max_index_object->IsSmi() || max_number_key() < key) {
16031     FixedArray::set(kMaxNumberKeyIndex,
16032                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
16033   }
16034 }
16035
16036
16037 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
16038     Handle<SeededNumberDictionary> dictionary,
16039     uint32_t key,
16040     Handle<Object> value,
16041     PropertyDetails details) {
16042   dictionary->UpdateMaxNumberKey(key);
16043   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
16044   return Add(dictionary, key, value, details);
16045 }
16046
16047
16048 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
16049     Handle<UnseededNumberDictionary> dictionary,
16050     uint32_t key,
16051     Handle<Object> value) {
16052   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
16053   return Add(dictionary, key, value, PropertyDetails(NONE, DATA, 0));
16054 }
16055
16056
16057 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
16058     Handle<SeededNumberDictionary> dictionary,
16059     uint32_t key,
16060     Handle<Object> value) {
16061   dictionary->UpdateMaxNumberKey(key);
16062   return AtPut(dictionary, key, value);
16063 }
16064
16065
16066 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
16067     Handle<UnseededNumberDictionary> dictionary,
16068     uint32_t key,
16069     Handle<Object> value) {
16070   return AtPut(dictionary, key, value);
16071 }
16072
16073
16074 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
16075     Handle<SeededNumberDictionary> dictionary,
16076     uint32_t key,
16077     Handle<Object> value,
16078     PropertyDetails details) {
16079   int entry = dictionary->FindEntry(key);
16080   if (entry == kNotFound) {
16081     return AddNumberEntry(dictionary, key, value, details);
16082   }
16083   // Preserve enumeration index.
16084   details = PropertyDetails(details.attributes(),
16085                             details.type(),
16086                             dictionary->DetailsAt(entry).dictionary_index());
16087   Handle<Object> object_key =
16088       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
16089   dictionary->SetEntry(entry, object_key, value, details);
16090   return dictionary;
16091 }
16092
16093
16094 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
16095     Handle<UnseededNumberDictionary> dictionary,
16096     uint32_t key,
16097     Handle<Object> value) {
16098   int entry = dictionary->FindEntry(key);
16099   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
16100   Handle<Object> object_key =
16101       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
16102   dictionary->SetEntry(entry, object_key, value);
16103   return dictionary;
16104 }
16105
16106
16107
16108 template<typename Derived, typename Shape, typename Key>
16109 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
16110     PropertyAttributes filter) {
16111   int capacity = DerivedHashTable::Capacity();
16112   int result = 0;
16113   for (int i = 0; i < capacity; i++) {
16114     Object* k = DerivedHashTable::KeyAt(i);
16115     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
16116       PropertyDetails details = DetailsAt(i);
16117       if (details.IsDeleted()) continue;
16118       PropertyAttributes attr = details.attributes();
16119       if ((attr & filter) == 0) result++;
16120     }
16121   }
16122   return result;
16123 }
16124
16125
16126 template<typename Derived, typename Shape, typename Key>
16127 int Dictionary<Derived, Shape, Key>::NumberOfEnumElements() {
16128   return NumberOfElementsFilterAttributes(
16129       static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
16130 }
16131
16132
16133 template <typename Derived, typename Shape, typename Key>
16134 bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
16135   int capacity = DerivedHashTable::Capacity();
16136   for (int i = 0; i < capacity; i++) {
16137     Object* k = DerivedHashTable::KeyAt(i);
16138     if (DerivedHashTable::IsKey(k) && !FilterKey(k, NONE)) {
16139       PropertyDetails details = DetailsAt(i);
16140       if (details.IsDeleted()) continue;
16141       if (details.type() == ACCESSOR_CONSTANT) return true;
16142       PropertyAttributes attr = details.attributes();
16143       if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true;
16144     }
16145   }
16146   return false;
16147 }
16148
16149
16150 template <typename Derived, typename Shape, typename Key>
16151 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
16152     FixedArray* storage, PropertyAttributes filter,
16153     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
16154   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
16155   int capacity = DerivedHashTable::Capacity();
16156   int index = 0;
16157   for (int i = 0; i < capacity; i++) {
16158      Object* k = DerivedHashTable::KeyAt(i);
16159      if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
16160        PropertyDetails details = DetailsAt(i);
16161        if (details.IsDeleted()) continue;
16162        PropertyAttributes attr = details.attributes();
16163        if ((attr & filter) == 0) storage->set(index++, k);
16164      }
16165   }
16166   if (sort_mode == Dictionary::SORTED) {
16167     storage->SortPairs(storage, index);
16168   }
16169   DCHECK(storage->length() >= index);
16170 }
16171
16172
16173 struct EnumIndexComparator {
16174   explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
16175   bool operator() (Smi* a, Smi* b) {
16176     PropertyDetails da(dict->DetailsAt(a->value()));
16177     PropertyDetails db(dict->DetailsAt(b->value()));
16178     return da.dictionary_index() < db.dictionary_index();
16179   }
16180   NameDictionary* dict;
16181 };
16182
16183
16184 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
16185   int length = storage->length();
16186   int capacity = Capacity();
16187   int properties = 0;
16188   for (int i = 0; i < capacity; i++) {
16189      Object* k = KeyAt(i);
16190      if (IsKey(k) && !k->IsSymbol()) {
16191        PropertyDetails details = DetailsAt(i);
16192        if (details.IsDeleted() || details.IsDontEnum()) continue;
16193        storage->set(properties, Smi::FromInt(i));
16194        properties++;
16195        if (properties == length) break;
16196      }
16197   }
16198   CHECK_EQ(length, properties);
16199   EnumIndexComparator cmp(this);
16200   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
16201   std::sort(start, start + length, cmp);
16202   for (int i = 0; i < length; i++) {
16203     int index = Smi::cast(storage->get(i))->value();
16204     storage->set(i, KeyAt(index));
16205   }
16206 }
16207
16208
16209 template<typename Derived, typename Shape, typename Key>
16210 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
16211     FixedArray* storage,
16212     int index,
16213     PropertyAttributes filter,
16214     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
16215   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
16216   int capacity = DerivedHashTable::Capacity();
16217   for (int i = 0; i < capacity; i++) {
16218     Object* k = DerivedHashTable::KeyAt(i);
16219     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
16220       PropertyDetails details = DetailsAt(i);
16221       if (details.IsDeleted()) continue;
16222       PropertyAttributes attr = details.attributes();
16223       if ((attr & filter) == 0) storage->set(index++, k);
16224     }
16225   }
16226   if (sort_mode == Dictionary::SORTED) {
16227     storage->SortPairs(storage, index);
16228   }
16229   DCHECK(storage->length() >= index);
16230 }
16231
16232
16233 // Backwards lookup (slow).
16234 template<typename Derived, typename Shape, typename Key>
16235 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
16236   int capacity = DerivedHashTable::Capacity();
16237   for (int i = 0; i < capacity; i++) {
16238     Object* k =  DerivedHashTable::KeyAt(i);
16239     if (Dictionary::IsKey(k)) {
16240       Object* e = ValueAt(i);
16241       if (e->IsPropertyCell()) {
16242         e = PropertyCell::cast(e)->value();
16243       }
16244       if (e == value) return k;
16245     }
16246   }
16247   Heap* heap = Dictionary::GetHeap();
16248   return heap->undefined_value();
16249 }
16250
16251
16252 Object* ObjectHashTable::Lookup(Handle<Object> key) {
16253   DisallowHeapAllocation no_gc;
16254   DCHECK(IsKey(*key));
16255
16256   // If the object does not have an identity hash, it was never used as a key.
16257   Object* hash = key->GetHash();
16258   if (hash->IsUndefined()) {
16259     return GetHeap()->the_hole_value();
16260   }
16261   int entry = FindEntry(key);
16262   if (entry == kNotFound) return GetHeap()->the_hole_value();
16263   return get(EntryToIndex(entry) + 1);
16264 }
16265
16266
16267 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
16268                                              Handle<Object> key,
16269                                              Handle<Object> value) {
16270   DCHECK(table->IsKey(*key));
16271   DCHECK(!value->IsTheHole());
16272
16273   Isolate* isolate = table->GetIsolate();
16274
16275   // Make sure the key object has an identity hash code.
16276   Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
16277
16278   int entry = table->FindEntry(key);
16279
16280   // Key is already in table, just overwrite value.
16281   if (entry != kNotFound) {
16282     table->set(EntryToIndex(entry) + 1, *value);
16283     return table;
16284   }
16285
16286   // Check whether the hash table should be extended.
16287   table = EnsureCapacity(table, 1, key);
16288   table->AddEntry(table->FindInsertionEntry(hash->value()),
16289                   *key,
16290                   *value);
16291   return table;
16292 }
16293
16294
16295 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
16296                                                 Handle<Object> key,
16297                                                 bool* was_present) {
16298   DCHECK(table->IsKey(*key));
16299
16300   Object* hash = key->GetHash();
16301   if (hash->IsUndefined()) {
16302     *was_present = false;
16303     return table;
16304   }
16305
16306   int entry = table->FindEntry(key);
16307   if (entry == kNotFound) {
16308     *was_present = false;
16309     return table;
16310   }
16311
16312   *was_present = true;
16313   table->RemoveEntry(entry);
16314   return Shrink(table, key);
16315 }
16316
16317
16318 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
16319   set(EntryToIndex(entry), key);
16320   set(EntryToIndex(entry) + 1, value);
16321   ElementAdded();
16322 }
16323
16324
16325 void ObjectHashTable::RemoveEntry(int entry) {
16326   set_the_hole(EntryToIndex(entry));
16327   set_the_hole(EntryToIndex(entry) + 1);
16328   ElementRemoved();
16329 }
16330
16331
16332 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
16333   DisallowHeapAllocation no_gc;
16334   DCHECK(IsKey(*key));
16335   int entry = FindEntry(key);
16336   if (entry == kNotFound) return GetHeap()->the_hole_value();
16337   return get(EntryToValueIndex(entry));
16338 }
16339
16340
16341 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
16342                                          Handle<HeapObject> key,
16343                                          Handle<HeapObject> value) {
16344   DCHECK(table->IsKey(*key));
16345   int entry = table->FindEntry(key);
16346   // Key is already in table, just overwrite value.
16347   if (entry != kNotFound) {
16348     table->set(EntryToValueIndex(entry), *value);
16349     return table;
16350   }
16351
16352   Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
16353
16354   // Check whether the hash table should be extended.
16355   table = EnsureCapacity(table, 1, key, TENURED);
16356
16357   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
16358   return table;
16359 }
16360
16361
16362 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
16363                              Handle<HeapObject> value) {
16364   DisallowHeapAllocation no_allocation;
16365   set(EntryToIndex(entry), *key_cell);
16366   set(EntryToValueIndex(entry), *value);
16367   ElementAdded();
16368 }
16369
16370
16371 template<class Derived, class Iterator, int entrysize>
16372 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
16373     Isolate* isolate, int capacity, PretenureFlag pretenure) {
16374   // Capacity must be a power of two, since we depend on being able
16375   // to divide and multiple by 2 (kLoadFactor) to derive capacity
16376   // from number of buckets. If we decide to change kLoadFactor
16377   // to something other than 2, capacity should be stored as another
16378   // field of this object.
16379   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
16380   if (capacity > kMaxCapacity) {
16381     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
16382   }
16383   int num_buckets = capacity / kLoadFactor;
16384   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
16385       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
16386   backing_store->set_map_no_write_barrier(
16387       isolate->heap()->ordered_hash_table_map());
16388   Handle<Derived> table = Handle<Derived>::cast(backing_store);
16389   for (int i = 0; i < num_buckets; ++i) {
16390     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
16391   }
16392   table->SetNumberOfBuckets(num_buckets);
16393   table->SetNumberOfElements(0);
16394   table->SetNumberOfDeletedElements(0);
16395   return table;
16396 }
16397
16398
16399 template<class Derived, class Iterator, int entrysize>
16400 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
16401     Handle<Derived> table) {
16402   DCHECK(!table->IsObsolete());
16403
16404   int nof = table->NumberOfElements();
16405   int nod = table->NumberOfDeletedElements();
16406   int capacity = table->Capacity();
16407   if ((nof + nod) < capacity) return table;
16408   // Don't need to grow if we can simply clear out deleted entries instead.
16409   // Note that we can't compact in place, though, so we always allocate
16410   // a new table.
16411   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
16412 }
16413
16414
16415 template<class Derived, class Iterator, int entrysize>
16416 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
16417     Handle<Derived> table) {
16418   DCHECK(!table->IsObsolete());
16419
16420   int nof = table->NumberOfElements();
16421   int capacity = table->Capacity();
16422   if (nof >= (capacity >> 2)) return table;
16423   return Rehash(table, capacity / 2);
16424 }
16425
16426
16427 template<class Derived, class Iterator, int entrysize>
16428 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
16429     Handle<Derived> table) {
16430   DCHECK(!table->IsObsolete());
16431
16432   Handle<Derived> new_table =
16433       Allocate(table->GetIsolate(),
16434                kMinCapacity,
16435                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16436
16437   table->SetNextTable(*new_table);
16438   table->SetNumberOfDeletedElements(kClearedTableSentinel);
16439
16440   return new_table;
16441 }
16442
16443
16444 template<class Derived, class Iterator, int entrysize>
16445 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Remove(
16446     Handle<Derived> table, Handle<Object> key, bool* was_present) {
16447   int entry = table->FindEntry(key);
16448   if (entry == kNotFound) {
16449     *was_present = false;
16450     return table;
16451   }
16452   *was_present = true;
16453   table->RemoveEntry(entry);
16454   return Shrink(table);
16455 }
16456
16457
16458 template<class Derived, class Iterator, int entrysize>
16459 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
16460     Handle<Derived> table, int new_capacity) {
16461   DCHECK(!table->IsObsolete());
16462
16463   Handle<Derived> new_table =
16464       Allocate(table->GetIsolate(),
16465                new_capacity,
16466                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16467   int nof = table->NumberOfElements();
16468   int nod = table->NumberOfDeletedElements();
16469   int new_buckets = new_table->NumberOfBuckets();
16470   int new_entry = 0;
16471   int removed_holes_index = 0;
16472
16473   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
16474     Object* key = table->KeyAt(old_entry);
16475     if (key->IsTheHole()) {
16476       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
16477       continue;
16478     }
16479
16480     Object* hash = key->GetHash();
16481     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
16482     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
16483     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
16484     int new_index = new_table->EntryToIndex(new_entry);
16485     int old_index = table->EntryToIndex(old_entry);
16486     for (int i = 0; i < entrysize; ++i) {
16487       Object* value = table->get(old_index + i);
16488       new_table->set(new_index + i, value);
16489     }
16490     new_table->set(new_index + kChainOffset, chain_entry);
16491     ++new_entry;
16492   }
16493
16494   DCHECK_EQ(nod, removed_holes_index);
16495
16496   new_table->SetNumberOfElements(nof);
16497   table->SetNextTable(*new_table);
16498
16499   return new_table;
16500 }
16501
16502
16503 template <class Derived, class Iterator, int entrysize>
16504 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16505     Handle<Object> key, int hash) {
16506   DCHECK(!IsObsolete());
16507
16508   DisallowHeapAllocation no_gc;
16509   DCHECK(!key->IsTheHole());
16510   for (int entry = HashToEntry(hash); entry != kNotFound;
16511        entry = ChainAt(entry)) {
16512     Object* candidate = KeyAt(entry);
16513     if (candidate->SameValueZero(*key))
16514       return entry;
16515   }
16516   return kNotFound;
16517 }
16518
16519
16520 template <class Derived, class Iterator, int entrysize>
16521 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16522     Handle<Object> key) {
16523   DisallowHeapAllocation no_gc;
16524   Object* hash = key->GetHash();
16525   if (!hash->IsSmi()) return kNotFound;
16526   return FindEntry(key, Smi::cast(hash)->value());
16527 }
16528
16529
16530 template <class Derived, class Iterator, int entrysize>
16531 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
16532   DCHECK(!IsObsolete());
16533
16534   int entry = UsedCapacity();
16535   int bucket = HashToBucket(hash);
16536   int index = EntryToIndex(entry);
16537   Object* chain_entry = get(kHashTableStartIndex + bucket);
16538   set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
16539   set(index + kChainOffset, chain_entry);
16540   SetNumberOfElements(NumberOfElements() + 1);
16541   return index;
16542 }
16543
16544
16545 template<class Derived, class Iterator, int entrysize>
16546 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
16547   DCHECK(!IsObsolete());
16548
16549   int index = EntryToIndex(entry);
16550   for (int i = 0; i < entrysize; ++i) {
16551     set_the_hole(index + i);
16552   }
16553   SetNumberOfElements(NumberOfElements() - 1);
16554   SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
16555 }
16556
16557
16558 template Handle<OrderedHashSet>
16559 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
16560     Isolate* isolate, int capacity, PretenureFlag pretenure);
16561
16562 template Handle<OrderedHashSet>
16563 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
16564     Handle<OrderedHashSet> table);
16565
16566 template Handle<OrderedHashSet>
16567 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
16568     Handle<OrderedHashSet> table);
16569
16570 template Handle<OrderedHashSet>
16571 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
16572     Handle<OrderedHashSet> table);
16573
16574 template Handle<OrderedHashSet>
16575 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Remove(
16576     Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
16577
16578 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16579     Handle<Object> key, int hash);
16580 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16581     Handle<Object> key);
16582
16583 template int
16584 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
16585
16586 template void
16587 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
16588
16589
16590 template Handle<OrderedHashMap>
16591 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
16592     Isolate* isolate, int capacity, PretenureFlag pretenure);
16593
16594 template Handle<OrderedHashMap>
16595 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
16596     Handle<OrderedHashMap> table);
16597
16598 template Handle<OrderedHashMap>
16599 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
16600     Handle<OrderedHashMap> table);
16601
16602 template Handle<OrderedHashMap>
16603 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
16604     Handle<OrderedHashMap> table);
16605
16606 template Handle<OrderedHashMap>
16607 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Remove(
16608     Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
16609
16610 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16611     Handle<Object> key, int hash);
16612 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16613     Handle<Object> key);
16614
16615 template int
16616 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
16617
16618 template void
16619 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
16620
16621
16622 bool OrderedHashSet::Contains(Handle<Object> key) {
16623   return FindEntry(key) != kNotFound;
16624 }
16625
16626
16627 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
16628                                            Handle<Object> key) {
16629   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16630   if (table->FindEntry(key, hash) != kNotFound) return table;
16631
16632   table = EnsureGrowable(table);
16633
16634   int index = table->AddEntry(hash);
16635   table->set(index, *key);
16636   return table;
16637 }
16638
16639
16640 Object* OrderedHashMap::Lookup(Handle<Object> key) {
16641   DisallowHeapAllocation no_gc;
16642   int entry = FindEntry(key);
16643   if (entry == kNotFound) return GetHeap()->the_hole_value();
16644   return ValueAt(entry);
16645 }
16646
16647
16648 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table,
16649                                            Handle<Object> key,
16650                                            Handle<Object> value) {
16651   DCHECK(!key->IsTheHole());
16652
16653   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16654   int entry = table->FindEntry(key, hash);
16655
16656   if (entry != kNotFound) {
16657     table->set(table->EntryToIndex(entry) + kValueOffset, *value);
16658     return table;
16659   }
16660
16661   table = EnsureGrowable(table);
16662
16663   int index = table->AddEntry(hash);
16664   table->set(index, *key);
16665   table->set(index + kValueOffset, *value);
16666   return table;
16667 }
16668
16669
16670 template<class Derived, class TableType>
16671 void OrderedHashTableIterator<Derived, TableType>::Transition() {
16672   DisallowHeapAllocation no_allocation;
16673   TableType* table = TableType::cast(this->table());
16674   if (!table->IsObsolete()) return;
16675
16676   int index = Smi::cast(this->index())->value();
16677   while (table->IsObsolete()) {
16678     TableType* next_table = table->NextTable();
16679
16680     if (index > 0) {
16681       int nod = table->NumberOfDeletedElements();
16682
16683       if (nod == TableType::kClearedTableSentinel) {
16684         index = 0;
16685       } else {
16686         int old_index = index;
16687         for (int i = 0; i < nod; ++i) {
16688           int removed_index = table->RemovedIndexAt(i);
16689           if (removed_index >= old_index) break;
16690           --index;
16691         }
16692       }
16693     }
16694
16695     table = next_table;
16696   }
16697
16698   set_table(table);
16699   set_index(Smi::FromInt(index));
16700 }
16701
16702
16703 template<class Derived, class TableType>
16704 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
16705   DisallowHeapAllocation no_allocation;
16706   if (this->table()->IsUndefined()) return false;
16707
16708   Transition();
16709
16710   TableType* table = TableType::cast(this->table());
16711   int index = Smi::cast(this->index())->value();
16712   int used_capacity = table->UsedCapacity();
16713
16714   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
16715     index++;
16716   }
16717
16718   set_index(Smi::FromInt(index));
16719
16720   if (index < used_capacity) return true;
16721
16722   set_table(GetHeap()->undefined_value());
16723   return false;
16724 }
16725
16726
16727 template<class Derived, class TableType>
16728 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
16729   DisallowHeapAllocation no_allocation;
16730   if (HasMore()) {
16731     FixedArray* array = FixedArray::cast(value_array->elements());
16732     static_cast<Derived*>(this)->PopulateValueArray(array);
16733     MoveNext();
16734     return Smi::cast(kind());
16735   }
16736   return Smi::FromInt(0);
16737 }
16738
16739
16740 template Smi*
16741 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
16742     JSArray* value_array);
16743
16744 template bool
16745 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
16746
16747 template void
16748 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
16749
16750 template Object*
16751 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
16752
16753 template void
16754 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
16755
16756
16757 template Smi*
16758 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
16759     JSArray* value_array);
16760
16761 template bool
16762 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
16763
16764 template void
16765 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
16766
16767 template Object*
16768 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
16769
16770 template void
16771 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
16772
16773
16774 // Check if there is a break point at this code position.
16775 bool DebugInfo::HasBreakPoint(int code_position) {
16776   // Get the break point info object for this code position.
16777   Object* break_point_info = GetBreakPointInfo(code_position);
16778
16779   // If there is no break point info object or no break points in the break
16780   // point info object there is no break point at this code position.
16781   if (break_point_info->IsUndefined()) return false;
16782   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
16783 }
16784
16785
16786 // Get the break point info object for this code position.
16787 Object* DebugInfo::GetBreakPointInfo(int code_position) {
16788   // Find the index of the break point info object for this code position.
16789   int index = GetBreakPointInfoIndex(code_position);
16790
16791   // Return the break point info object if any.
16792   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
16793   return BreakPointInfo::cast(break_points()->get(index));
16794 }
16795
16796
16797 // Clear a break point at the specified code position.
16798 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
16799                                 int code_position,
16800                                 Handle<Object> break_point_object) {
16801   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16802                                   debug_info->GetIsolate());
16803   if (break_point_info->IsUndefined()) return;
16804   BreakPointInfo::ClearBreakPoint(
16805       Handle<BreakPointInfo>::cast(break_point_info),
16806       break_point_object);
16807 }
16808
16809
16810 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
16811                               int code_position,
16812                               int source_position,
16813                               int statement_position,
16814                               Handle<Object> break_point_object) {
16815   Isolate* isolate = debug_info->GetIsolate();
16816   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16817                                   isolate);
16818   if (!break_point_info->IsUndefined()) {
16819     BreakPointInfo::SetBreakPoint(
16820         Handle<BreakPointInfo>::cast(break_point_info),
16821         break_point_object);
16822     return;
16823   }
16824
16825   // Adding a new break point for a code position which did not have any
16826   // break points before. Try to find a free slot.
16827   int index = kNoBreakPointInfo;
16828   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16829     if (debug_info->break_points()->get(i)->IsUndefined()) {
16830       index = i;
16831       break;
16832     }
16833   }
16834   if (index == kNoBreakPointInfo) {
16835     // No free slot - extend break point info array.
16836     Handle<FixedArray> old_break_points =
16837         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
16838     Handle<FixedArray> new_break_points =
16839         isolate->factory()->NewFixedArray(
16840             old_break_points->length() +
16841             DebugInfo::kEstimatedNofBreakPointsInFunction);
16842
16843     debug_info->set_break_points(*new_break_points);
16844     for (int i = 0; i < old_break_points->length(); i++) {
16845       new_break_points->set(i, old_break_points->get(i));
16846     }
16847     index = old_break_points->length();
16848   }
16849   DCHECK(index != kNoBreakPointInfo);
16850
16851   // Allocate new BreakPointInfo object and set the break point.
16852   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
16853       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
16854   new_break_point_info->set_code_position(Smi::FromInt(code_position));
16855   new_break_point_info->set_source_position(Smi::FromInt(source_position));
16856   new_break_point_info->
16857       set_statement_position(Smi::FromInt(statement_position));
16858   new_break_point_info->set_break_point_objects(
16859       isolate->heap()->undefined_value());
16860   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
16861   debug_info->break_points()->set(index, *new_break_point_info);
16862 }
16863
16864
16865 // Get the break point objects for a code position.
16866 Object* DebugInfo::GetBreakPointObjects(int code_position) {
16867   Object* break_point_info = GetBreakPointInfo(code_position);
16868   if (break_point_info->IsUndefined()) {
16869     return GetHeap()->undefined_value();
16870   }
16871   return BreakPointInfo::cast(break_point_info)->break_point_objects();
16872 }
16873
16874
16875 // Get the total number of break points.
16876 int DebugInfo::GetBreakPointCount() {
16877   if (break_points()->IsUndefined()) return 0;
16878   int count = 0;
16879   for (int i = 0; i < break_points()->length(); i++) {
16880     if (!break_points()->get(i)->IsUndefined()) {
16881       BreakPointInfo* break_point_info =
16882           BreakPointInfo::cast(break_points()->get(i));
16883       count += break_point_info->GetBreakPointCount();
16884     }
16885   }
16886   return count;
16887 }
16888
16889
16890 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
16891                                       Handle<Object> break_point_object) {
16892   Heap* heap = debug_info->GetHeap();
16893   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
16894   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16895     if (!debug_info->break_points()->get(i)->IsUndefined()) {
16896       Handle<BreakPointInfo> break_point_info =
16897           Handle<BreakPointInfo>(BreakPointInfo::cast(
16898               debug_info->break_points()->get(i)));
16899       if (BreakPointInfo::HasBreakPointObject(break_point_info,
16900                                               break_point_object)) {
16901         return *break_point_info;
16902       }
16903     }
16904   }
16905   return heap->undefined_value();
16906 }
16907
16908
16909 // Find the index of the break point info object for the specified code
16910 // position.
16911 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16912   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16913   for (int i = 0; i < break_points()->length(); i++) {
16914     if (!break_points()->get(i)->IsUndefined()) {
16915       BreakPointInfo* break_point_info =
16916           BreakPointInfo::cast(break_points()->get(i));
16917       if (break_point_info->code_position()->value() == code_position) {
16918         return i;
16919       }
16920     }
16921   }
16922   return kNoBreakPointInfo;
16923 }
16924
16925
16926 // Remove the specified break point object.
16927 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
16928                                      Handle<Object> break_point_object) {
16929   Isolate* isolate = break_point_info->GetIsolate();
16930   // If there are no break points just ignore.
16931   if (break_point_info->break_point_objects()->IsUndefined()) return;
16932   // If there is a single break point clear it if it is the same.
16933   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16934     if (break_point_info->break_point_objects() == *break_point_object) {
16935       break_point_info->set_break_point_objects(
16936           isolate->heap()->undefined_value());
16937     }
16938     return;
16939   }
16940   // If there are multiple break points shrink the array
16941   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
16942   Handle<FixedArray> old_array =
16943       Handle<FixedArray>(
16944           FixedArray::cast(break_point_info->break_point_objects()));
16945   Handle<FixedArray> new_array =
16946       isolate->factory()->NewFixedArray(old_array->length() - 1);
16947   int found_count = 0;
16948   for (int i = 0; i < old_array->length(); i++) {
16949     if (old_array->get(i) == *break_point_object) {
16950       DCHECK(found_count == 0);
16951       found_count++;
16952     } else {
16953       new_array->set(i - found_count, old_array->get(i));
16954     }
16955   }
16956   // If the break point was found in the list change it.
16957   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16958 }
16959
16960
16961 // Add the specified break point object.
16962 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16963                                    Handle<Object> break_point_object) {
16964   Isolate* isolate = break_point_info->GetIsolate();
16965
16966   // If there was no break point objects before just set it.
16967   if (break_point_info->break_point_objects()->IsUndefined()) {
16968     break_point_info->set_break_point_objects(*break_point_object);
16969     return;
16970   }
16971   // If the break point object is the same as before just ignore.
16972   if (break_point_info->break_point_objects() == *break_point_object) return;
16973   // If there was one break point object before replace with array.
16974   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16975     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16976     array->set(0, break_point_info->break_point_objects());
16977     array->set(1, *break_point_object);
16978     break_point_info->set_break_point_objects(*array);
16979     return;
16980   }
16981   // If there was more than one break point before extend array.
16982   Handle<FixedArray> old_array =
16983       Handle<FixedArray>(
16984           FixedArray::cast(break_point_info->break_point_objects()));
16985   Handle<FixedArray> new_array =
16986       isolate->factory()->NewFixedArray(old_array->length() + 1);
16987   for (int i = 0; i < old_array->length(); i++) {
16988     // If the break point was there before just ignore.
16989     if (old_array->get(i) == *break_point_object) return;
16990     new_array->set(i, old_array->get(i));
16991   }
16992   // Add the new break point.
16993   new_array->set(old_array->length(), *break_point_object);
16994   break_point_info->set_break_point_objects(*new_array);
16995 }
16996
16997
16998 bool BreakPointInfo::HasBreakPointObject(
16999     Handle<BreakPointInfo> break_point_info,
17000     Handle<Object> break_point_object) {
17001   // No break point.
17002   if (break_point_info->break_point_objects()->IsUndefined()) return false;
17003   // Single break point.
17004   if (!break_point_info->break_point_objects()->IsFixedArray()) {
17005     return break_point_info->break_point_objects() == *break_point_object;
17006   }
17007   // Multiple break points.
17008   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
17009   for (int i = 0; i < array->length(); i++) {
17010     if (array->get(i) == *break_point_object) {
17011       return true;
17012     }
17013   }
17014   return false;
17015 }
17016
17017
17018 // Get the number of break points.
17019 int BreakPointInfo::GetBreakPointCount() {
17020   // No break point.
17021   if (break_point_objects()->IsUndefined()) return 0;
17022   // Single break point.
17023   if (!break_point_objects()->IsFixedArray()) return 1;
17024   // Multiple break points.
17025   return FixedArray::cast(break_point_objects())->length();
17026 }
17027
17028
17029 Object* JSDate::GetField(Object* object, Smi* index) {
17030   return JSDate::cast(object)->DoGetField(
17031       static_cast<FieldIndex>(index->value()));
17032 }
17033
17034
17035 Object* JSDate::DoGetField(FieldIndex index) {
17036   DCHECK(index != kDateValue);
17037
17038   DateCache* date_cache = GetIsolate()->date_cache();
17039
17040   if (index < kFirstUncachedField) {
17041     Object* stamp = cache_stamp();
17042     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
17043       // Since the stamp is not NaN, the value is also not NaN.
17044       int64_t local_time_ms =
17045           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
17046       SetCachedFields(local_time_ms, date_cache);
17047     }
17048     switch (index) {
17049       case kYear: return year();
17050       case kMonth: return month();
17051       case kDay: return day();
17052       case kWeekday: return weekday();
17053       case kHour: return hour();
17054       case kMinute: return min();
17055       case kSecond: return sec();
17056       default: UNREACHABLE();
17057     }
17058   }
17059
17060   if (index >= kFirstUTCField) {
17061     return GetUTCField(index, value()->Number(), date_cache);
17062   }
17063
17064   double time = value()->Number();
17065   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
17066
17067   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
17068   int days = DateCache::DaysFromTime(local_time_ms);
17069
17070   if (index == kDays) return Smi::FromInt(days);
17071
17072   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
17073   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
17074   DCHECK(index == kTimeInDay);
17075   return Smi::FromInt(time_in_day_ms);
17076 }
17077
17078
17079 Object* JSDate::GetUTCField(FieldIndex index,
17080                             double value,
17081                             DateCache* date_cache) {
17082   DCHECK(index >= kFirstUTCField);
17083
17084   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
17085
17086   int64_t time_ms = static_cast<int64_t>(value);
17087
17088   if (index == kTimezoneOffset) {
17089     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
17090   }
17091
17092   int days = DateCache::DaysFromTime(time_ms);
17093
17094   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
17095
17096   if (index <= kDayUTC) {
17097     int year, month, day;
17098     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
17099     if (index == kYearUTC) return Smi::FromInt(year);
17100     if (index == kMonthUTC) return Smi::FromInt(month);
17101     DCHECK(index == kDayUTC);
17102     return Smi::FromInt(day);
17103   }
17104
17105   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
17106   switch (index) {
17107     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
17108     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
17109     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
17110     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
17111     case kDaysUTC: return Smi::FromInt(days);
17112     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
17113     default: UNREACHABLE();
17114   }
17115
17116   UNREACHABLE();
17117   return NULL;
17118 }
17119
17120
17121 void JSDate::SetValue(Object* value, bool is_value_nan) {
17122   set_value(value);
17123   if (is_value_nan) {
17124     HeapNumber* nan = GetIsolate()->heap()->nan_value();
17125     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
17126     set_year(nan, SKIP_WRITE_BARRIER);
17127     set_month(nan, SKIP_WRITE_BARRIER);
17128     set_day(nan, SKIP_WRITE_BARRIER);
17129     set_hour(nan, SKIP_WRITE_BARRIER);
17130     set_min(nan, SKIP_WRITE_BARRIER);
17131     set_sec(nan, SKIP_WRITE_BARRIER);
17132     set_weekday(nan, SKIP_WRITE_BARRIER);
17133   } else {
17134     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
17135   }
17136 }
17137
17138
17139 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
17140   int days = DateCache::DaysFromTime(local_time_ms);
17141   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
17142   int year, month, day;
17143   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
17144   int weekday = date_cache->Weekday(days);
17145   int hour = time_in_day_ms / (60 * 60 * 1000);
17146   int min = (time_in_day_ms / (60 * 1000)) % 60;
17147   int sec = (time_in_day_ms / 1000) % 60;
17148   set_cache_stamp(date_cache->stamp());
17149   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
17150   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
17151   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
17152   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
17153   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
17154   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
17155   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
17156 }
17157
17158
17159 void JSArrayBuffer::Neuter() {
17160   CHECK(is_neuterable());
17161   CHECK(is_external());
17162   set_backing_store(NULL);
17163   set_byte_length(Smi::FromInt(0));
17164 }
17165
17166
17167 void JSArrayBufferView::NeuterView() {
17168   CHECK(JSArrayBuffer::cast(buffer())->is_neuterable());
17169   set_byte_offset(Smi::FromInt(0));
17170   set_byte_length(Smi::FromInt(0));
17171 }
17172
17173
17174 void JSDataView::Neuter() {
17175   NeuterView();
17176 }
17177
17178
17179 void JSTypedArray::Neuter() {
17180   NeuterView();
17181   set_length(Smi::FromInt(0));
17182   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
17183 }
17184
17185
17186 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
17187   switch (elements_kind) {
17188 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
17189     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
17190
17191     TYPED_ARRAYS(TYPED_ARRAY_CASE)
17192 #undef TYPED_ARRAY_CASE
17193
17194     default:
17195       UNREACHABLE();
17196       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
17197   }
17198 }
17199
17200
17201 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
17202     Handle<JSTypedArray> typed_array) {
17203
17204   Handle<Map> map(typed_array->map());
17205   Isolate* isolate = typed_array->GetIsolate();
17206
17207   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
17208
17209   Handle<Map> new_map = Map::TransitionElementsTo(
17210           map,
17211           FixedToExternalElementsKind(map->elements_kind()));
17212
17213   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
17214   Handle<FixedTypedArrayBase> fixed_typed_array(
17215       FixedTypedArrayBase::cast(typed_array->elements()));
17216   Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
17217       fixed_typed_array->DataSize(), false);
17218   memcpy(buffer->backing_store(),
17219          fixed_typed_array->DataPtr(),
17220          fixed_typed_array->DataSize());
17221   Handle<ExternalArray> new_elements =
17222       isolate->factory()->NewExternalArray(
17223           fixed_typed_array->length(), typed_array->type(),
17224           static_cast<uint8_t*>(buffer->backing_store()));
17225
17226   buffer->set_weak_first_view(*typed_array);
17227   DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
17228   typed_array->set_buffer(*buffer);
17229   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
17230
17231   return buffer;
17232 }
17233
17234
17235 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
17236   Handle<Object> result(buffer(), GetIsolate());
17237   if (*result != Smi::FromInt(0)) {
17238     DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
17239     return Handle<JSArrayBuffer>::cast(result);
17240   }
17241   Handle<JSTypedArray> self(this);
17242   return MaterializeArrayBuffer(self);
17243 }
17244
17245
17246 HeapType* PropertyCell::type() {
17247   return static_cast<HeapType*>(type_raw());
17248 }
17249
17250
17251 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) {
17252   DCHECK(IsPropertyCell());
17253   set_type_raw(type, ignored);
17254 }
17255
17256
17257 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell,
17258                                            Handle<Object> value) {
17259   Isolate* isolate = cell->GetIsolate();
17260   Handle<HeapType> old_type(cell->type(), isolate);
17261   Handle<HeapType> new_type = HeapType::Constant(value, isolate);
17262
17263   if (new_type->Is(old_type)) return old_type;
17264
17265   cell->dependent_code()->DeoptimizeDependentCodeGroup(
17266       isolate, DependentCode::kPropertyCellChangedGroup);
17267
17268   if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
17269     return new_type;
17270   }
17271
17272   return HeapType::Any(isolate);
17273 }
17274
17275
17276 Handle<Object> PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
17277                                                Handle<Object> value) {
17278   // Heuristic: if a small-ish string is stored in a previously uninitialized
17279   // property cell, internalize it.
17280   const int kMaxLengthForInternalization = 200;
17281   if ((cell->type()->Is(HeapType::None()) ||
17282        cell->type()->Is(HeapType::Undefined())) &&
17283       value->IsString()) {
17284     auto string = Handle<String>::cast(value);
17285     if (string->length() <= kMaxLengthForInternalization &&
17286         !string->map()->is_undetectable()) {
17287       value = cell->GetIsolate()->factory()->InternalizeString(string);
17288     }
17289   }
17290   cell->set_value(*value);
17291   if (!HeapType::Any()->Is(cell->type())) {
17292     Handle<HeapType> new_type = UpdatedType(cell, value);
17293     cell->set_type(*new_type);
17294   }
17295   return value;
17296 }
17297
17298
17299 // static
17300 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
17301                                                CompilationInfo* info) {
17302   Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17303       handle(cell->dependent_code(), info->isolate()),
17304       DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17305   if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17306   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17307       cell, info->zone());
17308 }
17309
17310 } }  // namespace v8::internal